From 11b0624a7b8afeb448243209880a5cab74c02e23 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 17 Mar 2022 10:20:19 +0100 Subject: [PATCH 1/9] header api: add curl_easy_header and curl_easy_nextheader Add test 1940 to 1946 to verify. Closes #8593 --- docs/EXPERIMENTAL.md | 3 +- docs/examples/Makefile.inc | 1 + docs/examples/headerapi.c | 79 +++ docs/libcurl/Makefile.inc | 4 +- docs/libcurl/curl_easy_header.3 | 151 ++++++ docs/libcurl/curl_easy_nextheader.3 | 96 ++++ docs/libcurl/opts/CURLINFO_CONTENT_TYPE.3 | 3 +- docs/libcurl/opts/CURLOPT_HEADERFUNCTION.3 | 3 +- docs/libcurl/symbols-in-versions | 533 +++++++++++---------- include/curl/Makefile.am | 4 +- include/curl/curl.h | 1 + include/curl/header.h | 64 +++ lib/Makefile.inc | 2 + lib/headers.c | 319 ++++++++++++ lib/headers.h | 53 ++ lib/http.c | 12 +- lib/http2.c | 8 +- lib/http_chunks.c | 4 +- lib/http_proxy.c | 8 +- lib/http_proxy.h | 3 +- lib/multi.c | 1 - lib/sendf.c | 25 +- lib/sendf.h | 10 +- lib/transfer.c | 4 + lib/url.c | 2 + lib/urldata.h | 3 + tests/data/Makefile.inc | 3 +- tests/data/test1940 | 55 +++ tests/data/test1941 | 75 +++ tests/data/test1942 | 65 +++ tests/data/test1943 | 61 +++ tests/data/test1944 | 63 +++ tests/data/test1945 | 75 +++ tests/data/test1946 | 65 +++ tests/libtest/Makefile.inc | 16 +- tests/libtest/lib1940.c | 116 +++++ tests/libtest/lib1945.c | 75 +++ tests/symbol-scan.pl | 29 +- 38 files changed, 1793 insertions(+), 301 deletions(-) create mode 100644 docs/examples/headerapi.c create mode 100644 docs/libcurl/curl_easy_header.3 create mode 100644 docs/libcurl/curl_easy_nextheader.3 create mode 100644 include/curl/header.h create mode 100644 lib/headers.c create mode 100644 lib/headers.h create mode 100644 tests/data/test1940 create mode 100644 tests/data/test1941 create mode 100644 tests/data/test1942 create mode 100644 tests/data/test1943 create mode 100644 tests/data/test1944 create mode 100644 tests/data/test1945 create mode 100644 tests/data/test1946 create mode 100644 tests/libtest/lib1940.c create mode 100644 tests/libtest/lib1945.c diff --git a/docs/EXPERIMENTAL.md b/docs/EXPERIMENTAL.md index ce9a1b8e85e529..06deb5fc93494b 100644 --- a/docs/EXPERIMENTAL.md +++ b/docs/EXPERIMENTAL.md @@ -20,4 +20,5 @@ Experimental support in curl means: - The Hyper HTTP backend - HTTP/3 support and options - - CURLSSLOPT_NATIVE_CA (No configure option, feature built in when supported) + - `CURLSSLOPT_NATIVE_CA` (No configure option, feature built in when supported) + - The headers API: `curl_easy_header` and `curl_easy_nextheader`. diff --git a/docs/examples/Makefile.inc b/docs/examples/Makefile.inc index 039bec13cbb7f0..cc66a9baf333f8 100644 --- a/docs/examples/Makefile.inc +++ b/docs/examples/Makefile.inc @@ -44,6 +44,7 @@ check_PROGRAMS = \ getinmemory \ getredirect \ getreferrer \ + headerapi \ http-post \ http2-download \ http2-pushinmemory \ diff --git a/docs/examples/headerapi.c b/docs/examples/headerapi.c new file mode 100644 index 00000000000000..a6266e90ffcd4f --- /dev/null +++ b/docs/examples/headerapi.c @@ -0,0 +1,79 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + * Extract headers post transfer with the header API + * + */ +#include +#include + +static size_t write_cb(char *data, size_t n, size_t l, void *userp) +{ + /* take care of the data here, ignored in this example */ + (void)data; + (void)userp; + return n*l; +} + +int main(void) +{ + CURL *curl; + + curl = curl_easy_init(); + if(curl) { + CURLcode res; + struct curl_header *header; + curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); + /* example.com is redirected, so we tell libcurl to follow redirection */ + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + + /* this example just ignores the content */ + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); + + /* 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)); + + if(CURLHE_OK == curl_easy_header(curl, "Content-Type", 0, CURLH_HEADER, + -1, &header)) + printf("Got content-type: %s\n", header->value); + + printf("All server headers:\n"); + { + struct curl_header *h; + struct curl_header *prev = NULL; + do { + h = curl_easy_nextheader(curl, CURLH_HEADER, -1, prev); + if(h) + printf(" %s: %s (%u)\n", h->name, h->value, (int)h->amount); + prev = h; + } while(h); + + } + /* always cleanup */ + curl_easy_cleanup(curl); + } + return 0; +} diff --git a/docs/libcurl/Makefile.inc b/docs/libcurl/Makefile.inc index 706d8b6baf46e0..d314f95a3c3b02 100644 --- a/docs/libcurl/Makefile.inc +++ b/docs/libcurl/Makefile.inc @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 2008 - 2021, Daniel Stenberg, , et al. +# Copyright (C) 2008 - 2022, Daniel Stenberg, , et al. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms @@ -27,7 +27,9 @@ man_MANS = \ curl_easy_duphandle.3 \ curl_easy_escape.3 \ curl_easy_getinfo.3 \ + curl_easy_header.3 \ curl_easy_init.3 \ + curl_easy_nextheader.3 \ curl_easy_option_by_id.3 \ curl_easy_option_by_name.3 \ curl_easy_option_next.3 \ diff --git a/docs/libcurl/curl_easy_header.3 b/docs/libcurl/curl_easy_header.3 new file mode 100644 index 00000000000000..241187d579984f --- /dev/null +++ b/docs/libcurl/curl_easy_header.3 @@ -0,0 +1,151 @@ +.\" ************************************************************************** +.\" * _ _ ____ _ +.\" * Project ___| | | | _ \| | +.\" * / __| | | | |_) | | +.\" * | (__| |_| | _ <| |___ +.\" * \___|\___/|_| \_\_____| +.\" * +.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. +.\" * +.\" * This software is licensed as described in the file COPYING, which +.\" * you should have received as part of this distribution. The terms +.\" * are also available at https://curl.se/docs/copyright.html. +.\" * +.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell +.\" * copies of the Software, and permit persons to whom the Software is +.\" * furnished to do so, under the terms of the COPYING file. +.\" * +.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +.\" * KIND, either express or implied. +.\" * +.\" ************************************************************************** +.TH curl_easy_header 3 "13 March 2022" "libcurl 7.83.0" "libcurl Manual" +.SH NAME +curl_easy_header - get a HTTP header +.SH SYNOPSIS +.nf +#include + +CURLHcode curl_easy_header(CURL *easy, + const char *name, + size_t index, + unsigned int origin, + int request, + struct curl_header **hout); +.SH DESCRIPTION +EXPERIMENTAL feature! + +\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. + +\fIindex\fP 0 means asking for the first instance of the header. If the +returned header struct has \fBamount\fP set larger than 1, it means there are +more instances of the same header name available to get. Asking for a too big +index makes \fBCURLHE_BADINDEX\fP get returned. + +The \fIorigin\fP argument is for specifying which headers to receive, as a +single HTTP transfer might provide headers from several different places and +they may then have different importance to the user and headers using the same +name might be used. The \fIorigin\fP is a bitmask for what header sources you +want. See the descriptions below. + +The \fIrequest\fP argument tells libcurl from which request you want headers +from. A single transfer might consist of a series of HTTP requests and this +argument lets you specify which particular invidual request you want the +headers from. 0 being the first request and then the number increases for +further redirects or when multi-state authentication is used. Passing in -1 is +a shortcut to "the last" request in the series, independently of the actual +amount of requests used. + +libcurl stores and provides the actually used "correct" headers. If for +example two headers with the same name arrive and the latter overrides the +former, then only the latter will be provided. If the first header survives +the second, then only the first one will be provided. An application using +this API does not have to bother about multiple headers used wrongly. + +The memory for the returned struct is associated with the easy handle and +subsequent calls to \fIcurl_easy_header(3)\fP will clobber the struct used in +the previous calls for the same easy handle. Applications need to copy the +data if it wants to keep it around. The memory used for the struct gets freed +with calling \fIcurl_easy_cleanup(3)\fP of the easy handle. + +The first line in a HTTP response is called the status line. It is not +considered a header by this function. Headers are the "name: value" lines +following the status. + +This function can be used before (all) headers have been received and is fine +to call from within libcurl callbacks. It will always return the state of the +headers at the time it is called. +.SH "The header struct" +.nf +struct curl_header { + char *name; + char *value; + size_t amount; + size_t index; + unsigned int origin; + void *anchor; +}; +.fi + +The data \fBname\fP field points to, will be the same as the requested name +but it might have a different case. + +The data \fBvalue\fP field points to, comes exactly as delivered over the +network but with leading and trailing whitespace and newlines stripped +off. The `value` data is nul-terminated. + +\fBamount\fP is how many headers using this name that exist, within the origin +and request scope asked for. + +\fBindex\fP is the zero based entry number of this particular header, which in +case this header was used more than once in the requested scope can be larger +than 0 but is always less than \fBamount\fP. + +The \fBorigin\fP field in the "curl_header" struct has one of the origin bits +set, indicating where from the header originates. At the time of this writing, +there are 5 bits with defined use. The undocumented 27 remaining bits are +reserved for future use and must not be assumed to have any particular value. + +\fBanchor\fP is a private handle used by libcurl internals. Do not modify. +.SH ORIGINS +.IP CURLH_HEADER +The header arrived as a header from the server. +.IP CURLH_TRAILER +The header arrived as a trailer. A header that arrives after the body. +.IP CURLH_CONNECT +The header arrived in a CONNECT response. A CONNECT request is being done to +setup a transfer "through" a HTTP(S) proxy. +.IP CURLH_1XX +The header arrived in a HTTP 1xx response. A 1xx response is an "intermediate" +response that might happen before the "real" response. +.IP CURLH_PSUEDO +The header is a HTTP/2 or HTTP/3 pseudo header +.SH EXAMPLE +.nf +struct curl_header *type; +CURLHcode h = + curl_easy_header(easy, "Content-Type", 0, CURLH_HEADER, -1, &type); +.fi +.SH AVAILABILITY +Added in 7.83.0 +.SH RETURN VALUE +This function returns a CURLHcode indiciating 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 disbled in the build. +.SH "SEE ALSO" +.BR curl_easy_nextheader "(3), " curl_easy_perform "(3), " +.BR CURLOPT_HEADERFUNCTION "(3), " CURLINFO_CONTENT_TYPE "(3) " diff --git a/docs/libcurl/curl_easy_nextheader.3 b/docs/libcurl/curl_easy_nextheader.3 new file mode 100644 index 00000000000000..50ddd2d89a3f01 --- /dev/null +++ b/docs/libcurl/curl_easy_nextheader.3 @@ -0,0 +1,96 @@ +.\" ************************************************************************** +.\" * _ _ ____ _ +.\" * Project ___| | | | _ \| | +.\" * / __| | | | |_) | | +.\" * | (__| |_| | _ <| |___ +.\" * \___|\___/|_| \_\_____| +.\" * +.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. +.\" * +.\" * This software is licensed as described in the file COPYING, which +.\" * you should have received as part of this distribution. The terms +.\" * are also available at https://curl.se/docs/copyright.html. +.\" * +.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell +.\" * copies of the Software, and permit persons to whom the Software is +.\" * furnished to do so, under the terms of the COPYING file. +.\" * +.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +.\" * KIND, either express or implied. +.\" * +.\" ************************************************************************** +.TH curl_easy_nextheader 3 "13 March 2022" "libcurl 7.83.0" "libcurl Manual" +.SH NAME +curl_easy_nextheader - get the next HTTP header +.SH SYNOPSIS +.nf +#include + +struct curl_header *curl_easy_nextheader(CURL *easy, + unsigned int origin, + int request, + struct curl_header *prev); +.fi +.SH DESCRIPTION +EXPERIMENTAL feature! + +This function lets an application iterate over all previously received HTTP +headers. + +The \fIorigin\fP argument is for specifying which headers to receive, as a +single HTTP transfer might provide headers from several different places and +they may then have different importance to the user and headers using the same +name might be used. The \fIorigin\fP is a bitmask for what header sources you +want. See the \fIcurl_easy_header(3)\fP man page for the origin descriptions. + +The \fIrequest\fP argument tells libcurl from which request you want headers +from. A single transfer might consist of a series of HTTP requests and this +argument lets you specify which particular invidual request you want the +headers from. 0 being the first request and then the number increases for +further redirects or when multi-state authentication is used. Passing in -1 is +a shortcut to "the last" request in the series, independently of the actual +amount of requests used. + +It is suggested that you pass in the same \fBorigin\fP and \fBrequest\fP when +iterating over a range of headers as changing the value mid-loop might give +you unexpected results. + +If \fIprev\fP is NULL, this function returns a pointer to the first header +stored within the given scope (origin + request). + +If \fIprev\fP is a pointer to a previously returned header struct, +\fIcurl_easy_nextheader(3)\fP returns a pointer the next header stored within +the given scope. This way, an application can iterate over all availble +headers. + +The memory for the struct this points to, is owned and managed by libcurl and +is associated with the easy handle. Applications must copy the data if they +want it to survive subsequent API calls or the life-time of the easy handle. +.SH EXAMPLE +.nf +struct curl_header *prev = NULL; +struct curl_header *h; + +/* extract the normal headers from the first request */ +while((h = curl_easy_nextheader(easy, CURLH_HEADER, 0, prev))) { + print "%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); + prev = h; +} +.fi +.SH AVAILABILITY +Added in 7.83.0 +.SH RETURN VALUE +This function returns the next header, or NULL when there are no more +(matching) headers or an error occurred. + +If this function returns NULL when \fIprev\fP was set to NULL, then there are +no headers available within the scope to return. +.SH "SEE ALSO" +.BR curl_easy_header "(3), " curl_easy_perform "(3) " diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.3 b/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.3 index 59190f84838bd6..b629ac1dab6a9b 100644 --- a/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.3 +++ b/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.3 @@ -5,7 +5,7 @@ .\" * | (__| |_| | _ <| |___ .\" * \___|\___/|_| \_\_____| .\" * -.\" * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. +.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. .\" * .\" * This software is licensed as described in the file COPYING, which .\" * you should have received as part of this distribution. The terms @@ -65,3 +65,4 @@ Added in 7.9.4 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 CURLOPT_HEADERFUNCTION "(3), " curl_easy_header "(3) " diff --git a/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.3 b/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.3 index 392727eecf2674..506226bb789530 100644 --- a/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.3 +++ b/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.3 @@ -5,7 +5,7 @@ .\" * | (__| |_| | _ <| |___ .\" * \___|\___/|_| \_\_____| .\" * -.\" * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. +.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. .\" * .\" * This software is licensed as described in the file COPYING, which .\" * you should have received as part of this distribution. The terms @@ -117,4 +117,5 @@ Always .SH RETURN VALUE Returns CURLE_OK .SH "SEE ALSO" +.BR curl_easy_header "(3), " .BR CURLOPT_HEADERDATA "(3), " CURLOPT_WRITEFUNCTION "(3), " diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions index 5e683455e67de6..698bde1a7c1fbc 100644 --- a/docs/libcurl/symbols-in-versions +++ b/docs/libcurl/symbols-in-versions @@ -12,12 +12,183 @@ Name Introduced Deprecated Last +CURL_CHUNK_BGN_FUNC_FAIL 7.21.0 +CURL_CHUNK_BGN_FUNC_OK 7.21.0 +CURL_CHUNK_BGN_FUNC_SKIP 7.21.0 +CURL_CHUNK_END_FUNC_FAIL 7.21.0 +CURL_CHUNK_END_FUNC_OK 7.21.0 +CURL_CSELECT_ERR 7.16.3 +CURL_CSELECT_IN 7.16.3 +CURL_CSELECT_OUT 7.16.3 +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 +CURL_ERROR_SIZE 7.1 +CURL_FNMATCHFUNC_FAIL 7.21.0 +CURL_FNMATCHFUNC_MATCH 7.21.0 +CURL_FNMATCHFUNC_NOMATCH 7.21.0 +CURL_FORMADD_DISABLED 7.12.1 7.56.0 +CURL_FORMADD_ILLEGAL_ARRAY 7.9.8 7.56.0 +CURL_FORMADD_INCOMPLETE 7.9.8 7.56.0 +CURL_FORMADD_MEMORY 7.9.8 7.56.0 +CURL_FORMADD_NULL 7.9.8 7.56.0 +CURL_FORMADD_OK 7.9.8 7.56.0 +CURL_FORMADD_OPTION_TWICE 7.9.8 7.56.0 +CURL_FORMADD_UNKNOWN_OPTION 7.9.8 7.56.0 +CURL_GLOBAL_ACK_EINTR 7.30.0 +CURL_GLOBAL_ALL 7.8 +CURL_GLOBAL_DEFAULT 7.8 +CURL_GLOBAL_NOTHING 7.8 +CURL_GLOBAL_SSL 7.8 +CURL_GLOBAL_WIN32 7.8.1 +CURL_HET_DEFAULT 7.59.0 +CURL_HTTP_VERSION_1_0 7.9.1 +CURL_HTTP_VERSION_1_1 7.9.1 +CURL_HTTP_VERSION_2 7.43.0 +CURL_HTTP_VERSION_2_0 7.33.0 +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_NONE 7.9.1 +CURL_HTTPPOST_BUFFER 7.46.0 +CURL_HTTPPOST_CALLBACK 7.46.0 +CURL_HTTPPOST_FILENAME 7.46.0 +CURL_HTTPPOST_LARGE 7.46.0 +CURL_HTTPPOST_PTRBUFFER 7.46.0 +CURL_HTTPPOST_PTRCONTENTS 7.46.0 +CURL_HTTPPOST_PTRNAME 7.46.0 +CURL_HTTPPOST_READFILE 7.46.0 +CURL_IPRESOLVE_V4 7.10.8 +CURL_IPRESOLVE_V6 7.10.8 +CURL_IPRESOLVE_WHATEVER 7.10.8 +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_NONE 7.10.3 +CURL_LOCK_DATA_PSL 7.61.0 +CURL_LOCK_DATA_SHARE 7.10.4 +CURL_LOCK_DATA_SSL_SESSION 7.10.3 +CURL_LOCK_TYPE_CONNECT 7.10 - 7.10.2 +CURL_LOCK_TYPE_COOKIE 7.10 - 7.10.2 +CURL_LOCK_TYPE_DNS 7.10 - 7.10.2 +CURL_LOCK_TYPE_NONE 7.10 - 7.10.2 +CURL_LOCK_TYPE_SSL_SESSION 7.10 - 7.10.2 +CURL_MAX_HTTP_HEADER 7.19.7 +CURL_MAX_READ_SIZE 7.53.0 +CURL_MAX_WRITE_SIZE 7.9.7 +CURL_NETRC_IGNORED 7.9.8 +CURL_NETRC_OPTIONAL 7.9.8 +CURL_NETRC_REQUIRED 7.9.8 +CURL_POLL_IN 7.14.0 +CURL_POLL_INOUT 7.14.0 +CURL_POLL_NONE 7.14.0 +CURL_POLL_OUT 7.14.0 +CURL_POLL_REMOVE 7.14.0 +CURL_PREREQFUNC_ABORT 7.79.0 +CURL_PREREQFUNC_OK 7.79.0 +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_PUSH_DENY 7.44.0 +CURL_PUSH_ERROROUT 7.72.0 +CURL_PUSH_OK 7.44.0 +CURL_READFUNC_ABORT 7.12.1 +CURL_READFUNC_PAUSE 7.18.0 +CURL_REDIR_GET_ALL 7.19.1 +CURL_REDIR_POST_301 7.19.1 +CURL_REDIR_POST_302 7.19.1 +CURL_REDIR_POST_303 7.25.1 +CURL_REDIR_POST_ALL 7.19.1 +CURL_RTSPREQ_ANNOUNCE 7.20.0 +CURL_RTSPREQ_DESCRIBE 7.20.0 +CURL_RTSPREQ_GET_PARAMETER 7.20.0 +CURL_RTSPREQ_NONE 7.20.0 +CURL_RTSPREQ_OPTIONS 7.20.0 +CURL_RTSPREQ_PAUSE 7.20.0 +CURL_RTSPREQ_PLAY 7.20.0 +CURL_RTSPREQ_RECEIVE 7.20.0 +CURL_RTSPREQ_RECORD 7.20.0 +CURL_RTSPREQ_SET_PARAMETER 7.20.0 +CURL_RTSPREQ_SETUP 7.20.0 +CURL_RTSPREQ_TEARDOWN 7.20.0 +CURL_SEEKFUNC_CANTSEEK 7.19.5 +CURL_SEEKFUNC_FAIL 7.19.5 +CURL_SEEKFUNC_OK 7.19.5 +CURL_SOCKET_BAD 7.14.0 +CURL_SOCKET_TIMEOUT 7.14.0 +CURL_SOCKOPT_ALREADY_CONNECTED 7.21.5 +CURL_SOCKOPT_ERROR 7.21.5 +CURL_SOCKOPT_OK 7.21.5 +CURL_SSLVERSION_DEFAULT 7.9.2 +CURL_SSLVERSION_MAX_DEFAULT 7.54.0 +CURL_SSLVERSION_MAX_NONE 7.54.0 +CURL_SSLVERSION_MAX_TLSv1_0 7.54.0 +CURL_SSLVERSION_MAX_TLSv1_1 7.54.0 +CURL_SSLVERSION_MAX_TLSv1_2 7.54.0 +CURL_SSLVERSION_MAX_TLSv1_3 7.54.0 +CURL_SSLVERSION_SSLv2 7.9.2 +CURL_SSLVERSION_SSLv3 7.9.2 +CURL_SSLVERSION_TLSv1 7.9.2 +CURL_SSLVERSION_TLSv1_0 7.34.0 +CURL_SSLVERSION_TLSv1_1 7.34.0 +CURL_SSLVERSION_TLSv1_2 7.34.0 +CURL_SSLVERSION_TLSv1_3 7.52.0 +CURL_STRICTER 7.50.2 +CURL_TIMECOND_IFMODSINCE 7.9.7 +CURL_TIMECOND_IFUNMODSINCE 7.9.7 +CURL_TIMECOND_LASTMOD 7.9.7 +CURL_TIMECOND_NONE 7.9.7 +CURL_TLSAUTH_NONE 7.21.4 +CURL_TLSAUTH_SRP 7.21.4 +CURL_TRAILERFUNC_ABORT 7.64.0 +CURL_TRAILERFUNC_OK 7.64.0 +CURL_UPKEEP_INTERVAL_DEFAULT 7.62.0 +CURL_VERSION_ALTSVC 7.64.1 +CURL_VERSION_ASYNCHDNS 7.10.7 +CURL_VERSION_BROTLI 7.57.0 +CURL_VERSION_CONV 7.15.4 +CURL_VERSION_CURLDEBUG 7.19.6 +CURL_VERSION_DEBUG 7.10.6 +CURL_VERSION_GSASL 7.76.0 +CURL_VERSION_GSSAPI 7.38.0 +CURL_VERSION_GSSNEGOTIATE 7.10.6 7.38.0 +CURL_VERSION_HSTS 7.74.0 +CURL_VERSION_HTTP2 7.33.0 +CURL_VERSION_HTTP3 7.66.0 +CURL_VERSION_HTTPS_PROXY 7.52.0 +CURL_VERSION_IDN 7.12.0 +CURL_VERSION_IPV6 7.10 +CURL_VERSION_KERBEROS4 7.10 7.33.0 +CURL_VERSION_KERBEROS5 7.40.0 +CURL_VERSION_LARGEFILE 7.11.1 +CURL_VERSION_LIBZ 7.10 +CURL_VERSION_MULTI_SSL 7.56.0 +CURL_VERSION_NTLM 7.10.6 +CURL_VERSION_NTLM_WB 7.22.0 +CURL_VERSION_PSL 7.47.0 +CURL_VERSION_SPNEGO 7.10.8 +CURL_VERSION_SSL 7.10 +CURL_VERSION_SSPI 7.13.2 +CURL_VERSION_TLSAUTH_SRP 7.21.4 +CURL_VERSION_UNICODE 7.72.0 +CURL_VERSION_UNIX_SOCKETS 7.40.0 +CURL_VERSION_ZSTD 7.72.0 +CURL_WAIT_POLLIN 7.28.0 +CURL_WAIT_POLLOUT 7.28.0 +CURL_WAIT_POLLPRI 7.28.0 +CURL_WIN32 7.69.0 +CURL_WRITEFUNC_PAUSE 7.18.0 +CURL_ZERO_TERMINATED 7.56.0 CURLALTSVC_H1 7.64.1 CURLALTSVC_H2 7.64.1 CURLALTSVC_H3 7.64.1 CURLALTSVC_READONLYFILE 7.64.1 CURLAUTH_ANY 7.10.6 CURLAUTH_ANYSAFE 7.10.6 +CURLAUTH_AWS_SIGV4 7.75.0 CURLAUTH_BASIC 7.10.6 CURLAUTH_BEARER 7.61.0 CURLAUTH_DIGEST 7.10.6 @@ -29,7 +200,6 @@ CURLAUTH_NONE 7.10.6 CURLAUTH_NTLM 7.10.6 CURLAUTH_NTLM_WB 7.22.0 CURLAUTH_ONLY 7.21.3 -CURLAUTH_AWS_SIGV4 7.75.0 CURLCLOSEPOLICY_CALLBACK 7.7 CURLCLOSEPOLICY_LEAST_RECENTLY_USED 7.7 CURLCLOSEPOLICY_LEAST_TRAFFIC 7.7 @@ -52,8 +222,8 @@ CURLE_COULDNT_CONNECT 7.1 CURLE_COULDNT_RESOLVE_HOST 7.1 CURLE_COULDNT_RESOLVE_PROXY 7.1 CURLE_FAILED_INIT 7.1 -CURLE_FILESIZE_EXCEEDED 7.10.8 CURLE_FILE_COULDNT_READ_FILE 7.1 +CURLE_FILESIZE_EXCEEDED 7.10.8 CURLE_FTP_ACCEPT_FAILED 7.24.0 CURLE_FTP_ACCEPT_TIMEOUT 7.24.0 CURLE_FTP_ACCESS_DENIED 7.1 7.17.0 @@ -97,8 +267,8 @@ CURLE_LDAP_SEARCH_FAILED 7.1 CURLE_LIBRARY_NOT_FOUND 7.1 7.17.0 CURLE_LOGIN_DENIED 7.13.1 CURLE_MALFORMAT_USER 7.1 7.17.0 -CURLE_NOT_BUILT_IN 7.21.5 CURLE_NO_CONNECTION_AVAILABLE 7.30.0 +CURLE_NOT_BUILT_IN 7.21.5 CURLE_OK 7.1 CURLE_OPERATION_TIMEDOUT 7.10.2 CURLE_OPERATION_TIMEOUTED 7.1 7.17.0 @@ -194,6 +364,9 @@ CURLFORM_NOTHING 7.9 7.56.0 CURLFORM_PTRCONTENTS 7.9 7.56.0 CURLFORM_PTRNAME 7.9 7.56.0 CURLFORM_STREAM 7.18.2 7.56.0 +CURLFTP_CREATE_DIR 7.19.4 +CURLFTP_CREATE_DIR_NONE 7.19.4 +CURLFTP_CREATE_DIR_RETRY 7.19.4 CURLFTPAUTH_DEFAULT 7.12.2 CURLFTPAUTH_SSL 7.12.2 CURLFTPAUTH_TLS 7.12.2 @@ -208,12 +381,22 @@ CURLFTPSSL_CCC_PASSIVE 7.16.1 CURLFTPSSL_CONTROL 7.11.0 7.17.0 CURLFTPSSL_NONE 7.11.0 7.17.0 CURLFTPSSL_TRY 7.11.0 7.17.0 -CURLFTP_CREATE_DIR 7.19.4 -CURLFTP_CREATE_DIR_NONE 7.19.4 -CURLFTP_CREATE_DIR_RETRY 7.19.4 CURLGSSAPI_DELEGATION_FLAG 7.22.0 CURLGSSAPI_DELEGATION_NONE 7.22.0 CURLGSSAPI_DELEGATION_POLICY_FLAG 7.22.0 +CURLH_1XX 7.83.0 +CURLH_CONNECT 7.83.0 +CURLH_HEADER 7.83.0 +CURLH_PSEUDO 7.83.0 +CURLH_TRAILER 7.83.0 +CURLHE_BAD_ARGUMENT 7.83.0 +CURLHE_BADINDEX 7.83.0 +CURLHE_MISSING 7.83.0 +CURLHE_NOHEADERS 7.83.0 +CURLHE_NOREQUEST 7.83.0 +CURLHE_NOT_BUILT_IN 7.83.0 +CURLHE_OK 7.83.0 +CURLHE_OUT_OF_MEMORY 7.83.0 CURLHEADER_SEPARATE 7.37.0 CURLHEADER_UNIFIED 7.37.0 CURLHSTS_ENABLE 7.74.0 @@ -243,10 +426,10 @@ CURLINFO_FTP_ENTRY_PATH 7.15.4 CURLINFO_HEADER_IN 7.9.6 CURLINFO_HEADER_OUT 7.9.6 CURLINFO_HEADER_SIZE 7.4.1 -CURLINFO_HTTPAUTH_AVAIL 7.10.8 CURLINFO_HTTP_CODE 7.4.1 7.10.8 CURLINFO_HTTP_CONNECTCODE 7.10.7 CURLINFO_HTTP_VERSION 7.50.0 +CURLINFO_HTTPAUTH_AVAIL 7.10.8 CURLINFO_LASTONE 7.4.1 CURLINFO_LASTSOCKET 7.15.2 CURLINFO_LOCAL_IP 7.21.0 @@ -265,9 +448,9 @@ CURLINFO_PRIMARY_IP 7.19.0 CURLINFO_PRIMARY_PORT 7.21.0 CURLINFO_PRIVATE 7.10.3 CURLINFO_PROTOCOL 7.52.0 -CURLINFO_PROXYAUTH_AVAIL 7.10.8 CURLINFO_PROXY_ERROR 7.73.0 CURLINFO_PROXY_SSL_VERIFYRESULT 7.52.0 +CURLINFO_PROXYAUTH_AVAIL 7.10.8 CURLINFO_PTR 7.54.1 CURLINFO_REDIRECT_COUNT 7.9.7 CURLINFO_REDIRECT_TIME 7.9.7 @@ -324,14 +507,28 @@ CURLKHTYPE_ED25519 7.58.0 CURLKHTYPE_RSA 7.19.6 CURLKHTYPE_RSA1 7.19.6 CURLKHTYPE_UNKNOWN 7.19.6 +CURLM_ABORTED_BY_CALLBACK 7.81.0 +CURLM_ADDED_ALREADY 7.32.1 +CURLM_BAD_EASY_HANDLE 7.9.6 +CURLM_BAD_FUNCTION_ARGUMENT 7.69.0 +CURLM_BAD_HANDLE 7.9.6 +CURLM_BAD_SOCKET 7.15.4 +CURLM_CALL_MULTI_PERFORM 7.9.6 +CURLM_CALL_MULTI_SOCKET 7.15.5 +CURLM_INTERNAL_ERROR 7.9.6 +CURLM_OK 7.9.6 +CURLM_OUT_OF_MEMORY 7.9.6 +CURLM_RECURSIVE_API_CALL 7.59.0 +CURLM_UNKNOWN_OPTION 7.15.4 +CURLM_WAKEUP_FAILURE 7.68.0 CURLMIMEOPT_FORMESCAPE 7.81.0 CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE 7.30.0 CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE 7.30.0 -CURLMOPT_MAXCONNECTS 7.16.3 CURLMOPT_MAX_CONCURRENT_STREAMS 7.67.0 CURLMOPT_MAX_HOST_CONNECTIONS 7.30.0 CURLMOPT_MAX_PIPELINE_LENGTH 7.30.0 CURLMOPT_MAX_TOTAL_CONNECTIONS 7.30.0 +CURLMOPT_MAXCONNECTS 7.16.3 CURLMOPT_PIPELINING 7.16.0 CURLMOPT_PIPELINING_SERVER_BL 7.30.0 CURLMOPT_PIPELINING_SITE_BL 7.30.0 @@ -343,38 +540,16 @@ CURLMOPT_TIMERDATA 7.16.0 CURLMOPT_TIMERFUNCTION 7.16.0 CURLMSG_DONE 7.9.6 CURLMSG_NONE 7.9.6 -CURLM_ABORTED_BY_CALLBACK 7.81.0 -CURLM_ADDED_ALREADY 7.32.1 -CURLM_BAD_EASY_HANDLE 7.9.6 -CURLM_BAD_FUNCTION_ARGUMENT 7.69.0 -CURLM_BAD_HANDLE 7.9.6 -CURLM_BAD_SOCKET 7.15.4 -CURLM_CALL_MULTI_PERFORM 7.9.6 -CURLM_CALL_MULTI_SOCKET 7.15.5 -CURLM_INTERNAL_ERROR 7.9.6 -CURLM_OK 7.9.6 -CURLM_OUT_OF_MEMORY 7.9.6 -CURLM_RECURSIVE_API_CALL 7.59.0 -CURLM_UNKNOWN_OPTION 7.15.4 -CURLM_WAKEUP_FAILURE 7.68.0 CURLOPT 7.69.0 -CURLOPTTYPE_BLOB 7.71.0 -CURLOPTTYPE_CBPOINT 7.73.0 -CURLOPTTYPE_FUNCTIONPOINT 7.1 -CURLOPTTYPE_LONG 7.1 -CURLOPTTYPE_OBJECTPOINT 7.1 -CURLOPTTYPE_OFF_T 7.11.0 -CURLOPTTYPE_SLISTPOINT 7.65.2 -CURLOPTTYPE_STRINGPOINT 7.46.0 -CURLOPTTYPE_VALUES 7.73.0 CURLOPT_ABSTRACT_UNIX_SOCKET 7.53.0 -CURLOPT_ACCEPTTIMEOUT_MS 7.24.0 CURLOPT_ACCEPT_ENCODING 7.21.6 +CURLOPT_ACCEPTTIMEOUT_MS 7.24.0 CURLOPT_ADDRESS_SCOPE 7.19.0 CURLOPT_ALTSVC 7.64.1 CURLOPT_ALTSVC_CTRL 7.64.1 CURLOPT_APPEND 7.17.0 CURLOPT_AUTOREFERER 7.1 +CURLOPT_AWS_SIGV4 7.75.0 CURLOPT_BUFFERSIZE 7.10 CURLOPT_CAINFO 7.4.2 CURLOPT_CAINFO_BLOB 7.77.0 @@ -387,10 +562,10 @@ CURLOPT_CLOSEFUNCTION 7.7 7.11.1 7.15.5 CURLOPT_CLOSEPOLICY 7.7 7.16.1 CURLOPT_CLOSESOCKETDATA 7.21.7 CURLOPT_CLOSESOCKETFUNCTION 7.21.7 -CURLOPT_CONNECTTIMEOUT 7.7 -CURLOPT_CONNECTTIMEOUT_MS 7.16.2 CURLOPT_CONNECT_ONLY 7.15.2 CURLOPT_CONNECT_TO 7.49.0 +CURLOPT_CONNECTTIMEOUT 7.7 +CURLOPT_CONNECTTIMEOUT_MS 7.16.2 CURLOPT_CONV_FROM_NETWORK_FUNCTION 7.15.4 7.82.0 CURLOPT_CONV_FROM_UTF8_FUNCTION 7.15.4 7.82.0 CURLOPT_CONV_TO_NETWORK_FUNCTION 7.15.4 7.82.0 @@ -432,11 +607,6 @@ CURLOPT_FNMATCH_FUNCTION 7.21.0 CURLOPT_FOLLOWLOCATION 7.1 CURLOPT_FORBID_REUSE 7.7 CURLOPT_FRESH_CONNECT 7.7 -CURLOPT_FTPAPPEND 7.1 7.16.4 -CURLOPT_FTPASCII 7.1 7.11.1 7.15.5 -CURLOPT_FTPLISTONLY 7.1 7.16.4 -CURLOPT_FTPPORT 7.1 -CURLOPT_FTPSSLAUTH 7.12.2 CURLOPT_FTP_ACCOUNT 7.13.0 CURLOPT_FTP_ALTERNATIVE_TO_USER 7.15.5 CURLOPT_FTP_CREATE_MISSING_DIRS 7.10.7 @@ -448,6 +618,11 @@ CURLOPT_FTP_SSL_CCC 7.16.1 CURLOPT_FTP_USE_EPRT 7.10.5 CURLOPT_FTP_USE_EPSV 7.9.2 CURLOPT_FTP_USE_PRET 7.20.0 +CURLOPT_FTPAPPEND 7.1 7.16.4 +CURLOPT_FTPASCII 7.1 7.11.1 7.15.5 +CURLOPT_FTPLISTONLY 7.1 7.16.4 +CURLOPT_FTPPORT 7.1 +CURLOPT_FTPSSLAUTH 7.12.2 CURLOPT_GSSAPI_DELEGATION 7.22.0 CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS 7.59.0 CURLOPT_HAPROXYPROTOCOL 7.60.0 @@ -463,15 +638,15 @@ CURLOPT_HSTSWRITEDATA 7.74.0 CURLOPT_HSTSWRITEFUNCTION 7.74.0 CURLOPT_HTTP09_ALLOWED 7.64.0 CURLOPT_HTTP200ALIASES 7.10.3 +CURLOPT_HTTP_CONTENT_DECODING 7.16.2 +CURLOPT_HTTP_TRANSFER_DECODING 7.16.2 +CURLOPT_HTTP_VERSION 7.9.1 CURLOPT_HTTPAUTH 7.10.6 CURLOPT_HTTPGET 7.8.1 CURLOPT_HTTPHEADER 7.1 CURLOPT_HTTPPOST 7.1 7.56.0 CURLOPT_HTTPPROXYTUNNEL 7.3 CURLOPT_HTTPREQUEST 7.1 - 7.15.5 -CURLOPT_HTTP_CONTENT_DECODING 7.16.2 -CURLOPT_HTTP_TRANSFER_DECODING 7.16.2 -CURLOPT_HTTP_VERSION 7.9.1 CURLOPT_IGNORE_CONTENT_LENGTH 7.14.1 CURLOPT_INFILE 7.1 7.9.7 CURLOPT_INFILESIZE 7.1 @@ -497,16 +672,16 @@ 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_MAX_RECV_SPEED_LARGE 7.15.5 +CURLOPT_MAX_SEND_SPEED_LARGE 7.15.5 CURLOPT_MAXAGE_CONN 7.65.0 CURLOPT_MAXCONNECTS 7.7 CURLOPT_MAXFILESIZE 7.10.8 CURLOPT_MAXFILESIZE_LARGE 7.11.0 CURLOPT_MAXLIFETIME_CONN 7.80.0 CURLOPT_MAXREDIRS 7.5 -CURLOPT_MAX_RECV_SPEED_LARGE 7.15.5 -CURLOPT_MAX_SEND_SPEED_LARGE 7.15.5 -CURLOPT_MIMEPOST 7.56.0 CURLOPT_MIME_OPTIONS 7.81.0 +CURLOPT_MIMEPOST 7.56.0 CURLOPT_MUTE 7.1 7.8 7.15.5 CURLOPT_NETRC 7.1 CURLOPT_NETRC_FILE 7.11.0 @@ -534,22 +709,15 @@ CURLOPT_POSTFIELDSIZE 7.2 CURLOPT_POSTFIELDSIZE_LARGE 7.11.1 CURLOPT_POSTQUOTE 7.1 CURLOPT_POSTREDIR 7.19.1 +CURLOPT_PRE_PROXY 7.52.0 CURLOPT_PREQUOTE 7.9.5 CURLOPT_PREREQDATA 7.80.0 CURLOPT_PREREQFUNCTION 7.80.0 -CURLOPT_PRE_PROXY 7.52.0 CURLOPT_PRIVATE 7.10.3 CURLOPT_PROGRESSDATA 7.1 CURLOPT_PROGRESSFUNCTION 7.1 7.32.0 CURLOPT_PROTOCOLS 7.19.4 CURLOPT_PROXY 7.1 -CURLOPT_PROXYAUTH 7.10.7 -CURLOPT_PROXYHEADER 7.37.0 -CURLOPT_PROXYPASSWORD 7.19.1 -CURLOPT_PROXYPORT 7.1 -CURLOPT_PROXYTYPE 7.10 -CURLOPT_PROXYUSERNAME 7.19.1 -CURLOPT_PROXYUSERPWD 7.1 CURLOPT_PROXY_CAINFO 7.52.0 CURLOPT_PROXY_CAINFO_BLOB 7.77.0 CURLOPT_PROXY_CAPATH 7.52.0 @@ -559,22 +727,29 @@ CURLOPT_PROXY_ISSUERCERT_BLOB 7.71.0 CURLOPT_PROXY_KEYPASSWD 7.52.0 CURLOPT_PROXY_PINNEDPUBLICKEY 7.52.0 CURLOPT_PROXY_SERVICE_NAME 7.43.0 +CURLOPT_PROXY_SSL_CIPHER_LIST 7.52.0 +CURLOPT_PROXY_SSL_OPTIONS 7.52.0 +CURLOPT_PROXY_SSL_VERIFYHOST 7.52.0 +CURLOPT_PROXY_SSL_VERIFYPEER 7.52.0 CURLOPT_PROXY_SSLCERT 7.52.0 -CURLOPT_PROXY_SSLCERTTYPE 7.52.0 CURLOPT_PROXY_SSLCERT_BLOB 7.71.0 +CURLOPT_PROXY_SSLCERTTYPE 7.52.0 CURLOPT_PROXY_SSLKEY 7.52.0 -CURLOPT_PROXY_SSLKEYTYPE 7.52.0 CURLOPT_PROXY_SSLKEY_BLOB 7.71.0 +CURLOPT_PROXY_SSLKEYTYPE 7.52.0 CURLOPT_PROXY_SSLVERSION 7.52.0 -CURLOPT_PROXY_SSL_CIPHER_LIST 7.52.0 -CURLOPT_PROXY_SSL_OPTIONS 7.52.0 -CURLOPT_PROXY_SSL_VERIFYHOST 7.52.0 -CURLOPT_PROXY_SSL_VERIFYPEER 7.52.0 CURLOPT_PROXY_TLS13_CIPHERS 7.61.0 CURLOPT_PROXY_TLSAUTH_PASSWORD 7.52.0 CURLOPT_PROXY_TLSAUTH_TYPE 7.52.0 CURLOPT_PROXY_TLSAUTH_USERNAME 7.52.0 CURLOPT_PROXY_TRANSFER_MODE 7.18.0 +CURLOPT_PROXYAUTH 7.10.7 +CURLOPT_PROXYHEADER 7.37.0 +CURLOPT_PROXYPASSWORD 7.19.1 +CURLOPT_PROXYPORT 7.1 +CURLOPT_PROXYTYPE 7.10 +CURLOPT_PROXYUSERNAME 7.19.1 +CURLOPT_PROXYUSERPWD 7.1 CURLOPT_PUT 7.1 CURLOPT_QUOTE 7.1 CURLOPT_RANDOM_FILE 7.7 @@ -589,13 +764,13 @@ CURLOPT_RESOLVER_START_DATA 7.59.0 CURLOPT_RESOLVER_START_FUNCTION 7.59.0 CURLOPT_RESUME_FROM 7.1 CURLOPT_RESUME_FROM_LARGE 7.11.0 -CURLOPT_RTSPHEADER 7.20.0 CURLOPT_RTSP_CLIENT_CSEQ 7.20.0 CURLOPT_RTSP_REQUEST 7.20.0 CURLOPT_RTSP_SERVER_CSEQ 7.20.0 CURLOPT_RTSP_SESSION_ID 7.20.0 CURLOPT_RTSP_STREAM_URI 7.20.0 CURLOPT_RTSP_TRANSPORT 7.20.0 +CURLOPT_RTSPHEADER 7.20.0 CURLOPT_SASL_AUTHZID 7.66.0 CURLOPT_SASL_IR 7.31.0 CURLOPT_SEEKDATA 7.18.0 @@ -625,17 +800,6 @@ CURLOPT_SSH_KEYFUNCTION 7.19.6 CURLOPT_SSH_KNOWNHOSTS 7.19.6 CURLOPT_SSH_PRIVATE_KEYFILE 7.16.1 CURLOPT_SSH_PUBLIC_KEYFILE 7.16.1 -CURLOPT_SSLCERT 7.1 -CURLOPT_SSLCERTPASSWD 7.1.1 7.17.0 -CURLOPT_SSLCERTTYPE 7.9.3 -CURLOPT_SSLCERT_BLOB 7.71.0 -CURLOPT_SSLENGINE 7.9.3 -CURLOPT_SSLENGINE_DEFAULT 7.9.3 -CURLOPT_SSLKEY 7.9.3 -CURLOPT_SSLKEYPASSWD 7.9.3 7.17.0 -CURLOPT_SSLKEYTYPE 7.9.3 -CURLOPT_SSLKEY_BLOB 7.71.0 -CURLOPT_SSLVERSION 7.1 CURLOPT_SSL_CIPHER_LIST 7.9 CURLOPT_SSL_CTX_DATA 7.10.6 CURLOPT_SSL_CTX_FUNCTION 7.10.6 @@ -648,6 +812,17 @@ CURLOPT_SSL_SESSIONID_CACHE 7.16.0 CURLOPT_SSL_VERIFYHOST 7.8.1 CURLOPT_SSL_VERIFYPEER 7.4.2 CURLOPT_SSL_VERIFYSTATUS 7.41.0 +CURLOPT_SSLCERT 7.1 +CURLOPT_SSLCERT_BLOB 7.71.0 +CURLOPT_SSLCERTPASSWD 7.1.1 7.17.0 +CURLOPT_SSLCERTTYPE 7.9.3 +CURLOPT_SSLENGINE 7.9.3 +CURLOPT_SSLENGINE_DEFAULT 7.9.3 +CURLOPT_SSLKEY 7.9.3 +CURLOPT_SSLKEY_BLOB 7.71.0 +CURLOPT_SSLKEYPASSWD 7.9.3 7.17.0 +CURLOPT_SSLKEYTYPE 7.9.3 +CURLOPT_SSLVERSION 7.1 CURLOPT_STDERR 7.1 CURLOPT_STREAM_DEPENDS 7.46.0 CURLOPT_STREAM_DEPENDS_E 7.46.0 @@ -672,19 +847,18 @@ CURLOPT_TLSAUTH_TYPE 7.21.4 CURLOPT_TLSAUTH_USERNAME 7.21.4 CURLOPT_TRAILERDATA 7.64.0 CURLOPT_TRAILERFUNCTION 7.64.0 -CURLOPT_TRANSFERTEXT 7.1.1 CURLOPT_TRANSFER_ENCODING 7.21.6 +CURLOPT_TRANSFERTEXT 7.1.1 CURLOPT_UNIX_SOCKET_PATH 7.40.0 CURLOPT_UNRESTRICTED_AUTH 7.10.4 CURLOPT_UPKEEP_INTERVAL_MS 7.62.0 CURLOPT_UPLOAD 7.1 CURLOPT_UPLOAD_BUFFERSIZE 7.62.0 CURLOPT_URL 7.1 +CURLOPT_USE_SSL 7.17.0 CURLOPT_USERAGENT 7.1 CURLOPT_USERNAME 7.19.1 CURLOPT_USERPWD 7.1 -CURLOPT_USE_SSL 7.17.0 -CURLOPT_AWS_SIGV4 7.75.0 CURLOPT_VERBOSE 7.1 CURLOPT_WILDCARDMATCH 7.21.0 CURLOPT_WRITEDATA 7.9.7 @@ -694,6 +868,15 @@ CURLOPT_WRITEINFO 7.1 CURLOPT_XFERINFODATA 7.32.0 CURLOPT_XFERINFOFUNCTION 7.32.0 CURLOPT_XOAUTH2_BEARER 7.33.0 +CURLOPTTYPE_BLOB 7.71.0 +CURLOPTTYPE_CBPOINT 7.73.0 +CURLOPTTYPE_FUNCTIONPOINT 7.1 +CURLOPTTYPE_LONG 7.1 +CURLOPTTYPE_OBJECTPOINT 7.1 +CURLOPTTYPE_OFF_T 7.11.0 +CURLOPTTYPE_SLISTPOINT 7.65.2 +CURLOPTTYPE_STRINGPOINT 7.46.0 +CURLOPTTYPE_VALUES 7.73.0 CURLOT_BLOB 7.73.0 CURLOT_CBPTR 7.73.0 CURLOT_FUNCTION 7.73.0 @@ -744,8 +927,8 @@ CURLPROTO_SMTPS 7.20.0 CURLPROTO_TELNET 7.19.4 CURLPROTO_TFTP 7.19.4 CURLPROXY_HTTP 7.10 -CURLPROXY_HTTPS 7.52.0 CURLPROXY_HTTP_1_0 7.19.4 +CURLPROXY_HTTPS 7.52.0 CURLPROXY_SOCKS4 7.10 CURLPROXY_SOCKS4A 7.18.0 CURLPROXY_SOCKS5 7.10 @@ -785,8 +968,8 @@ CURLPX_UNKNOWN_FAIL 7.73.0 CURLPX_UNKNOWN_MODE 7.73.0 CURLPX_USER_REJECTED 7.73.0 CURLSHE_BAD_OPTION 7.10.3 -CURLSHE_INVALID 7.10.3 CURLSHE_IN_USE 7.10.3 +CURLSHE_INVALID 7.10.3 CURLSHE_NOMEM 7.12.0 CURLSHE_NOT_BUILT_IN 7.23.0 CURLSHE_OK 7.10.3 @@ -821,8 +1004,8 @@ CURLSSLBACKEND_NONE 7.34.0 CURLSSLBACKEND_NSS 7.34.0 CURLSSLBACKEND_OPENSSL 7.34.0 CURLSSLBACKEND_POLARSSL 7.34.0 7.69.0 -CURLSSLBACKEND_RUSTLS 7.76.0 CURLSSLBACKEND_QSOSSL 7.34.0 - 7.38.0 +CURLSSLBACKEND_RUSTLS 7.76.0 CURLSSLBACKEND_SCHANNEL 7.34.0 CURLSSLBACKEND_SECURETRANSPORT 7.64.1 CURLSSLBACKEND_WOLFSSL 7.49.0 @@ -839,6 +1022,18 @@ CURLSSLSET_UNKNOWN_BACKEND 7.56.0 CURLSTS_DONE 7.74.0 CURLSTS_FAIL 7.74.0 CURLSTS_OK 7.74.0 +CURLU_ALLOW_SPACE 7.78.0 +CURLU_APPENDQUERY 7.62.0 +CURLU_DEFAULT_PORT 7.62.0 +CURLU_DEFAULT_SCHEME 7.62.0 +CURLU_DISALLOW_USER 7.62.0 +CURLU_GUESS_SCHEME 7.62.0 +CURLU_NO_AUTHORITY 7.67.0 +CURLU_NO_DEFAULT_PORT 7.62.0 +CURLU_NON_SUPPORT_SCHEME 7.62.0 +CURLU_PATH_AS_IS 7.62.0 +CURLU_URLDECODE 7.62.0 +CURLU_URLENCODE 7.62.0 CURLUE_BAD_FILE_URL 7.81.0 CURLUE_BAD_FRAGMENT 7.81.0 CURLUE_BAD_HANDLE 7.62.0 @@ -884,18 +1079,6 @@ CURLUSESSL_ALL 7.17.0 CURLUSESSL_CONTROL 7.17.0 CURLUSESSL_NONE 7.17.0 CURLUSESSL_TRY 7.17.0 -CURLU_ALLOW_SPACE 7.78.0 -CURLU_APPENDQUERY 7.62.0 -CURLU_DEFAULT_PORT 7.62.0 -CURLU_DEFAULT_SCHEME 7.62.0 -CURLU_DISALLOW_USER 7.62.0 -CURLU_GUESS_SCHEME 7.62.0 -CURLU_NON_SUPPORT_SCHEME 7.62.0 -CURLU_NO_AUTHORITY 7.67.0 -CURLU_NO_DEFAULT_PORT 7.62.0 -CURLU_PATH_AS_IS 7.62.0 -CURLU_URLDECODE 7.62.0 -CURLU_URLENCODE 7.62.0 CURLVERSION_EIGHTH 7.72.0 CURLVERSION_FIFTH 7.57.0 CURLVERSION_FIRST 7.10 @@ -907,173 +1090,3 @@ CURLVERSION_SEVENTH 7.70.0 CURLVERSION_SIXTH 7.66.0 CURLVERSION_TENTH 7.77.0 CURLVERSION_THIRD 7.12.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 -CURL_CHUNK_END_FUNC_FAIL 7.21.0 -CURL_CHUNK_END_FUNC_OK 7.21.0 -CURL_CSELECT_ERR 7.16.3 -CURL_CSELECT_IN 7.16.3 -CURL_CSELECT_OUT 7.16.3 -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 -CURL_ERROR_SIZE 7.1 -CURL_FNMATCHFUNC_FAIL 7.21.0 -CURL_FNMATCHFUNC_MATCH 7.21.0 -CURL_FNMATCHFUNC_NOMATCH 7.21.0 -CURL_FORMADD_DISABLED 7.12.1 7.56.0 -CURL_FORMADD_ILLEGAL_ARRAY 7.9.8 7.56.0 -CURL_FORMADD_INCOMPLETE 7.9.8 7.56.0 -CURL_FORMADD_MEMORY 7.9.8 7.56.0 -CURL_FORMADD_NULL 7.9.8 7.56.0 -CURL_FORMADD_OK 7.9.8 7.56.0 -CURL_FORMADD_OPTION_TWICE 7.9.8 7.56.0 -CURL_FORMADD_UNKNOWN_OPTION 7.9.8 7.56.0 -CURL_GLOBAL_ACK_EINTR 7.30.0 -CURL_GLOBAL_ALL 7.8 -CURL_GLOBAL_DEFAULT 7.8 -CURL_GLOBAL_NOTHING 7.8 -CURL_GLOBAL_SSL 7.8 -CURL_GLOBAL_WIN32 7.8.1 -CURL_HET_DEFAULT 7.59.0 -CURL_HTTPPOST_BUFFER 7.46.0 -CURL_HTTPPOST_CALLBACK 7.46.0 -CURL_HTTPPOST_FILENAME 7.46.0 -CURL_HTTPPOST_LARGE 7.46.0 -CURL_HTTPPOST_PTRBUFFER 7.46.0 -CURL_HTTPPOST_PTRCONTENTS 7.46.0 -CURL_HTTPPOST_PTRNAME 7.46.0 -CURL_HTTPPOST_READFILE 7.46.0 -CURL_HTTP_VERSION_1_0 7.9.1 -CURL_HTTP_VERSION_1_1 7.9.1 -CURL_HTTP_VERSION_2 7.43.0 -CURL_HTTP_VERSION_2TLS 7.47.0 -CURL_HTTP_VERSION_2_0 7.33.0 -CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE 7.49.0 -CURL_HTTP_VERSION_3 7.66.0 -CURL_HTTP_VERSION_NONE 7.9.1 -CURL_IPRESOLVE_V4 7.10.8 -CURL_IPRESOLVE_V6 7.10.8 -CURL_IPRESOLVE_WHATEVER 7.10.8 -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_NONE 7.10.3 -CURL_LOCK_DATA_PSL 7.61.0 -CURL_LOCK_DATA_SHARE 7.10.4 -CURL_LOCK_DATA_SSL_SESSION 7.10.3 -CURL_LOCK_TYPE_CONNECT 7.10 - 7.10.2 -CURL_LOCK_TYPE_COOKIE 7.10 - 7.10.2 -CURL_LOCK_TYPE_DNS 7.10 - 7.10.2 -CURL_LOCK_TYPE_NONE 7.10 - 7.10.2 -CURL_LOCK_TYPE_SSL_SESSION 7.10 - 7.10.2 -CURL_MAX_HTTP_HEADER 7.19.7 -CURL_MAX_READ_SIZE 7.53.0 -CURL_MAX_WRITE_SIZE 7.9.7 -CURL_NETRC_IGNORED 7.9.8 -CURL_NETRC_OPTIONAL 7.9.8 -CURL_NETRC_REQUIRED 7.9.8 -CURL_POLL_IN 7.14.0 -CURL_POLL_INOUT 7.14.0 -CURL_POLL_NONE 7.14.0 -CURL_POLL_OUT 7.14.0 -CURL_POLL_REMOVE 7.14.0 -CURL_PREREQFUNC_ABORT 7.79.0 -CURL_PREREQFUNC_OK 7.79.0 -CURL_PROGRESSFUNC_CONTINUE 7.68.0 -CURL_PROGRESS_BAR 7.1.1 - 7.4.1 -CURL_PROGRESS_STATS 7.1.1 - 7.4.1 -CURL_PUSH_DENY 7.44.0 -CURL_PUSH_ERROROUT 7.72.0 -CURL_PUSH_OK 7.44.0 -CURL_READFUNC_ABORT 7.12.1 -CURL_READFUNC_PAUSE 7.18.0 -CURL_REDIR_GET_ALL 7.19.1 -CURL_REDIR_POST_301 7.19.1 -CURL_REDIR_POST_302 7.19.1 -CURL_REDIR_POST_303 7.25.1 -CURL_REDIR_POST_ALL 7.19.1 -CURL_RTSPREQ_ANNOUNCE 7.20.0 -CURL_RTSPREQ_DESCRIBE 7.20.0 -CURL_RTSPREQ_GET_PARAMETER 7.20.0 -CURL_RTSPREQ_NONE 7.20.0 -CURL_RTSPREQ_OPTIONS 7.20.0 -CURL_RTSPREQ_PAUSE 7.20.0 -CURL_RTSPREQ_PLAY 7.20.0 -CURL_RTSPREQ_RECEIVE 7.20.0 -CURL_RTSPREQ_RECORD 7.20.0 -CURL_RTSPREQ_SETUP 7.20.0 -CURL_RTSPREQ_SET_PARAMETER 7.20.0 -CURL_RTSPREQ_TEARDOWN 7.20.0 -CURL_SEEKFUNC_CANTSEEK 7.19.5 -CURL_SEEKFUNC_FAIL 7.19.5 -CURL_SEEKFUNC_OK 7.19.5 -CURL_SOCKET_BAD 7.14.0 -CURL_SOCKET_TIMEOUT 7.14.0 -CURL_SOCKOPT_ALREADY_CONNECTED 7.21.5 -CURL_SOCKOPT_ERROR 7.21.5 -CURL_SOCKOPT_OK 7.21.5 -CURL_SSLVERSION_DEFAULT 7.9.2 -CURL_SSLVERSION_MAX_DEFAULT 7.54.0 -CURL_SSLVERSION_MAX_NONE 7.54.0 -CURL_SSLVERSION_MAX_TLSv1_0 7.54.0 -CURL_SSLVERSION_MAX_TLSv1_1 7.54.0 -CURL_SSLVERSION_MAX_TLSv1_2 7.54.0 -CURL_SSLVERSION_MAX_TLSv1_3 7.54.0 -CURL_SSLVERSION_SSLv2 7.9.2 -CURL_SSLVERSION_SSLv3 7.9.2 -CURL_SSLVERSION_TLSv1 7.9.2 -CURL_SSLVERSION_TLSv1_0 7.34.0 -CURL_SSLVERSION_TLSv1_1 7.34.0 -CURL_SSLVERSION_TLSv1_2 7.34.0 -CURL_SSLVERSION_TLSv1_3 7.52.0 -CURL_STRICTER 7.50.2 -CURL_TIMECOND_IFMODSINCE 7.9.7 -CURL_TIMECOND_IFUNMODSINCE 7.9.7 -CURL_TIMECOND_LASTMOD 7.9.7 -CURL_TIMECOND_NONE 7.9.7 -CURL_TLSAUTH_NONE 7.21.4 -CURL_TLSAUTH_SRP 7.21.4 -CURL_TRAILERFUNC_ABORT 7.64.0 -CURL_TRAILERFUNC_OK 7.64.0 -CURL_UPKEEP_INTERVAL_DEFAULT 7.62.0 -CURL_VERSION_ALTSVC 7.64.1 -CURL_VERSION_ASYNCHDNS 7.10.7 -CURL_VERSION_BROTLI 7.57.0 -CURL_VERSION_CONV 7.15.4 -CURL_VERSION_CURLDEBUG 7.19.6 -CURL_VERSION_DEBUG 7.10.6 -CURL_VERSION_GSASL 7.76.0 -CURL_VERSION_GSSAPI 7.38.0 -CURL_VERSION_GSSNEGOTIATE 7.10.6 7.38.0 -CURL_VERSION_HSTS 7.74.0 -CURL_VERSION_HTTP2 7.33.0 -CURL_VERSION_HTTP3 7.66.0 -CURL_VERSION_HTTPS_PROXY 7.52.0 -CURL_VERSION_IDN 7.12.0 -CURL_VERSION_IPV6 7.10 -CURL_VERSION_KERBEROS4 7.10 7.33.0 -CURL_VERSION_KERBEROS5 7.40.0 -CURL_VERSION_LARGEFILE 7.11.1 -CURL_VERSION_LIBZ 7.10 -CURL_VERSION_MULTI_SSL 7.56.0 -CURL_VERSION_NTLM 7.10.6 -CURL_VERSION_NTLM_WB 7.22.0 -CURL_VERSION_PSL 7.47.0 -CURL_VERSION_SPNEGO 7.10.8 -CURL_VERSION_SSL 7.10 -CURL_VERSION_SSPI 7.13.2 -CURL_VERSION_TLSAUTH_SRP 7.21.4 -CURL_VERSION_UNICODE 7.72.0 -CURL_VERSION_UNIX_SOCKETS 7.40.0 -CURL_VERSION_ZSTD 7.72.0 -CURL_WAIT_POLLIN 7.28.0 -CURL_WAIT_POLLOUT 7.28.0 -CURL_WAIT_POLLPRI 7.28.0 -CURL_WIN32 7.69.0 -CURL_WRITEFUNC_PAUSE 7.18.0 -CURL_ZERO_TERMINATED 7.56.0 diff --git a/include/curl/Makefile.am b/include/curl/Makefile.am index e77273717de9d7..b6b19416593bdb 100644 --- a/include/curl/Makefile.am +++ b/include/curl/Makefile.am @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. +# Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms @@ -21,7 +21,7 @@ ########################################################################### pkginclude_HEADERS = \ curl.h curlver.h easy.h mprintf.h stdcheaders.h multi.h \ - typecheck-gcc.h system.h urlapi.h options.h + typecheck-gcc.h system.h urlapi.h options.h header.h pkgincludedir= $(includedir)/curl diff --git a/include/curl/curl.h b/include/curl/curl.h index 2e260d5168cc41..79de068923258f 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -3069,6 +3069,7 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); #include "multi.h" #include "urlapi.h" #include "options.h" +#include "header.h" /* the typechecker doesn't work in C++ (yet) */ #if defined(__GNUC__) && defined(__GNUC_MINOR__) && \ diff --git a/include/curl/header.h b/include/curl/header.h new file mode 100644 index 00000000000000..ca3834b56a4a0f --- /dev/null +++ b/include/curl/header.h @@ -0,0 +1,64 @@ +#ifndef CURLINC_HEADER_H +#define CURLINC_HEADER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2018 - 2022, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +struct curl_header { + char *name; /* this might not use the same case */ + char *value; + size_t amount; /* number of headers using this name */ + size_t index; /* ... of this instance, 0 or higher */ + unsigned int origin; /* see bits below */ + void *anchor; /* handle privately used by libcurl */ +}; + +/* 'origin' bits */ +#define CURLH_HEADER (1<<0) /* plain server header */ +#define CURLH_TRAILER (1<<1) /* trailers */ +#define CURLH_CONNECT (1<<2) /* CONNECT headers */ +#define CURLH_1XX (1<<3) /* 1xx headers */ +#define CURLH_PSEUDO (1<<4) /* psuedo headers */ + +typedef enum { + CURLHE_OK, + CURLHE_BADINDEX, /* header exists but not with this index */ + CURLHE_MISSING, /* no such header exists */ + CURLHE_NOHEADERS, /* no headers at all exist (yet) */ + CURLHE_NOREQUEST, /* no request with this number was used */ + CURLHE_OUT_OF_MEMORY, /* out of memory while processing */ + CURLHE_BAD_ARGUMENT, /* a function argument was not okay */ + CURLHE_NOT_BUILT_IN /* if API was disabled in the build */ +} CURLHcode; + +CURL_EXTERN CURLHcode curl_easy_header(CURL *easy, + const char *name, + size_t index, + unsigned int origin, + int request, + struct curl_header **hout); + +CURL_EXTERN struct curl_header *curl_easy_nextheader(CURL *easy, + unsigned int origin, + int request, + struct curl_header *prev); + +#endif /* CURLINC_HEADER_H */ diff --git a/lib/Makefile.inc b/lib/Makefile.inc index e8f110feedd780..b39691b2420bff 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -141,6 +141,7 @@ LIB_CFILES = \ gopher.c \ h2h3.c \ hash.c \ + headers.c \ hmac.c \ hostasyn.c \ hostip.c \ @@ -270,6 +271,7 @@ LIB_HFILES = \ gopher.h \ h2h3.h \ hash.h \ + headers.h \ hostip.h \ hsts.h \ http.h \ diff --git a/lib/headers.c b/lib/headers.c new file mode 100644 index 00000000000000..67ae00fb4267fe --- /dev/null +++ b/lib/headers.c @@ -0,0 +1,319 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2022, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "urldata.h" +#include "strdup.h" +#include "strcase.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" + +#ifndef CURL_DISABLE_HTTP + +/* 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, + size_t index, + size_t amount, + struct Curl_llist_element *e, + struct curl_header **hout) +{ + struct curl_header *h = *hout = &data->state.headerout; + h->name = hs->name; + h->value = hs->value; + h->amount = amount; + h->index = index; + /* this will randomly OR a reverved bit for the sole purpose of making it + impossible for applications to do == comparisons, as that would + otherwise be very tempting and then lead the reserved bits not being + reserved anymore. */ + h->origin = hs->type | (1<<27); + h->anchor = e; +} + +/* public API */ +CURLHcode curl_easy_header(CURL *easy, + const char *name, + size_t nameindex, + unsigned int type, + int request, + struct curl_header **hout) +{ + struct Curl_llist_element *e; + struct Curl_llist_element *e_pick = NULL; + struct Curl_easy *data = easy; + size_t match = 0; + size_t amount = 0; + 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)) + return CURLHE_BAD_ARGUMENT; + if(!Curl_llist_count(&data->state.httphdrs)) + return CURLHE_NOHEADERS; /* no headers available */ + if(request > data->state.requests) + return CURLHE_NOREQUEST; + if(request == -1) + request = data->state.requests; + + /* we need a first round to count amount of this header */ + for(e = data->state.httphdrs.head; e; e = e->next) { + hs = e->ptr; + if(strcasecompare(hs->name, name) && + (hs->type & type) && + (hs->request == request)) { + amount++; + pick = hs; + e_pick = e; + } + } + if(!amount) + return CURLHE_MISSING; + else if(nameindex >= amount) + return CURLHE_BADINDEX; + + if(nameindex == amount - 1) + /* if the last or only ocurrance is what's asked for, then we know it */ + hs = pick; + else { + for(e = data->state.httphdrs.head; e; e = e->next) { + hs = e->ptr; + if(strcasecompare(hs->name, name) && + (hs->type & type) && + (hs->request == request) && + (match++ == nameindex)) { + e_pick = e; + break; + } + } + if(!e) /* this shouldn't happen */ + return CURLHE_MISSING; + } + /* this is the name we want */ + copy_header_external(data, hs, nameindex, amount, e_pick, hout); + return CURLHE_OK; +} + +/* public API */ +struct curl_header *curl_easy_nextheader(CURL *easy, + unsigned int type, + int request, + struct curl_header *prev) +{ + struct Curl_easy *data = easy; + 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; + + if(request > data->state.requests) + return NULL; + if(request == -1) + request = data->state.requests; + + if(prev) { + pick = prev->anchor; + if(!pick) + /* something is wrong */ + return NULL; + pick = pick->next; + } + else + pick = data->state.httphdrs.head; + + if(pick) { + /* make sure it is the next header of the desired type */ + do { + hs = pick->ptr; + if((hs->type & type) && (hs->request == request)) + break; + } while((pick = pick->next)); + } + + if(!pick) + /* no more headers available */ + return NULL; + + hs = pick->ptr; + + /* count number of occurrences of this name within the mask and figure out + the index for the currently selected entry */ + for(e = data->state.httphdrs.head; e; e = e->next) { + struct Curl_header_store *check = e->ptr; + if(strcasecompare(hs->name, check->name) && + (check->request == request) && + (check->type & type)) + amount++; + if(e == pick) + index = amount - 1; + } + + copy_header_external(data, hs, index, amount, pick, &hout); + return hout; +} + +static CURLcode namevalue(char *header, size_t hlen, unsigned int type, + char **name, char **value) +{ + char *end = header + hlen - 1; /* point to the last byte */ + DEBUGASSERT(hlen); + *name = header; + + if(type == CURLH_PSEUDO) { + if(*header != ':') + return CURLE_BAD_FUNCTION_ARGUMENT; + header++; + } + + /* Find the end of the header name */ + while(*header && (*header != ':')) + ++header; + + if(*header) + /* Skip over colon, null it */ + *header++ = 0; + else + return CURLE_BAD_FUNCTION_ARGUMENT; + + /* skip all leading space letters */ + while(*header && ISSPACE(*header)) + header++; + + *value = header; + + /* skip all trailing space letters */ + while((end > header) && ISSPACE(*end)) + *end-- = 0; /* nul terminate */ + return CURLE_OK; +} + +/* + * Curl_headers_push() gets passed a full HTTP header to store. It gets called + * immediately before the header callback. The header is CRLF terminated. + */ +CURLcode Curl_headers_push(struct Curl_easy *data, const char *header, + unsigned char type) +{ + char *value = NULL; + char *name = NULL; + char *end; + size_t hlen; /* length of the incoming header */ + struct Curl_header_store *hs; + CURLcode result = CURLE_OUT_OF_MEMORY; + + if((header[0] == '\r') || (header[0] == '\n')) + /* ignore the body separator */ + return CURLE_OK; + + end = strchr(header, '\r'); + if(!end) { + end = strchr(header, '\n'); + if(!end) + return CURLE_BAD_FUNCTION_ARGUMENT; + } + hlen = end - header + 1; + + hs = calloc(1, sizeof(*hs) + hlen); + if(!hs) + return CURLE_OUT_OF_MEMORY; + memcpy(hs->buffer, header, hlen); + hs->buffer[hlen] = 0; /* nul terminate */ + + result = namevalue(hs->buffer, hlen, type, &name, &value); + if(result) + goto fail; + + hs->name = name; + hs->value = value; + hs->type = type; + hs->request = data->state.requests; + + /* insert this node into the list of headers */ + Curl_llist_insert_next(&data->state.httphdrs, data->state.httphdrs.tail, + hs, &hs->node); + + return CURLE_OK; + fail: + free(hs); + return result; +} + +/* + * Curl_headers_init(). Init the headers subsystem. + */ +static void headers_init(struct Curl_easy *data) +{ + Curl_llist_init(&data->state.httphdrs, NULL); +} + +/* + * Curl_headers_cleanup(). Free all stored headers and associated memory. + */ +CURLcode Curl_headers_cleanup(struct Curl_easy *data) +{ + struct Curl_llist_element *e; + struct Curl_llist_element *n; + + for(e = data->state.httphdrs.head; e; e = n) { + struct Curl_header_store *hs = e->ptr; + n = e->next; + free(hs); + } + headers_init(data); + return CURLE_OK; +} + +#else /* HTTP-disabled builds below */ + +CURLHcode curl_easy_header(CURL *easy, + const char *name, + size_t index, + unsigned int type, + struct curl_header **hout) +{ + (void)easy; + (void)name; + (void)index; + (void)type; + (void)hout; + return CURLHE_NOT_BUILT_IN; +} + +struct curl_header *curl_easy_nextheader(CURL *easy, + unsigned int type, + struct curl_header *prev) +{ + (void)easy; + (void)type; + (void)prev; + return NULL; +} +#endif diff --git a/lib/headers.h b/lib/headers.h new file mode 100644 index 00000000000000..83c7b4272c9d7d --- /dev/null +++ b/lib/headers.h @@ -0,0 +1,53 @@ +#ifndef HEADER_CURL_HEADER_H +#define HEADER_CURL_HEADER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifndef CURL_DISABLE_HTTP + +struct Curl_header_store { + struct Curl_llist_element node; + char *name; /* points into 'buffer' */ + char *value; /* points into 'buffer */ + int request; /* 0 is the first request, then 1.. 2.. */ + unsigned char type; /* CURLH_* defines */ + char buffer[1]; /* this is the raw header blob */ +}; + +/* + * Curl_headers_push() gets passed a full header to store. + */ +CURLcode Curl_headers_push(struct Curl_easy *data, const char *header, + unsigned char type); + +/* + * Curl_headers_cleanup(). Free all stored headers and associated memory. + */ +CURLcode Curl_headers_cleanup(struct Curl_easy *data); + +#else +#define Curl_headers_push(x,y,z) CURLE_NOT_BUILT_IN +#define Curl_headers_cleanup(x) Curl_nop_stmt +#endif + +#endif /* HEADER_CURL_HEADER_H */ diff --git a/lib/http.c b/lib/http.c index f5075c98a221fe..6445f98f8d0de8 100644 --- a/lib/http.c +++ b/lib/http.c @@ -4020,9 +4020,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, /* now, only output this if the header AND body are requested: */ - writetype = CLIENTWRITE_HEADER; - if(data->set.include_header) - writetype |= CLIENTWRITE_BODY; + writetype = CLIENTWRITE_HEADER | + (data->set.include_header ? CLIENTWRITE_BODY : 0) | + ((k->httpcode/100 == 1) ? CLIENTWRITE_1XX : 0); headerlen = Curl_dyn_len(&data->state.headerb); result = Curl_client_write(data, writetype, @@ -4175,6 +4175,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, * Checks for special headers coming up. */ + writetype = CLIENTWRITE_HEADER; 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! */ @@ -4299,6 +4300,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, result = Curl_http_statusline(data, conn); if(result) return result; + writetype |= CLIENTWRITE_STATUS; } else { k->header = FALSE; /* this is not a header line */ @@ -4317,10 +4319,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, /* * End of header-checks. Write them to the client. */ - - writetype = CLIENTWRITE_HEADER; if(data->set.include_header) writetype |= CLIENTWRITE_BODY; + if(k->httpcode/100 == 1) + writetype |= CLIENTWRITE_1XX; Curl_debug(data, CURLINFO_HEADER_IN, headp, Curl_dyn_len(&data->state.headerb)); diff --git a/lib/http2.c b/lib/http2.c index 125436584738b7..82a9939301b5e9 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -39,6 +39,7 @@ #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" @@ -1078,9 +1079,14 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, /* nghttp2 guarantees :status is received first and only once, and value is 3 digits status code, and decode_status_code always succeeds. */ + 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", + 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 ")); if(result) return NGHTTP2_ERR_CALLBACK_FAILURE; diff --git a/lib/http_chunks.c b/lib/http_chunks.c index 7edfd6472492af..6bafcd9777e02d 100644 --- a/lib/http_chunks.c +++ b/lib/http_chunks.c @@ -221,7 +221,9 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, tr = Curl_dyn_ptr(&conn->trailer); trlen = Curl_dyn_len(&conn->trailer); if(!data->set.http_te_skip) { - result = Curl_client_write(data, CLIENTWRITE_HEADER, tr, trlen); + result = Curl_client_write(data, + CLIENTWRITE_HEADER|CLIENTWRITE_TRAILER, + tr, trlen); if(result) { *extrap = result; return CHUNKE_PASSTHRU_ERROR; diff --git a/lib/http_proxy.c b/lib/http_proxy.c index 5d5ffc0e1c405d..97f85011b06932 100644 --- a/lib/http_proxy.c +++ b/lib/http_proxy.c @@ -345,6 +345,7 @@ static CURLcode CONNECT(struct Curl_easy *data, /* 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"); @@ -480,6 +481,7 @@ static CURLcode CONNECT(struct Curl_easy *data, if(byte != 0x0a) continue; + s->headerlines++; linep = Curl_dyn_ptr(&s->rcvbuf); perline = Curl_dyn_len(&s->rcvbuf); /* amount of bytes in this line */ @@ -488,9 +490,9 @@ static CURLcode CONNECT(struct Curl_easy *data, if(!data->set.suppress_connect_headers) { /* send the header to the callback */ - int writetype = CLIENTWRITE_HEADER; - if(data->set.include_header) - writetype |= CLIENTWRITE_BODY; + 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) diff --git a/lib/http_proxy.h b/lib/http_proxy.h index 2820e11841c269..67543b589bf767 100644 --- a/lib/http_proxy.h +++ b/lib/http_proxy.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -59,6 +59,7 @@ struct http_connect_state { struct dynbuf rcvbuf; struct dynbuf req; size_t nsend; + size_t headerlines; enum keeponval { KEEPON_DONE, KEEPON_CONNECT, diff --git a/lib/multi.c b/lib/multi.c index 6fdeafb8e6a07d..e127f0904a28a9 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -719,7 +719,6 @@ static CURLcode multi_done(struct Curl_easy *data, } Curl_safefree(data->state.buffer); - Curl_free_request_state(data); return result; } diff --git a/lib/sendf.c b/lib/sendf.c index 220c7dd7ba7115..92cb62a8641366 100644 --- a/lib/sendf.c +++ b/lib/sendf.c @@ -45,6 +45,7 @@ #include "select.h" #include "strdup.h" #include "http2.h" +#include "headers.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -580,21 +581,33 @@ static CURLcode chop_write(struct Curl_easy *data, len -= chunklen; } + /* 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))); + if(result) + return result; + } + if(writeheader) { size_t wrote; - ptr = optr; - len = olen; + Curl_set_in_callback(data, true); - wrote = writeheader(ptr, 1, len, data->set.writeheader); + wrote = writeheader(optr, 1, olen, data->set.writeheader); Curl_set_in_callback(data, false); if(CURL_WRITEFUNC_PAUSE == wrote) /* 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, ptr, len); + return pausewrite(data, CLIENTWRITE_HEADER, optr, olen); - if(wrote != len) { + if(wrote != olen) { failf(data, "Failed writing header"); return CURLE_WRITE_ERROR; } @@ -620,8 +633,6 @@ CURLcode Curl_client_write(struct Curl_easy *data, { struct connectdata *conn = data->conn; - DEBUGASSERT(!(type & ~CLIENTWRITE_BOTH)); - if(!len) return CURLE_OK; diff --git a/lib/sendf.h b/lib/sendf.h index 108a5e934a2fc8..6676003a91e38e 100644 --- a/lib/sendf.h +++ b/lib/sendf.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -45,8 +45,12 @@ void Curl_failf(struct Curl_easy *, const char *fmt, ...); #define failf Curl_failf -#define CLIENTWRITE_BODY (1<<0) -#define CLIENTWRITE_HEADER (1<<1) +#define CLIENTWRITE_BODY (1<<0) +#define CLIENTWRITE_HEADER (1<<1) +#define CLIENTWRITE_STATUS (1<<2) /* the first "header" is the status line */ +#define CLIENTWRITE_CONNECT (1<<3) /* a CONNECT response */ +#define CLIENTWRITE_1XX (1<<4) /* a 1xx response */ +#define CLIENTWRITE_TRAILER (1<<5) /* a trailer header */ #define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER) CURLcode Curl_client_write(struct Curl_easy *data, int type, char *ptr, diff --git a/lib/transfer.c b/lib/transfer.c index 1f8019b3d0c4e9..61e42fa0cb7ef0 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -79,6 +79,7 @@ #include "urlapi-int.h" #include "hsts.h" #include "setopt.h" +#include "headers.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -1489,6 +1490,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) data->set.str[STRING_PROXYPASSWORD]); data->req.headerbytecount = 0; + Curl_headers_cleanup(data); return result; } @@ -1533,6 +1535,8 @@ CURLcode Curl_follow(struct Curl_easy *data, DEBUGASSERT(type != FOLLOW_NONE); + if(type != FOLLOW_FAKE) + data->state.requests++; /* count all real follows */ if(type == FOLLOW_REDIR) { if((data->set.maxredirs != -1) && (data->state.followlocation >= data->set.maxredirs)) { diff --git a/lib/url.c b/lib/url.c index adef2cdb36e50d..a56e4b093da32e 100644 --- a/lib/url.c +++ b/lib/url.c @@ -130,6 +130,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out); #include "setopt.h" #include "altsvc.h" #include "dynbuf.h" +#include "headers.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -470,6 +471,7 @@ CURLcode Curl_close(struct Curl_easy **datap) /* destruct wildcard structures if it is needed */ Curl_wildcard_dtor(&data->wildcard); Curl_freeset(data); + Curl_headers_cleanup(data); free(data); return CURLE_OK; } diff --git a/lib/urldata.h b/lib/urldata.h index cc8a600db43a6c..e77fae7d10b340 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1343,6 +1343,7 @@ struct UrlState { int os_errno; /* filled in with errno whenever an error occurs */ char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */ long followlocation; /* redirect counter */ + int requests; /* request counter: redirects + authentication retakes */ #ifdef HAVE_SIGNAL /* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */ void (*prev_signal)(int sig); @@ -1414,6 +1415,8 @@ struct UrlState { size_t trailers_bytes_sent; struct dynbuf trailers_buf; /* a buffer containing the compiled trailing headers */ + struct Curl_llist httphdrs; /* received headers */ + struct curl_header headerout; /* for external purposes */ #endif trailers_state trailers_state; /* whether we are sending trailers and what stage are we at */ diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc index c16e5b1da87e71..5f5ba1bcc11f44 100644 --- a/tests/data/Makefile.inc +++ b/tests/data/Makefile.inc @@ -219,7 +219,8 @@ test1800 test1801 \ test1908 test1909 test1910 test1911 test1912 test1913 test1914 test1915 \ test1916 test1917 test1918 \ \ -test1933 test1934 test1935 test1936 test1937 test1938 test1939 \ +test1933 test1934 test1935 test1936 test1937 test1938 test1939 test1940 \ +test1941 test1942 test1943 test1944 test1945 test1946 \ \ test2000 test2001 test2002 test2003 test2004 \ \ diff --git a/tests/data/test1940 b/tests/data/test1940 new file mode 100644 index 00000000000000..7de6d9371929c3 --- /dev/null +++ b/tests/data/test1940 @@ -0,0 +1,55 @@ + + + +curl_easy_header + + + +# Server-side + + +HTTP/1.1 200 OK +Date: Thu, 09 Nov 2010 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 + + + + +# Client-side + + +http + + + +curl_easy_header + + +lib%TESTNUMBER + + + +http://%HOSTIP:%HTTPPORT/%TESTNUMBER + + + +# Verify data after the test has been "shot" + + + Date == Thu, 09 Nov 2010 14:49:00 GMT + Server == test with trailing space + Content-Type == text/html + Content-Length == 0 + Location == /%TESTNUMBER0002 +- Set-Cookie == onecookie=data; (0/3) +- Set-Cookie == secondcookie=2data; (1/3) +- Set-Cookie == cookie3=data3; (2/3) + + + diff --git a/tests/data/test1941 b/tests/data/test1941 new file mode 100644 index 00000000000000..dcefa2818c1ad0 --- /dev/null +++ b/tests/data/test1941 @@ -0,0 +1,75 @@ + + + +curl_easy_header +CONNECT + + + +# Server-side + + +HTTP/1.1 200 OK +Date: Thu, 09 Nov 2010 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 + + + +HTTP/1.1 200 Sure go ahead +Server: from the connect +Silly-thing: yes yes + + + + +# Client-side + + +proxy +SSL + + +http +http-proxy + + + +curl_easy_header with CONNECT + + +lib1940 + + + +http://hello:%HTTPPORT/%TESTNUMBER %HOSTIP:%PROXYPORT + + + +# Verify data after the test has been "shot" + + +CONNECT hello:%HTTPPORT HTTP/1.1 +Host: hello:%HTTPPORT +Proxy-Connection: Keep-Alive + + + + Date == Thu, 09 Nov 2010 14:49:00 GMT + Server == test with trailing space + Content-Type == text/html + Content-Length == 0 + Location == /%TESTNUMBER0002 +- Set-Cookie == onecookie=data; (0/3) +- Set-Cookie == secondcookie=2data; (1/3) +- Set-Cookie == cookie3=data3; (2/3) + Server == from the connect + Silly-thing == yes yes + + + diff --git a/tests/data/test1942 b/tests/data/test1942 new file mode 100644 index 00000000000000..4a5e1a2e8a1cb0 --- /dev/null +++ b/tests/data/test1942 @@ -0,0 +1,65 @@ + + + +curl_easy_header +CONNECT + + + +# Server-side + + +HTTP/1.1 100 continue +Date: Thu, 09 Nov 2010 14:49:00 GMT +Server: maybe different + +HTTP/1.1 200 OK +Date: Thu, 09 Nov 2010 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 + + + + +# Client-side + + +http + + +http + + + +curl_easy_header with 1xx response + + +lib1940 + + + +http://%HOSTIP:%HTTPPORT/%TESTNUMBER + + + +# Verify data after the test has been "shot" + + + Date == Thu, 09 Nov 2010 14:49:00 GMT + Server == test with trailing space + Content-Type == text/html + Content-Length == 0 + Location == /%TESTNUMBER0002 +- Set-Cookie == onecookie=data; (0/3) +- Set-Cookie == secondcookie=2data; (1/3) +- Set-Cookie == cookie3=data3; (2/3) + Date == Thu, 09 Nov 2010 14:49:00 GMT + Server == maybe different + + + diff --git a/tests/data/test1943 b/tests/data/test1943 new file mode 100644 index 00000000000000..7f44b2ff5a2c5c --- /dev/null +++ b/tests/data/test1943 @@ -0,0 +1,61 @@ + + + +curl_easy_header +CONNECT + + + +# Server-side + + +HTTP/1.1 200 funky chunky! +Server: fakeit/0.9 fakeitbad/1.0 +Date: Thu, 09 Nov 2010 14:49:00 GMT +Transfer-Encoding: chunked +Trailer: server +Connection: mooo + +40 +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +30 +bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +21;heresatest=moooo +cccccccccccccccccccccccccccccccc + +0 +Server: sent-as-trailer + + + + +# Client-side + + +http + + +http + + + +curl_easy_header with trailers + + +lib1940 + + + +http://%HOSTIP:%HTTPPORT/%TESTNUMBER + + + +# Verify data after the test has been "shot" + + + Date == Thu, 09 Nov 2010 14:49:00 GMT + Server == fakeit/0.9 fakeitbad/1.0 + Server == sent-as-trailer + + + diff --git a/tests/data/test1944 b/tests/data/test1944 new file mode 100644 index 00000000000000..4c1f5049762fda --- /dev/null +++ b/tests/data/test1944 @@ -0,0 +1,63 @@ + + + +curl_easy_header + + + +# Server-side + + +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 + + + +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; + + + + +# Client-side + + +http + + + +curl_easy_header with redirect + + +lib1940 + + + +http://%HOSTIP:%HTTPPORT/%TESTNUMBER + + + +# Verify data after the test has been "shot" + + + Date == Thu, 09 Nov 2010 14:49:00 GMT + Server == the other one + Content-Type == text/html + Content-Length == 0 +- Set-Cookie == 1cookie=data1; (0/2) +- Set-Cookie == 2cookie=data2; (1/2) + + + diff --git a/tests/data/test1945 b/tests/data/test1945 new file mode 100644 index 00000000000000..f5c38e441ccef4 --- /dev/null +++ b/tests/data/test1945 @@ -0,0 +1,75 @@ + + + +curl_easy_header +CONNECT + + + +# Server-side + + +HTTP/1.1 200 OK +Date: Thu, 09 Nov 2010 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 + + + +HTTP/1.1 200 Sure go ahead +Server: from the connect +Silly-thing: yes yes + + + + +# Client-side + + +proxy +SSL + + +http +http-proxy + + + +curl_easy_nextheader with server + CONNECT + + +lib%TESTNUMBER + + + +http://hello:%HTTPPORT/%TESTNUMBER %HOSTIP:%PROXYPORT + + + +# Verify data after the test has been "shot" + + +CONNECT hello:%HTTPPORT HTTP/1.1 +Host: hello:%HTTPPORT +Proxy-Connection: Keep-Alive + + + + Server == from the connect (0/2) + Silly-thing == yes yes (0/1) + Date == Thu, 09 Nov 2010 14:49:00 GMT (0/1) + Server == test with trailing space (1/2) + Content-Type == text/html (0/1) + Content-Length == 0 (0/1) + Set-Cookie == onecookie=data; (0/3) + Set-Cookie == secondcookie=2data; (1/3) + Set-Cookie == cookie3=data3; (2/3) + Location == /19450002 (0/1) + + + diff --git a/tests/data/test1946 b/tests/data/test1946 new file mode 100644 index 00000000000000..4a18cf1c1c9101 --- /dev/null +++ b/tests/data/test1946 @@ -0,0 +1,65 @@ + + + +curl_easy_header + + + +# Server-side + + +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 + + + +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; + + + + +# Client-side + + +http + + + +curl_easy_header with redirect but get headers from first request + + +lib%TESTNUMBER + + + +http://%HOSTIP:%HTTPPORT/%TESTNUMBER + + + +# Verify data after the test has been "shot" + + + Date == Thu, 01 Nov 2001 14:49:00 GMT + Server == test with trailing space + Content-Type == text/html + Content-Length == 0 + Location == /19460002 +- Set-Cookie == onecookie=data; (0/3) +- Set-Cookie == secondcookie=2data; (1/3) +- Set-Cookie == cookie3=data3; (2/3) + + + diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc index 8721d550c1e069..a8739073345f5e 100644 --- a/tests/libtest/Makefile.inc +++ b/tests/libtest/Makefile.inc @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. +# Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms @@ -61,7 +61,7 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect \ lib1591 lib1592 lib1593 lib1594 lib1596 \ lib1905 lib1906 lib1907 lib1908 lib1910 lib1911 lib1912 lib1913 \ lib1915 lib1916 lib1917 lib1918 lib1933 lib1934 lib1935 lib1936 \ - lib1937 lib1938 lib1939 \ + lib1937 lib1938 lib1939 lib1940 lib1945 lib1946 \ lib3010 lib3025 chkdecimalpoint_SOURCES = chkdecimalpoint.c ../../lib/mprintf.c \ @@ -724,6 +724,18 @@ 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 + lib3010_SOURCES = lib3010.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) lib3010_LDADD = $(TESTUTIL_LIBS) lib3010_CPPFLAGS = $(AM_CPPFLAGS) diff --git a/tests/libtest/lib1940.c b/tests/libtest/lib1940.c new file mode 100644 index 00000000000000..922cd425a0e4a3 --- /dev/null +++ b/tests/libtest/lib1940.c @@ -0,0 +1,116 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "test.h" + +#include "memdebug.h" + +static const char *show[]={ + "daTE", + "Server", + "content-type", + "content-length", + "location", + "set-cookie", + "silly-thing", + NULL +}; + +#ifdef LIB1946 +#define HEADER_REQUEST 0 +#else +#define HEADER_REQUEST -1 +#endif + +static void showem(CURL *easy, unsigned int type) +{ + int i; + struct curl_header *header; + for(i = 0; show[i]; i++) { + if(CURLHE_OK == curl_easy_header(easy, show[i], 0, type, HEADER_REQUEST, + &header)) { + if(header->amount > 1) { + /* more than one, iterate over them */ + size_t index = 0; + size_t amount = header->amount; + do { + printf("- %s == %s (%u/%u)\n", header->name, header->value, + (int)index, (int)amount); + + if(++index == amount) + break; + if(CURLHE_OK != curl_easy_header(easy, show[i], index, type, + HEADER_REQUEST, &header)) + break; + } while(1); + } + else { + /* only one of this */ + printf(" %s == %s\n", header->name, header->value); + } + } + } +} + +static size_t write_cb(char *data, size_t n, size_t l, void *userp) +{ + /* take care of the data here, ignored in this example */ + (void)data; + (void)userp; + return n*l; +} +int test(char *URL) +{ + CURL *easy; + + curl_global_init(CURL_GLOBAL_DEFAULT); + + easy = curl_easy_init(); + if(easy) { + CURLcode res; + curl_easy_setopt(easy, CURLOPT_URL, URL); + curl_easy_setopt(easy, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(easy, CURLOPT_FOLLOWLOCATION, 1L); + /* ignores any content */ + curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, write_cb); + + /* if there's a proxy set, use it */ + if(libtest_arg2 && *libtest_arg2) { + curl_easy_setopt(easy, CURLOPT_PROXY, libtest_arg2); + curl_easy_setopt(easy, CURLOPT_HTTPPROXYTUNNEL, 1L); + } + res = curl_easy_perform(easy); + if(res) { + printf("badness: %d\n", (int)res); + } + showem(easy, CURLH_HEADER); + if(libtest_arg2 && *libtest_arg2) { + /* now show connect headers only */ + showem(easy, CURLH_CONNECT); + } + showem(easy, CURLH_1XX); + showem(easy, CURLH_TRAILER); + curl_easy_cleanup(easy); + } + curl_global_cleanup(); + return 0; +} diff --git a/tests/libtest/lib1945.c b/tests/libtest/lib1945.c new file mode 100644 index 00000000000000..b73135148df500 --- /dev/null +++ b/tests/libtest/lib1945.c @@ -0,0 +1,75 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "test.h" + +#include "memdebug.h" + +static void showem(CURL *easy, unsigned int type) +{ + struct curl_header *header = NULL; + struct curl_header *prev = NULL; + + while((header = curl_easy_nextheader(easy, type, 0, prev))) { + printf(" %s == %s (%u/%u)\n", header->name, header->value, + (int)header->index, (int)header->amount); + prev = header; + } +} + +static size_t write_cb(char *data, size_t n, size_t l, void *userp) +{ + /* take care of the data here, ignored in this example */ + (void)data; + (void)userp; + return n*l; +} +int test(char *URL) +{ + CURL *easy; + + curl_global_init(CURL_GLOBAL_DEFAULT); + + easy = curl_easy_init(); + if(easy) { + CURLcode res; + curl_easy_setopt(easy, CURLOPT_URL, URL); + curl_easy_setopt(easy, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(easy, CURLOPT_FOLLOWLOCATION, 1L); + /* ignores any content */ + curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, write_cb); + + /* if there's a proxy set, use it */ + if(libtest_arg2 && *libtest_arg2) { + curl_easy_setopt(easy, CURLOPT_PROXY, libtest_arg2); + curl_easy_setopt(easy, CURLOPT_HTTPPROXYTUNNEL, 1L); + } + res = curl_easy_perform(easy); + if(res) { + printf("badness: %d\n", (int)res); + } + showem(easy, CURLH_CONNECT|CURLH_HEADER|CURLH_TRAILER|CURLH_1XX); + curl_easy_cleanup(easy); + } + curl_global_cleanup(); + return 0; +} diff --git a/tests/symbol-scan.pl b/tests/symbol-scan.pl index d3058b190244b3..b56a8da8a14f10 100755 --- a/tests/symbol-scan.pl +++ b/tests/symbol-scan.pl @@ -6,7 +6,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 2010 - 2021, Daniel Stenberg, , et al. +# Copyright (C) 2010 - 2022, Daniel Stenberg, , et al. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms @@ -54,6 +54,7 @@ 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; @@ -63,17 +64,23 @@ my %doc; my %rem; -open H_IN, "-|", "$Cpreprocessor $i$h" || die "Cannot preprocess curl.h"; -while ( ) { - if ( /enum\s+(\S+\s+)?{/ .. /}/ ) { - s/^\s+//; - next unless /^CURL/; - chomp; - s/[,\s].*//; - push @syms, $_; +# scanenum runs the preprocessor on curl.h so it will process all enums +# included by it, which *should* be all headers +sub scanenum { + my ($file) = @_; + open H_IN, "-|", "$Cpreprocessor $i$file" || die "Cannot preprocess $file"; + while ( ) { + 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 curl.h"; sub scanheader { my ($f)=@_; @@ -86,9 +93,11 @@ sub scanheader { close H; } +scanenum($h); scanheader($h); scanheader($mh); scanheader($ua); +scanheader($hd); open S, "<$root/docs/libcurl/symbols-in-versions"; while() { From 31d6c2f6606c3f687b77a01d01f357582184bdad Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 17 Mar 2022 16:32:45 +0100 Subject: [PATCH 2/9] curl: add %header{name} support in -w handling Outputs the response header 'name' --- docs/cmdline-opts/write-out.d | 4 ++++ src/tool_writeout.c | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/cmdline-opts/write-out.d b/docs/cmdline-opts/write-out.d index 35ab41a22b396b..6d8ed44925ffb3 100644 --- a/docs/cmdline-opts/write-out.d +++ b/docs/cmdline-opts/write-out.d @@ -22,6 +22,10 @@ output a newline by using \\n, a carriage return with \\r and a tab space with The output will be written to standard output, but this can be switched to standard error by using %{stderr}. +You can also access HTTP headers of the most recent request done, with the +help of \fB%header{name}\fP where \fBname\fP is the case insensitive name of +the header (without trailing colon). Added in curl 7.83.0. + .B NOTE: The %-symbol is a special symbol in the win32-environment, where all occurrences of % must be doubled when using this option. diff --git a/src/tool_writeout.c b/src/tool_writeout.c index 5b22a1a9cb991f..c2e4095530aaee 100644 --- a/src/tool_writeout.c +++ b/src/tool_writeout.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -380,6 +380,20 @@ void ourWriteOut(const char *writeinfo, struct per_transfer *per, ptr = end + 1; /* pass the end */ *end = keepit; } + else if(!strncmp("header{", &ptr[1], 7)) { + ptr += 8; + end = strchr(ptr, '}'); + if(end) { + 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 */ + } + else + fputs("%header{", stream); + } else { /* illegal syntax, then just output the characters that are used */ fputc('%', stream); From 44631115d3de63b38afe8349836d8d438fa419bf Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 17 Mar 2022 17:55:06 +0100 Subject: [PATCH 3/9] curl: add %{header_json} support in -w handling Outputs all response headers as a JSON object. --- docs/cmdline-opts/write-out.d | 3 ++ lib/headers.c | 3 +- src/tool_writeout.c | 7 +++-- src/tool_writeout.h | 3 +- src/tool_writeout_json.c | 56 ++++++++++++++++++++++++++++++++--- src/tool_writeout_json.h | 4 +-- 6 files changed, 66 insertions(+), 10 deletions(-) diff --git a/docs/cmdline-opts/write-out.d b/docs/cmdline-opts/write-out.d index 6d8ed44925ffb3..11f01b87a24c91 100644 --- a/docs/cmdline-opts/write-out.d +++ b/docs/cmdline-opts/write-out.d @@ -52,6 +52,9 @@ option. (Added in 7.26.0) The initial path curl ended up in when logging on to the remote FTP server. (Added in 7.15.4) .TP +.B header_json +A JSON object with all HTTP response headers from the recent transfer. +.TP .B http_code The numerical response code that was found in the last retrieved HTTP(S) or FTP(s) transfer. diff --git a/lib/headers.c b/lib/headers.c index 67ae00fb4267fe..add23b786e9988 100644 --- a/lib/headers.c +++ b/lib/headers.c @@ -155,7 +155,8 @@ struct curl_header *curl_easy_nextheader(CURL *easy, hs = pick->ptr; if((hs->type & type) && (hs->request == request)) break; - } while((pick = pick->next)); + pick = pick->next; + } while(pick); } if(!pick) diff --git a/src/tool_writeout.c b/src/tool_writeout.c index c2e4095530aaee..c2239efde1da77 100644 --- a/src/tool_writeout.c +++ b/src/tool_writeout.c @@ -75,6 +75,7 @@ static const struct writeoutvar variables[] = { {"exitcode", VAR_EXITCODE, 0, writeLong}, {"filename_effective", VAR_EFFECTIVE_FILENAME, 0, writeString}, {"ftp_entry_path", VAR_FTP_ENTRY_PATH, CURLINFO_FTP_ENTRY_PATH, writeString}, + {"header_json", VAR_HEADER_JSON, 0, 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}, @@ -218,9 +219,8 @@ static int writeString(FILE *stream, const struct writeoutvar *wovar, if(valid) { DEBUGASSERT(strinfo); if(use_json) { - fprintf(stream, "\"%s\":\"", wovar->name); + fprintf(stream, "\"%s\":", wovar->name); jsonWriteString(stream, strinfo); - fputs("\"", stream); } else fputs(strinfo, stream); @@ -366,6 +366,9 @@ void ourWriteOut(const char *writeinfo, struct per_transfer *per, case VAR_JSON: ourWriteOutJSON(stream, variables, per, per_result); break; + case VAR_HEADER_JSON: + headerJSON(stream, per); + break; default: (void)variables[i].writefunc(stream, &variables[i], per, per_result, false); diff --git a/src/tool_writeout.h b/src/tool_writeout.h index b8f51ffaa3bbed..abf14e30b1c0ff 100644 --- a/src/tool_writeout.h +++ b/src/tool_writeout.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -35,6 +35,7 @@ typedef enum { VAR_ERRORMSG, VAR_EXITCODE, VAR_FTP_ENTRY_PATH, + VAR_HEADER_JSON, VAR_HEADER_SIZE, VAR_HTTP_CODE, VAR_HTTP_CODE_PROXY, diff --git a/src/tool_writeout_json.c b/src/tool_writeout_json.c index caa1ea6f3d1947..2ccc9942efa073 100644 --- a/src/tool_writeout_json.c +++ b/src/tool_writeout_json.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -29,12 +29,12 @@ #include "tool_writeout_json.h" #include "tool_writeout.h" - void jsonWriteString(FILE *stream, const char *in) { const char *i = in; const char *in_end = in + strlen(in); + fputc('\"', stream); for(; i < in_end; i++) { switch(*i) { case '\\': @@ -68,6 +68,7 @@ void jsonWriteString(FILE *stream, const char *in) break; } } + fputc('\"', stream); } void ourWriteOutJSON(FILE *stream, const struct writeoutvar mappings[], @@ -85,7 +86,54 @@ void ourWriteOutJSON(FILE *stream, const struct writeoutvar mappings[], /* The variables are sorted in alphabetical order but as a special case curl_version (which is not actually a --write-out variable) is last. */ - fprintf(stream, "\"curl_version\":\""); + fprintf(stream, "\"curl_version\":"); jsonWriteString(stream, curl_version()); - fprintf(stream, "\"}"); + fprintf(stream, "}"); +} + +#ifdef _MSC_VER +/* warning C4706: assignment within conditional expression */ +#pragma warning(disable:4706) +#endif + +void headerJSON(FILE *stream, struct per_transfer *per) +{ + struct curl_header *header; + struct curl_header *prev = NULL; + + fputc('{', stream); + while((header = curl_easy_nextheader(per->curl, CURLH_HEADER, -1, + prev))) { + if(prev) + fputs(",\n", stream); + jsonWriteString(stream, header->name); + 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 + JSON list */ + size_t a = header->amount; + size_t i = 0; + char *name = header->name; + fputc('[', stream); + do { + jsonWriteString(stream, header->value); + if(++i >= a) + break; + fputc(',', stream); + if(curl_easy_header(per->curl, name, i, CURLH_HEADER, + -1, &header)) + break; + } while(1); + } + fputc(']', stream); + } + else { + fputc('[', stream); + jsonWriteString(stream, header->value); + fputc(']', stream); + } + } + fputs("\n}", stream); } diff --git a/src/tool_writeout_json.h b/src/tool_writeout_json.h index f6b3a86afefb52..f10e260b52f318 100644 --- a/src/tool_writeout_json.h +++ b/src/tool_writeout_json.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -26,7 +26,7 @@ void ourWriteOutJSON(FILE *stream, const struct writeoutvar mappings[], struct per_transfer *per, CURLcode per_result); - +void headerJSON(FILE *stream, struct per_transfer *per); void jsonWriteString(FILE *stream, const char *in); #endif /* HEADER_CURL_TOOL_WRITEOUT_H */ From c5a5a1273140cf434b04aa0e35b96d8cbfb36001 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 17 Mar 2022 23:07:56 +0100 Subject: [PATCH 4/9] test1670: verify -w %header{} --- docs/cmdline-opts/write-out.d | 7 +++-- tests/data/Makefile.inc | 2 ++ tests/data/test1670 | 58 +++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 tests/data/test1670 diff --git a/docs/cmdline-opts/write-out.d b/docs/cmdline-opts/write-out.d index 11f01b87a24c91..df926a04902ee4 100644 --- a/docs/cmdline-opts/write-out.d +++ b/docs/cmdline-opts/write-out.d @@ -22,9 +22,10 @@ output a newline by using \\n, a carriage return with \\r and a tab space with The output will be written to standard output, but this can be switched to standard error by using %{stderr}. -You can also access HTTP headers of the most recent request done, with the -help of \fB%header{name}\fP where \fBname\fP is the case insensitive name of -the header (without trailing colon). Added in curl 7.83.0. +Output HTTP headers from the most recent request by using \fB%header{name}\fP +where \fBname\fP is the case insensitive name of the header (without the +trailing colon). The header contents are exactly as sent over the network, +with leading and trailing whitespace trimmed. Added in curl 7.83.0. .B NOTE: The %-symbol is a special symbol in the win32-environment, where all diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc index 5f5ba1bcc11f44..200e6af51c9f31 100644 --- a/tests/data/Makefile.inc +++ b/tests/data/Makefile.inc @@ -209,6 +209,8 @@ test1630 test1631 test1632 test1633 test1634 \ test1650 test1651 test1652 test1653 test1654 test1655 \ test1660 test1661 \ \ +test1670 \ +\ test1680 test1681 test1682 test1683 \ \ test1700 test1701 test1702 test1703 \ diff --git a/tests/data/test1670 b/tests/data/test1670 new file mode 100644 index 00000000000000..51af81a9ab2070 --- /dev/null +++ b/tests/data/test1670 @@ -0,0 +1,58 @@ + + + +HTTP +HTTP GET +-w +%header + + + +# +# Server-side + + +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- + + + +# +# Client-side + + +http + + +-w individual header output + + +http://%HOSTIP:%HTTPPORT/%TESTNUMBER -w '%header{etag} %header{nope} %header{DATE}\n' -o log/%TESTNUMBER.out + + + +# +# Verify data after the test has been "shot" + + +GET /%TESTNUMBER HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +User-Agent: curl/%VERSION +Accept: */* + + + +"21025-dc7-39462498" Tue, 09 Nov 2010 14:49:00 GMT + + + From 454f321fca956fe5498e8bae6c47dbb471149e3a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 17 Mar 2022 23:11:22 +0100 Subject: [PATCH 5/9] test1671: verify -w '%{header_json} --- docs/cmdline-opts/write-out.d | 20 +++++++--- tests/data/Makefile.inc | 2 +- tests/data/test1671 | 70 +++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 tests/data/test1671 diff --git a/docs/cmdline-opts/write-out.d b/docs/cmdline-opts/write-out.d index df926a04902ee4..208b302c91d5ab 100644 --- a/docs/cmdline-opts/write-out.d +++ b/docs/cmdline-opts/write-out.d @@ -22,10 +22,11 @@ output a newline by using \\n, a carriage return with \\r and a tab space with The output will be written to standard output, but this can be switched to standard error by using %{stderr}. -Output HTTP headers from the most recent request by using \fB%header{name}\fP -where \fBname\fP is the case insensitive name of the header (without the -trailing colon). The header contents are exactly as sent over the network, -with leading and trailing whitespace trimmed. Added in curl 7.83.0. +EXPERIMENTAL feature: Output HTTP headers from the most recent request by +using \fB%header{name}\fP where \fBname\fP is the case insensitive name of the +header (without the trailing colon). The header contents are exactly as sent +over the network, with leading and trailing whitespace trimmed. Added in curl +7.83.0. .B NOTE: The %-symbol is a special symbol in the win32-environment, where all @@ -54,7 +55,16 @@ The initial path curl ended up in when logging on to the remote FTP server. (Added in 7.15.4) .TP .B header_json -A JSON object with all HTTP response headers from the recent transfer. +EXPERIMENTAL feature. + +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. + +The header names are listed in order of appearance over the wire using the +same case as was used over the network. Except for duplicated headers. They +are grouped on the first occurance of that header, using the casing of the +first header, and then each value is presented in the JSON array. .TP .B http_code The numerical response code that was found in the last retrieved HTTP(S) or diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc index 200e6af51c9f31..9863a9d21c4257 100644 --- a/tests/data/Makefile.inc +++ b/tests/data/Makefile.inc @@ -209,7 +209,7 @@ test1630 test1631 test1632 test1633 test1634 \ test1650 test1651 test1652 test1653 test1654 test1655 \ test1660 test1661 \ \ -test1670 \ +test1670 test1671 \ \ test1680 test1681 test1682 test1683 \ \ diff --git a/tests/data/test1671 b/tests/data/test1671 new file mode 100644 index 00000000000000..ed4169955fedc6 --- /dev/null +++ b/tests/data/test1671 @@ -0,0 +1,70 @@ + + + +HTTP +HTTP GET +-w +%header + + + +# +# Server-side + + +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 +Set-Cookie: firstcookie=want1; path=/ +Funny-head: yesyes +Set-Cookie: 2cookie=want2; path=/ +Content-Type: text/html +Set-Cookie: cookie3=want3; path=/ +Content-Length: 6 +Connection: close + +-foo- + + + +# +# Client-side + + +http + + +-w header JSON output + + +http://%HOSTIP:%HTTPPORT/%TESTNUMBER -w '%{header_json}\n' -o log/%TESTNUMBER.out + + + +# +# Verify data after the test has been "shot" + + +GET /%TESTNUMBER HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +User-Agent: curl/%VERSION +Accept: */* + + + +{"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"], +"Set-Cookie":["firstcookie=want1; path=/","2cookie=want2; path=/","cookie3=want3; path=/"], +"Content-Length":["6"], +"Connection":["close"] +} + + + +o \ No newline at end of file From ecc21837a8ced7f54f279f9c5d005c274cfcb18e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 19 Mar 2022 22:34:19 +0100 Subject: [PATCH 6/9] configure: add --enable-headers-api to enable the headers API Defaults to disabled while labeled EXPERIMENTAL. Make all the headers API tests require 'headers-api' to run. --- configure.ac | 21 +++++++++++++++++++++ tests/data/test1670 | 3 +++ tests/data/test1671 | 3 +++ tests/data/test1940 | 3 +++ tests/data/test1941 | 1 + tests/data/test1942 | 1 + tests/data/test1943 | 1 + tests/data/test1944 | 3 +++ tests/data/test1945 | 1 + tests/data/test1946 | 3 +++ tests/runtests.pl | 1 + tests/server/disabled.c | 5 ++++- 12 files changed, 45 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index ed8018155c0396..b5755fb76f9e4a 100644 --- a/configure.ac +++ b/configure.ac @@ -165,6 +165,7 @@ curl_verbose_msg="enabled (--disable-verbose)" curl_rtmp_msg="no (--with-librtmp)" curl_psl_msg="no (--with-libpsl)" curl_altsvc_msg="enabled (--disable-alt-svc)" + curl_headers_msg="no (--enable-headers-api)" curl_hsts_msg="enabled (--disable-hsts)" ssl_backends= curl_h1_msg="enabled (internal)" @@ -3931,6 +3932,25 @@ AS_HELP_STRING([--disable-alt-svc],[Disable alt-svc support]), AC_MSG_RESULT(yes) ) +dnl ************************************************************ +dnl switch on/off headers-api +dnl +AC_MSG_CHECKING([whether to support headers-api]) +AC_ARG_ENABLE(headers-api, +AS_HELP_STRING([--enable-headers-api],[Enable headers-api support]) +AS_HELP_STRING([--disable-headers-api],[Disable headers-api support]), +[ case "$enableval" in + yes) + AC_MSG_RESULT(yes) + AC_DEFINE(USE_HEADERS_API, 1, [enable headers-api]) + curl_headers_msg="enabled"; + ;; + *) AC_MSG_RESULT(no) + ;; + esac ], + AC_MSG_RESULT(no) +) + dnl only check for HSTS if there's SSL present if test -n "$SSL_ENABLED"; then @@ -4345,6 +4365,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl: RTMP: ${curl_rtmp_msg} PSL: ${curl_psl_msg} Alt-svc: ${curl_altsvc_msg} + Headers API: ${curl_headers_msg} HSTS: ${curl_hsts_msg} HTTP1: ${curl_h1_msg} HTTP2: ${curl_h2_msg} diff --git a/tests/data/test1670 b/tests/data/test1670 index 51af81a9ab2070..6d8722f618d184 100644 --- a/tests/data/test1670 +++ b/tests/data/test1670 @@ -30,6 +30,9 @@ Funny-head: yesyes # # Client-side + +headers-api + http diff --git a/tests/data/test1671 b/tests/data/test1671 index ed4169955fedc6..ea0dc3e66017f8 100644 --- a/tests/data/test1671 +++ b/tests/data/test1671 @@ -33,6 +33,9 @@ Connection: close # # Client-side + +headers-api + http diff --git a/tests/data/test1940 b/tests/data/test1940 index 7de6d9371929c3..682916b709d3bf 100644 --- a/tests/data/test1940 +++ b/tests/data/test1940 @@ -23,6 +23,9 @@ Location: /%TESTNUMBER0002 # Client-side + +headers-api + http diff --git a/tests/data/test1941 b/tests/data/test1941 index dcefa2818c1ad0..fe3f1de3917ced 100644 --- a/tests/data/test1941 +++ b/tests/data/test1941 @@ -33,6 +33,7 @@ Silly-thing: yes yes proxy SSL +headers-api http diff --git a/tests/data/test1942 b/tests/data/test1942 index 4a5e1a2e8a1cb0..9079800990462e 100644 --- a/tests/data/test1942 +++ b/tests/data/test1942 @@ -30,6 +30,7 @@ Location: /%TESTNUMBER0002 http +headers-api http diff --git a/tests/data/test1943 b/tests/data/test1943 index 7f44b2ff5a2c5c..194ff111be9d75 100644 --- a/tests/data/test1943 +++ b/tests/data/test1943 @@ -33,6 +33,7 @@ Server: sent-as-trailer http +headers-api http diff --git a/tests/data/test1944 b/tests/data/test1944 index 4c1f5049762fda..3e8ed724cb896a 100644 --- a/tests/data/test1944 +++ b/tests/data/test1944 @@ -33,6 +33,9 @@ Set-Cookie: 2cookie=data2; # Client-side + +headers-api + http diff --git a/tests/data/test1945 b/tests/data/test1945 index f5c38e441ccef4..86fa147adcf0b4 100644 --- a/tests/data/test1945 +++ b/tests/data/test1945 @@ -33,6 +33,7 @@ Silly-thing: yes yes proxy SSL +headers-api http diff --git a/tests/data/test1946 b/tests/data/test1946 index 4a18cf1c1c9101..f2f8ecc0506fb7 100644 --- a/tests/data/test1946 +++ b/tests/data/test1946 @@ -33,6 +33,9 @@ Set-Cookie: 2cookie=data2; # Client-side + +headers-api + http diff --git a/tests/runtests.pl b/tests/runtests.pl index 21fcf66752042a..8afdf8f4bf0999 100755 --- a/tests/runtests.pl +++ b/tests/runtests.pl @@ -2933,6 +2933,7 @@ sub setupfeatures { $feature{"typecheck"} = 1; $feature{"verbose-strings"} = 1; $feature{"wakeup"} = 1; + $feature{"headers-api"} = 1; } diff --git a/tests/server/disabled.c b/tests/server/disabled.c index 6f7c10f18033b4..5ca5787e401822 100644 --- a/tests/server/disabled.c +++ b/tests/server/disabled.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -69,6 +69,9 @@ static const char *disabled[]={ #endif #ifndef ENABLE_WAKEUP "wakeup", +#endif +#ifndef USE_HEADERS_API + "headers-api", #endif NULL }; From 83a0668e15add831b7702a2dcfbc23e6d0381c42 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 19 Mar 2022 22:40:20 +0100 Subject: [PATCH 7/9] lib: make the headers API depend on --enable-headers-api --- lib/headers.c | 10 +++++++--- lib/headers.h | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/headers.c b/lib/headers.c index add23b786e9988..f32644cd4e1124 100644 --- a/lib/headers.c +++ b/lib/headers.c @@ -32,7 +32,7 @@ #include "curl_memory.h" #include "memdebug.h" -#ifndef CURL_DISABLE_HTTP +#if !defined(CURL_DISABLE_HTTP) && defined(USE_HEADERS_API) /* Generate the curl_header struct for the user. This function MUST assign all struct fields in the output struct. */ @@ -297,23 +297,27 @@ CURLcode Curl_headers_cleanup(struct Curl_easy *data) CURLHcode curl_easy_header(CURL *easy, const char *name, size_t index, - unsigned int type, + unsigned int origin, + int request, struct curl_header **hout) { (void)easy; (void)name; (void)index; - (void)type; + (void)origin; + (void)request; (void)hout; return CURLHE_NOT_BUILT_IN; } struct curl_header *curl_easy_nextheader(CURL *easy, unsigned int type, + int request, struct curl_header *prev) { (void)easy; (void)type; + (void)request; (void)prev; return NULL; } diff --git a/lib/headers.h b/lib/headers.h index 83c7b4272c9d7d..d6acc03c21d137 100644 --- a/lib/headers.h +++ b/lib/headers.h @@ -23,7 +23,7 @@ ***************************************************************************/ #include "curl_setup.h" -#ifndef CURL_DISABLE_HTTP +#if !defined(CURL_DISABLE_HTTP) && defined(USE_HEADERS_API) struct Curl_header_store { struct Curl_llist_element node; From 133ab47660ee9dfd45d87c3e7d3b6b885e6c7eac Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 19 Mar 2022 22:47:29 +0100 Subject: [PATCH 8/9] GHA: --enable-headers-api in all workflows --- .github/workflows/linux-hyper.yml | 2 +- .github/workflows/macos.yml | 2 +- .github/workflows/mbedtls.yml | 2 +- .github/workflows/nss.yml | 2 +- .github/workflows/rustls.yml | 2 +- .github/workflows/wolfssl.yml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/linux-hyper.yml b/.github/workflows/linux-hyper.yml index 01b8e801127b3b..4125378076b251 100644 --- a/.github/workflows/linux-hyper.yml +++ b/.github/workflows/linux-hyper.yml @@ -22,7 +22,7 @@ jobs: build: - name: hyper install: - configure: --with-openssl --with-hyper=$HOME/hyper + configure: --with-openssl --with-hyper=$HOME/hyper --enable-headers-api steps: - run: | diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 18c4ca4b8852aa..f2170af5984b6b 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -85,7 +85,7 @@ jobs: - uses: actions/checkout@v2 - - run: autoreconf -fi && ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }} + - run: autoreconf -fi && ./configure --enable-warnings --enable-werror --enable-headers-api ${{ matrix.build.configure }} name: 'configure and build' env: # -Wvla is caused by brotli diff --git a/.github/workflows/mbedtls.yml b/.github/workflows/mbedtls.yml index aa1aa29e97d32f..e94f0ec7fcc46f 100644 --- a/.github/workflows/mbedtls.yml +++ b/.github/workflows/mbedtls.yml @@ -42,7 +42,7 @@ jobs: - uses: actions/checkout@v2 - - run: autoreconf -fi && LDFLAGS="-Wl,-rpath,$HOME/mbed/lib" ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }} && make V=1 + - run: autoreconf -fi && LDFLAGS="-Wl,-rpath,$HOME/mbed/lib" ./configure --enable-warnings --enable-werror --enable-headers-api ${{ matrix.build.configure }} && make V=1 name: 'configure and build' - run: make V=1 test-ci diff --git a/.github/workflows/nss.yml b/.github/workflows/nss.yml index 82dd006dfdb214..fec7aa5ce508db 100644 --- a/.github/workflows/nss.yml +++ b/.github/workflows/nss.yml @@ -22,7 +22,7 @@ jobs: build: - name: NSS install: - configure: --with-nss --enable-debug --enable-werror --with-nss-deprecated + configure: --with-nss --enable-debug --enable-werror --with-nss-deprecated --enable-headers-api steps: - run: | diff --git a/.github/workflows/rustls.yml b/.github/workflows/rustls.yml index c7c1e9cd08be22..3e31d4c0df2628 100644 --- a/.github/workflows/rustls.yml +++ b/.github/workflows/rustls.yml @@ -22,7 +22,7 @@ jobs: build: - name: rustls install: - configure: --with-rustls=$HOME/rustls --enable-debug --enable-werror + configure: --with-rustls=$HOME/rustls --enable-debug --enable-werror --enable-headers-api steps: - run: | diff --git a/.github/workflows/wolfssl.yml b/.github/workflows/wolfssl.yml index c78a9b74c38c9a..2bf3dc6de8bee9 100644 --- a/.github/workflows/wolfssl.yml +++ b/.github/workflows/wolfssl.yml @@ -46,7 +46,7 @@ jobs: - uses: actions/checkout@v2 - - run: autoreconf -fi && LDFLAGS="-Wl,-rpath,$HOME/wssl/lib" ./configure --enable-warnings --enable-werror ${{ matrix.build.curl-configure }} && make V=1 + - run: autoreconf -fi && LDFLAGS="-Wl,-rpath,$HOME/wssl/lib" ./configure --enable-warnings --enable-werror --enable-headers-api ${{ matrix.build.curl-configure }} && make V=1 name: 'configure and build' - run: make V=1 test-ci From d3d8949431b684eb0dcdb78f791b5d6abfce4c8a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 19 Mar 2022 22:50:26 +0100 Subject: [PATCH 9/9] cirrus: add --enable-headers-api for some windows builds --- .cirrus.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 102a27db03b949..3cd8ba11729d79 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -84,14 +84,14 @@ windows_task: 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 + configure: --host=i686-w64-mingw32 --build=i686-w64-mingw32 --prefix=/mingw32 --enable-werror --enable-sspi --with-schannel --with-winidn --with-libssh2 --enable-headers-api tests: "~571" - 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-headers-api tests: "~571" curl_LDFLAGS: -all-static PKG_CONFIG: pkg-config --static @@ -100,14 +100,14 @@ windows_task: 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-headers-api tests: "~571" - 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-headers-api tests: "~571" curl_LDFLAGS: -all-static PKG_CONFIG: pkg-config --static