This adds support for `CURLOPT_DEBUGFUNCTION`[^1] Curl option to set a
custom callback that gets called with debug information during the
lifetime of a Curl request.
The callback gets called with the `CurlHandle` object, an integer
containing the type of the debug message, and a string containing the
debug message. The callback may get called multiple times with the
same message type during a request.
PHP already uses `CURLOPT_DEBUGFUNCTION` functionality to internally
to expose a Curl option named `CURLINFO_HEADER_OUT`.
However,`CURLINFO_HEADER_OUT` is not a "real" Curl option supported
by libcurl. Back in 2006, `CURLINFO_HEADER_OUT` was added[^2] as
a Curl option by using the debug-callback feature. Git history does
not run that back to show why `CURLINFO_HEADER_OUT` was added as a
Curl option, and why the other debug types (such as
`CURLINFO_HEADER_IN` were not added as Curl options, but this seems
to be a historical artifact when we added features without trying
to be close to libcurl options.
This approach has a few issues:
1. `CURLINFO_HEADER_OUT` is not an actual Curl option supported by
upstream libcurl.
2. All of the Curl options have `CURLOPT_` prefix, and `CURLINFO_HEADER_OUT`
is the only Curl "option" that uses the `CURLINFO` prefix. This exception
is, however, noted[^3] in docs.
3. When `CURLINFO_HEADER_OUT` is set, the `CURLOPT_VERBOSE` is also implicitly
set. This was reported[^4] to bugs.php.net, but the bug is marked as wontfix.
This commit adds support for `CURLOPT_DEBUGFUNCTION`. It extends the existing
`curl_debug` callback to store the header-in information if it encounters
a debug message with `CURLINFO_HEADER_OUT`. In all cases, if a callable
is set, it gets called.
`CURLOPT_DEBUGFUNCTION` intends to replace `CURLINFO_HEADER_OUT` Curl
option as a versatile alternative that can also be used to extract
other debug information such as SSL data, text information messages,
incoming headers, as well as headers sent out (which `CURLINFO_HEADER_OUT`
makes available).
The callables are allowed to throw exceptions, but the return values are
ignored.
`CURLOPT_DEBUGFUNCTION` requires `CURLOPT_VERBOSE` enabled, and setting
`CURLOPT_DEBUGFUNCTION` does _not_ implicitly enable `CURLOPT_VERBOSE`.
If the `CURLOPT_DEBUGFUNCTION` option is set, setting `CURLINFO_HEADER_OUT`
throws a `ValueError` exception. Setting `CURLOPT_DEBUGFUNCTION` _after_
enabling `CURLINFO_HEADER_OUT` is allowed. Technically, it is possible
for both functionality (calling user-provided callback _and_ storing
header-out data) is possible, setting `CURLINFO_HEADER_OUT` is not
allowed to encourage the use of `CURLOPT_DEBUGFUNCTION` function.
This commit also adds the rest of the `CURLINFO_` constants used as
the `type` integer value in `CURLOPT_DEBUGFUNCTION` callback.
---
[^1]: [cur.se - CURLOPT_DEBUGFUNCTION](https://curl.se/libcurl/c/CURLOPT_DEBUGFUNCTION.html)
[^2]: [`5f25d80`](5f25d80d10)
[^3]: [curl_setopt doc mentioning `CURLINFO_` prefix is intentional](https://www.php.net/manual/en/function.curl-setopt.php#:~:text=prefix%20is%20intentional)
[^4]: [bugs.php.net - `CURLOPT_VERBOSE` does not work with `CURLINFO_HEADER_OUT`](https://bugs.php.net/bug.php?id=65348)
Curl >= 7.80.0 supports declaring a function for `CURLOPT_PREREQFUNCTION` option
that gets called after Curl establishes a connection (including the TLS handshake
for HTTPS connections), but before the actual request is made.
The callable must return either `CURL_PREREQFUNC_OK` or `CURL_PREREQFUNC_ABORT` to
allow or abort the request.
This adds support for it to PHP with required ifdef.
- libc: https://curl.se/libcurl/c/CURLOPT_PREREQFUNCTION.html
Co-authored-by: Gina Peter Bnayard <girgias@php.net>
* ext/curl: Convert handlers.progress to just be a FCC
* ext/curl: Convert handlers.sshhostkey to just be a FCC
* ext/curl: Convert handlers.xferinfo to just be a FCC
* ext/curl: Convert handlers.fnmatch to just be a FCC
* ext/curl: Convert handlers.server_push to just be a FCC
* ext/curl: Convert php_curl_write to just use FCC without a function name zval
* ext/curl: Convert php_curl_read to just use FCC without a function name zval
* ext/curl: Remove workaround for old libcurl
* ext/curl: Create macros to codegen the handling of callable options
Bumps the minimum required libcurl version to 7.61.0.
Please also see #4917, which bumped minimum libcurl version to the current >= 7.29.0.
This bumps the minimum requirement to Curl 7.61.0 (released 2018 Sept).
Ubuntu, Debian, RHEL, and RHEL derivatives have major and LTS version bumps this year. Following are the
libcurl-dev/libcurl-devel versions available in the oldest supported (LTS or otherwise) in major OSs.
- Debian buster: [7.64](https://packages.debian.org/buster/libcurl4-openssl-dev)
- Ubuntu 20.04: [7.68](https://packages.ubuntu.com/focal/libcurl-dev)
- CentOS/RHEL 7: 7.29
- RHEL 8/Rocky 8/EL 8: 7.61
- Fedora 38: 7.87
RHEL/CentOS 7 reaches EOL mid 2024, so for PHP 8.4 scheduled towards the end of this year, we can safely
bump the minimum libcurl version.
7.61.0 was selected as the new minimum because RHEL and derivatives have libcurl-devel version 7.61. RHEL 8 is
a current and supported RHEL version.
`CURLOPT_XFERINFOFUNCTION` is available as of cURL 7.32.0, and
supersedes `CURLOPT_PROGRESSFUNCTION` which is still supported by
latest cURL, though.
Closes GH-7823.
1. Update: http://www.php.net/license/3_01.txt to https, as there is anyway server header "Location:" to https.
2. Update few license 3.0 to 3.01 as 3.0 states "php 5.1.1, 4.1.1, and earlier".
3. In some license comments is "at through the world-wide-web" while most is without "at", so deleted.
4. fixed indentation in some files before |
Add CURLStringFile class which works similarly to CURLFile, but
uploads a file from a string rather than a file. This avoids the
need to create a temporary file, or use of a data:// stream.
Basic usage:
$file = new CURLStringFile($data, 'filename.txt', 'text/plain');
curl_setopt($curl, CURLOPT_POSTFIELDS, ['file' => $file]);
Closes GH-6456.
We're starting to see a mix between uses of zend_bool and bool.
Replace all usages with the standard bool type everywhere.
Of course, zend_bool is retained as an alias.
This is simpler than going through curl, because we can manage
the memory more easily (in particular, this removes the need for
to_free->str). Additionally this allows the CURLOPT_PRIVATE data
to have any type, instead of being implicitly cast to string.
For these callbacks a non-null callback already indicates that
a user callback should be used. We don't need an additional
member to tell us the same thing.
Not keeping a reference will not result in use after free, because
curl protects against it, but it will result in a memory leak,
because curl_share_cleanup() will fail. We should make sure that
the share handle object stays alive as long as the curl handles
use it.
To allow exporting the php_curl.h header containing curl class
entries, split off a separate curl_private.h header with all the
implementation details.
We may move or expose additional APIs in php_curl.h on an as-needed
basis.