Commit fd8eaaf153f for php.net

commit fd8eaaf153f958c66068e3bc71b950ee33cb56e8
Author: Ayesh Karunaratne <ayesh@aye.sh>
Date:   Tue Jun 23 17:15:34 2026 +0700

    ext/curl: add support for `CURLINFO_SIZE_DELIVERED` (libcurl >= 8.20.0)

    Adds support for `CURLINFO_SIZE_DELIVERED`[^1] when built with libcurl
    >= 8.20.0.

    In `curl_getinfo()`, the `size_delivered` key or the direct return
    value when the `$option` parameter is set to `CURLINFO_SIZE_DELIVERED`
    returns the number of bytes delivered.

    For transfers that do not use compression (`CURLOPT_ACCEPT_ENCODING`),
    this value will be the same as `CURLINFO_SIZE_DOWNLOAD`. For encoded
    transfers, the `CURLINFO_SIZE_DELIVERED` value will be the uncompressed
    size while `CURLINFO_SIZE_DOWNLOAD` will be the compressed size over
    network.

    [^1]: https://github.com/curl/curl/blob/curl-8_20_0/docs/libcurl/opts/CURLINFO_SIZE_DELIVERED.md

    Closes GH-22408.

diff --git a/NEWS b/NEWS
index 858ca396189..3e24c2fa0bc 100644
--- a/NEWS
+++ b/NEWS
@@ -37,6 +37,9 @@ PHP                                                                        NEWS
 - BZ2:
   . Reject oversized input in bzdecompress(). (arshidkv12)

+- Curl:
+  . Add support for CURLINFO_SIZE_DELIVERED (libcurl >= 8.20.0). (Ayesh)
+
 - Date:
   . Update timelib to 2022.16. (Derick)

diff --git a/UPGRADING b/UPGRADING
index 9f7917301b5..18afee1a5c9 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -186,6 +186,13 @@ PHP 8.6 UPGRADE NOTES
   . It is now possible to define the `__debugInfo()` magic method on enums.
     RFC: https://wiki.php.net/rfc/debugable-enums

+- Curl:
+  . curl_getinfo() return array now includes a new size_delivered key,
+    which indicates the total number of bytes passed to the download
+    write callback. This value can also be obtained by passing
+    CURLINFO_SIZE_DELIVERED as the $option parameter.
+    Requires libcurl 8.20.0 or later.
+
 - Fileinfo:
   . finfo_file() now works with remote streams.

@@ -399,6 +406,9 @@ PHP 8.6 UPGRADE NOTES
 10. New Global Constants
 ========================================

+- Curl:
+  . CURLINFO_SIZE_DELIVERED (libcurl >= 8.20.0).
+
 - Sockets:
   . TCP_USER_TIMEOUT (Linux only).
   . AF_UNSPEC.
diff --git a/ext/curl/curl.stub.php b/ext/curl/curl.stub.php
index aadab8cb0b0..d3bd58510e4 100644
--- a/ext/curl/curl.stub.php
+++ b/ext/curl/curl.stub.php
@@ -3117,6 +3117,13 @@
  */
 const CURLINFO_CONN_ID = UNKNOWN;
 #endif
+#if LIBCURL_VERSION_NUM >= 0x081400 /* Available since 8.20.0 */
+/**
+ * @var int
+ * @cvalue CURLINFO_SIZE_DELIVERED
+ */
+const CURLINFO_SIZE_DELIVERED = UNKNOWN;
+#endif
 /**
  * @var int
  * @cvalue CURLOPT_DISALLOW_USERNAME_IN_URL
diff --git a/ext/curl/curl_arginfo.h b/ext/curl/curl_arginfo.h
index 6fb17ed029e..6a05b73572c 100644
Binary files a/ext/curl/curl_arginfo.h and b/ext/curl/curl_arginfo.h differ
diff --git a/ext/curl/interface.c b/ext/curl/interface.c
index ed544866a88..1dff14b7c8c 100644
--- a/ext/curl/interface.c
+++ b/ext/curl/interface.c
@@ -2456,6 +2456,11 @@ PHP_FUNCTION(curl_getinfo)
 		if (curl_easy_getinfo(ch->cp, CURLINFO_SIZE_DOWNLOAD, &d_code) == CURLE_OK) {
 			CAAD("size_download", d_code);
 		}
+#if LIBCURL_VERSION_NUM >= 0x081400 /* Available since 8.20.0 */
+		if (curl_easy_getinfo(ch->cp, CURLINFO_SIZE_DELIVERED , &l_code) == CURLE_OK) {
+			CAAL("size_delivered", l_code);
+		}
+#endif
 		if (curl_easy_getinfo(ch->cp, CURLINFO_SPEED_DOWNLOAD, &d_code) == CURLE_OK) {
 			CAAD("speed_download", d_code);
 		}
diff --git a/ext/curl/tests/curl_getinfo_CURLINFO_SIZE_DELIVERED.phpt b/ext/curl/tests/curl_getinfo_CURLINFO_SIZE_DELIVERED.phpt
new file mode 100644
index 00000000000..e33277ff88f
--- /dev/null
+++ b/ext/curl/tests/curl_getinfo_CURLINFO_SIZE_DELIVERED.phpt
@@ -0,0 +1,40 @@
+--TEST--
+Curlinfo CURLINFO_SIZE_DELIVERED
+--EXTENSIONS--
+curl
+--SKIPIF--
+<?php
+$curl_version = curl_version();
+if ($curl_version['version_number'] < 0x081400) die("skip: test works only with curl >= 8.20.0");
+?>
+--FILE--
+<?php
+include 'server.inc';
+
+$host = curl_cli_server_start();
+$port = (int) (explode(':', $host))[1];
+
+$ch = curl_init();
+curl_setopt($ch, CURLOPT_URL, "{$host}/get.inc");
+curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+
+$info = curl_getinfo($ch);
+var_dump(isset($info['size_delivered']));
+var_dump($info['size_delivered'] === 0); // this is always 0 before executing the transfer
+
+$result = curl_exec($ch);
+
+$info = curl_getinfo($ch);
+var_dump(isset($info['size_delivered']));
+var_dump(is_int($info['size_delivered']));
+var_dump(curl_getinfo($ch, CURLINFO_SIZE_DELIVERED) === $info['size_delivered']);
+var_dump(curl_getinfo($ch, CURLINFO_SIZE_DELIVERED) > 0);
+?>
+--EXPECT--
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+