Author: Derick Rethans (derickr)
Date: 2026-08-10T10:05:48+01:00
Commit:
https://github.com/php/web-php/commit/7fde0001f0470121d76d58b3656fcfeb540554e9
Raw diff:
https://github.com/php/web-php/commit/7fde0001f0470121d76d58b3656fcfeb540554e9.diff
Merge branch 'master' into preview
* master: (34 commits)
Fix missing “Copy” button on the Windows download page (#1981)
composer(deps-dev): bump friendsofphp/php-cs-fixer (#1982)
composer(deps-dev): bump phpstan/phpstan from 2.2.6 to 2.2.7 (#1983)
Announce PHP 8.4.24
Announce PHP 8.3.33
Set cache_control to 1 month for eol
Create release files with a cache timeout of 30 minutes, instead of the
default month
Don't rely on default cache timeout for archive
Announce PHP 8.6.0alpha3
Announce PHP 8.5.9
Announce PHP 8.2.33
Add SBOM links for Windows builds (#1978)
composer(deps-dev): bump friendsofphp/php-cs-fixer from 3.95.15 to 3.95.17
(#1976)
composer(deps-dev): bump phpstan/phpstan from 2.2.5 to 2.2.6 (#1977)
PHP CS Fixer: update usage (#1705)
Do not abort cross-origin requests with an empty 200 (#1955)
github-actions(deps): bump actions/setup-node from 6 to 7 (#1973)
composer(deps-dev): bump friendsofphp/php-cs-fixer (#1974)
Add a copy function for the SHA256 checksum (#1957)
Fix category for PHP 8.6.0alpha2
...
Changed paths:
A .php-cs-fixer.dist.php
A public/archive/entries/2026-07-07-1.xml
A public/archive/entries/2026-07-13-1.xml
A public/archive/entries/2026-07-16-1.xml
A public/archive/entries/2026-07-30-1.xml
A public/archive/entries/2026-07-30-2.xml
A public/archive/entries/2026-07-30-3.xml
A public/archive/entries/2026-07-30-4.xml
A public/archive/entries/2026-07-30-5.xml
A public/images/news/php-tek-2027.png
A public/releases/8_2_33.php
A public/releases/8_3_33.php
A public/releases/8_4_24.php
A public/releases/8_5_9.php
A tests/EndToEnd/OriginHeaderTest.php
D .php-cs-fixer.php
M .github/workflows/integrate.yaml
M .github/workflows/preview-deploy.yml
M .github/workflows/preview-tests.yml
M .gitignore
M Makefile
M bin/createReleaseEntry
M composer.json
M composer.lock
M include/download-instructions/windows-downloads.php
M include/header.inc
M include/layout.inc
M include/prepend.inc
M include/release-qa.php
M include/releases.inc
M include/version.inc
M phpstan-baseline.neon
M public/ChangeLog-8.php
M public/archive/2026.php
M public/archive/archive.xml
M public/backend/win-releases.json
M public/docs.php
M public/eol.php
M public/js/common.js
M public/pre-release-builds.php
M public/releases/index.php
M public/styles/code-syntax.css
M public/styles/theme-base.css
Diff:
diff --git a/.github/workflows/integrate.yaml b/.github/workflows/integrate.yaml
index 97b0a666aa..42103b874c 100644
--- a/.github/workflows/integrate.yaml
+++ b/.github/workflows/integrate.yaml
@@ -95,7 +95,7 @@ jobs:
run: "composer install --ansi --no-interaction --no-progress"
- name: "Run friendsofphp/php-cs-fixer"
- run: "vendor/bin/php-cs-fixer fix --ansi --config=.php-cs-fixer.php
--diff --dry-run --show-progress=dots --verbose"
+ run: "vendor/bin/php-cs-fixer check --diff --show-progress=dots
--verbose --ansi"
- name: "Get libxml2-utils"
run: |
diff --git a/.github/workflows/preview-deploy.yml
b/.github/workflows/preview-deploy.yml
index 7a9c6e27c9..e8745b8e2d 100644
--- a/.github/workflows/preview-deploy.yml
+++ b/.github/workflows/preview-deploy.yml
@@ -5,6 +5,12 @@ on:
types:
- completed
+# workflow_run needs explicit perms for PR comments.
+permissions:
+ contents: read
+ issues: write
+ pull-requests: write
+
jobs:
deploy:
runs-on: "ubuntu-22.04"
diff --git a/.github/workflows/preview-tests.yml
b/.github/workflows/preview-tests.yml
index a5ca37b774..f91b279128 100644
--- a/.github/workflows/preview-tests.yml
+++ b/.github/workflows/preview-tests.yml
@@ -48,7 +48,7 @@ jobs:
php-version: "${{ matrix.php-version }}"
- name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v6
+ uses: actions/setup-node@v7
with:
node-version: ${{ matrix.node-version }}
diff --git a/.gitignore b/.gitignore
index 5fa5cd36ef..f59a0e8c75 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
/.build/
+/.php-cs-fixer.php
/vendor/
backend/mirror.gif
diff --git a/.php-cs-fixer.php b/.php-cs-fixer.dist.php
similarity index 98%
rename from .php-cs-fixer.php
rename to .php-cs-fixer.dist.php
index feb6b4a4dd..49f50d793b 100644
--- a/.php-cs-fixer.php
+++ b/.php-cs-fixer.dist.php
@@ -35,6 +35,7 @@
'indentation_type' => true,
'is_null' => true,
'line_ending' => true,
+ 'modifier_keywords' => true,
'new_with_parentheses' => true,
'no_extra_blank_lines' => true,
'no_mixed_echo_print' => true,
@@ -64,7 +65,6 @@
],
'trim_array_spaces' => true,
'unary_operator_spaces' => true,
- 'visibility_required' => true,
'void_return' => true,
'whitespace_after_comma_in_array' => true,
]);
diff --git a/Makefile b/Makefile
index 724f253731..a99a403775 100644
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,7 @@ code-coverage: vendor ## Collects code coverage from running
unit tests with php
.PHONY: coding-standards
coding-standards: vendor ## Fixes code style issues with
friendsofphp/php-cs-fixer
- vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --diff
--show-progress=dots --verbose
+ vendor/bin/php-cs-fixer fix --diff --show-progress=dots --verbose
.PHONY: help
help: ## Displays this list of targets with descriptions
diff --git a/bin/createReleaseEntry b/bin/createReleaseEntry
index ca51982fe6..b7b81bed6d 100755
--- a/bin/createReleaseEntry
+++ b/bin/createReleaseEntry
@@ -58,7 +58,7 @@ if (isset($opts['r'])) {
file_put_contents(RELEASES_ABS . $release, "<?php
\$_SERVER['BASE_PAGE'] = 'releases/$release';
require_once __DIR__ . '/../../include/prepend.inc';
-site_header('PHP $version Release Announcement');
+site_header('PHP $version Release Announcement', ['cache' => true,
'cache_control' => 30 * 60]);
?>
<h1>PHP $version Release Announcement</h1>
diff --git a/composer.json b/composer.json
index b035a2865c..51d3e1f6ae 100644
--- a/composer.json
+++ b/composer.json
@@ -12,7 +12,7 @@
},
"require-dev": {
"ext-curl": "*",
- "friendsofphp/php-cs-fixer": "^3.95.11",
+ "friendsofphp/php-cs-fixer": "^3.95.18",
"phpstan/extension-installer": "^1.4",
"phpstan/phpstan": "^2.2",
"phpstan/phpstan-phpunit": "^2.0",
diff --git a/composer.lock b/composer.lock
index 5e6e4d9cfc..71194cf0f0 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at
https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "e14abd31e7a2ad2a15ca5a7b79a6fbb7",
+ "content-hash": "66f95196f6d2f23b9bbcf5edb4b17d69",
"packages": [],
"packages-dev": [
{
@@ -469,16 +469,16 @@
},
{
"name": "friendsofphp/php-cs-fixer",
- "version": "v3.95.11",
+ "version": "v3.95.18",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
- "reference": "35f98e1293283397824d7f349ce5afb8747c3cd5"
+ "reference": "a8b4e4216faabf67f4e96110ee99a48c96e4e683"
},
"dist": {
"type": "zip",
- "url":
"https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/35f98e1293283397824d7f349ce5afb8747c3cd5",
- "reference": "35f98e1293283397824d7f349ce5afb8747c3cd5",
+ "url":
"https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/a8b4e4216faabf67f4e96110ee99a48c96e4e683",
+ "reference": "a8b4e4216faabf67f4e96110ee99a48c96e4e683",
"shasum": ""
},
"require": {
@@ -518,10 +518,10 @@
"php-coveralls/php-coveralls": "^2.9.1",
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.8",
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.8",
- "phpunit/phpunit": "^9.6.34 || ^10.5.63 || ^11.5.55",
+ "phpunit/phpunit": "^9.6.35 || ^10.5.64 || ^11.5.56 ||
^12.5.31 || ^13.0.6",
"symfony/polyfill-php85": "^1.38",
- "symfony/var-dumper": "^5.4.48 || ^6.4.36 || ^7.4.8 || ^8.1.0",
- "symfony/yaml": "^5.4.53 || ^6.4.41 || ^7.4.13 || ^8.1.0"
+ "symfony/var-dumper": "^5.4.48 || ^6.4.36 || ^7.4.8 || ^8.1.1",
+ "symfony/yaml": "^5.4.53 || ^6.4.41 || ^7.4.13 || ^8.1.1"
},
"suggest": {
"ext-dom": "For handling output formats in XML",
@@ -562,7 +562,7 @@
],
"support": {
"issues":
"https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
- "source":
"https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.95.11"
+ "source":
"https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.95.18"
},
"funding": [
{
@@ -570,7 +570,7 @@
"type": "github"
}
],
- "time": "2026-06-25T14:17:04+00:00"
+ "time": "2026-07-30T15:46:02+00:00"
},
{
"name": "myclabs/deep-copy",
@@ -858,11 +858,11 @@
},
{
"name": "phpstan/phpstan",
- "version": "2.2.2",
+ "version": "2.2.7",
"dist": {
"type": "zip",
- "url":
"https://api.github.com/repos/phpstan/phpstan/zipball/e5cc34d491a90e79c216d824f60fe21fd4d93bd6",
- "reference": "e5cc34d491a90e79c216d824f60fe21fd4d93bd6",
+ "url":
"https://api.github.com/repos/phpstan/phpstan/zipball/692db47b9dddb0487934e5236e77d48594aef921",
+ "reference": "692db47b9dddb0487934e5236e77d48594aef921",
"shasum": ""
},
"require": {
@@ -918,25 +918,26 @@
"type": "github"
}
],
- "time": "2026-06-05T09:00:01+00:00"
+ "time": "2026-07-29T17:39:32+00:00"
},
{
"name": "phpstan/phpstan-phpunit",
- "version": "2.0.16",
+ "version": "2.0.18",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-phpunit.git",
- "reference": "6ab598e1bc106e6827fd346ae4a12b4a5d634c32"
+ "reference": "f5dc20ff8082d02339b60cab68ec3eb0d859fb30"
},
"dist": {
"type": "zip",
- "url":
"https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/6ab598e1bc106e6827fd346ae4a12b4a5d634c32",
- "reference": "6ab598e1bc106e6827fd346ae4a12b4a5d634c32",
+ "url":
"https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/f5dc20ff8082d02339b60cab68ec3eb0d859fb30",
+ "reference": "f5dc20ff8082d02339b60cab68ec3eb0d859fb30",
"shasum": ""
},
"require": {
+ "phar-io/version": "^3.2",
"php": "^7.4 || ^8.0",
- "phpstan/phpstan": "^2.1.32"
+ "phpstan/phpstan": "^2.2.3"
},
"conflict": {
"phpunit/phpunit": "<7.0"
@@ -946,7 +947,8 @@
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/phpstan-deprecation-rules": "^2.0",
"phpstan/phpstan-strict-rules": "^2.0",
- "phpunit/phpunit": "^9.6"
+ "phpunit/phpunit": "^9.6",
+ "shipmonk/name-collision-detector": "^2.1"
},
"type": "phpstan-extension",
"extra": {
@@ -972,9 +974,9 @@
],
"support": {
"issues": "https://github.com/phpstan/phpstan-phpunit/issues",
- "source":
"https://github.com/phpstan/phpstan-phpunit/tree/2.0.16"
+ "source":
"https://github.com/phpstan/phpstan-phpunit/tree/2.0.18"
},
- "time": "2026-02-14T09:05:21+00:00"
+ "time": "2026-07-04T12:16:09+00:00"
},
{
"name": "phpunit/php-code-coverage",
@@ -3152,16 +3154,16 @@
},
{
"name": "symfony/console",
- "version": "v8.0.14",
+ "version": "v8.0.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "e2a77289192c413abfe54f1d507159f911a20728"
+ "reference": "7327288efcaf02a3838d2de0ae23915d64713e14"
},
"dist": {
"type": "zip",
- "url":
"https://api.github.com/repos/symfony/console/zipball/e2a77289192c413abfe54f1d507159f911a20728",
- "reference": "e2a77289192c413abfe54f1d507159f911a20728",
+ "url":
"https://api.github.com/repos/symfony/console/zipball/7327288efcaf02a3838d2de0ae23915d64713e14",
+ "reference": "7327288efcaf02a3838d2de0ae23915d64713e14",
"shasum": ""
},
"require": {
@@ -3218,7 +3220,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v8.0.14"
+ "source": "https://github.com/symfony/console/tree/v8.0.15"
},
"funding": [
{
@@ -3238,7 +3240,7 @@
"type": "tidelift"
}
],
- "time": "2026-06-16T12:45:11+00:00"
+ "time": "2026-07-27T13:52:45+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -3313,16 +3315,16 @@
},
{
"name": "symfony/event-dispatcher",
- "version": "v8.0.14",
+ "version": "v8.0.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "3973836dd335445d0c622ffe98e418eed304d95b"
+ "reference": "4ad08142e63219fdcb75ea1a0ac1c9e5c0fc7686"
},
"dist": {
"type": "zip",
- "url":
"https://api.github.com/repos/symfony/event-dispatcher/zipball/3973836dd335445d0c622ffe98e418eed304d95b",
- "reference": "3973836dd335445d0c622ffe98e418eed304d95b",
+ "url":
"https://api.github.com/repos/symfony/event-dispatcher/zipball/4ad08142e63219fdcb75ea1a0ac1c9e5c0fc7686",
+ "reference": "4ad08142e63219fdcb75ea1a0ac1c9e5c0fc7686",
"shasum": ""
},
"require": {
@@ -3374,7 +3376,7 @@
"description": "Provides tools that allow your application
components to communicate with each other by dispatching events and listening
to them",
"homepage": "https://symfony.com",
"support": {
- "source":
"https://github.com/symfony/event-dispatcher/tree/v8.0.14"
+ "source":
"https://github.com/symfony/event-dispatcher/tree/v8.0.15"
},
"funding": [
{
@@ -3394,7 +3396,7 @@
"type": "tidelift"
}
],
- "time": "2026-06-06T11:11:34+00:00"
+ "time": "2026-07-22T15:20:43+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
@@ -3478,16 +3480,16 @@
},
{
"name": "symfony/filesystem",
- "version": "v8.0.11",
+ "version": "v8.0.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "224db910898ce1317b892a9a1338f1f8f17eb7c7"
+ "reference": "3d190c51f717870eed9aa5e9c7cb927ffc911d05"
},
"dist": {
"type": "zip",
- "url":
"https://api.github.com/repos/symfony/filesystem/zipball/224db910898ce1317b892a9a1338f1f8f17eb7c7",
- "reference": "224db910898ce1317b892a9a1338f1f8f17eb7c7",
+ "url":
"https://api.github.com/repos/symfony/filesystem/zipball/3d190c51f717870eed9aa5e9c7cb927ffc911d05",
+ "reference": "3d190c51f717870eed9aa5e9c7cb927ffc911d05",
"shasum": ""
},
"require": {
@@ -3524,7 +3526,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/filesystem/tree/v8.0.11"
+ "source": "https://github.com/symfony/filesystem/tree/v8.0.15"
},
"funding": [
{
@@ -3544,7 +3546,7 @@
"type": "tidelift"
}
],
- "time": "2026-05-11T16:39:47+00:00"
+ "time": "2026-07-22T15:20:43+00:00"
},
{
"name": "symfony/finder",
@@ -3770,16 +3772,16 @@
},
{
"name": "symfony/polyfill-intl-grapheme",
- "version": "v1.38.1",
+ "version": "v1.41.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
- "reference": "e9247d281d694a5120554d9afaf54e070e88a603"
+ "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d"
},
"dist": {
"type": "zip",
- "url":
"https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/e9247d281d694a5120554d9afaf54e070e88a603",
- "reference": "e9247d281d694a5120554d9afaf54e070e88a603",
+ "url":
"https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/bb899c1db0aa8127dc3afe8cda4a67eb24915f8d",
+ "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d",
"shasum": ""
},
"require": {
@@ -3828,7 +3830,7 @@
"shim"
],
"support": {
- "source":
"https://github.com/symfony/polyfill-intl-grapheme/tree/v1.38.1"
+ "source":
"https://github.com/symfony/polyfill-intl-grapheme/tree/v1.41.0"
},
"funding": [
{
@@ -3848,7 +3850,7 @@
"type": "tidelift"
}
],
- "time": "2026-05-26T05:58:03+00:00"
+ "time": "2026-07-28T08:25:59+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
@@ -4484,16 +4486,16 @@
},
{
"name": "symfony/string",
- "version": "v8.0.13",
+ "version": "v8.0.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "f2e3e4d33579350d1b12001ef2872f86b27ed3dc"
+ "reference": "1a6a4245943af4dabe57d269bd0903f9d140a15e"
},
"dist": {
"type": "zip",
- "url":
"https://api.github.com/repos/symfony/string/zipball/f2e3e4d33579350d1b12001ef2872f86b27ed3dc",
- "reference": "f2e3e4d33579350d1b12001ef2872f86b27ed3dc",
+ "url":
"https://api.github.com/repos/symfony/string/zipball/1a6a4245943af4dabe57d269bd0903f9d140a15e",
+ "reference": "1a6a4245943af4dabe57d269bd0903f9d140a15e",
"shasum": ""
},
"require": {
@@ -4550,7 +4552,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v8.0.13"
+ "source": "https://github.com/symfony/string/tree/v8.0.15"
},
"funding": [
{
@@ -4570,7 +4572,7 @@
"type": "tidelift"
}
],
- "time": "2026-05-23T18:05:53+00:00"
+ "time": "2026-07-28T07:34:23+00:00"
},
{
"name": "theseer/tokenizer",
diff --git a/include/download-instructions/windows-downloads.php
b/include/download-instructions/windows-downloads.php
index 896eaa54fc..5d0e64da3b 100644
--- a/include/download-instructions/windows-downloads.php
+++ b/include/download-instructions/windows-downloads.php
@@ -47,6 +47,23 @@ function ws_build_label(string $k, array $entry): string {
return trim(($tool ? $tool . ' ' : '') . ($arch ? $arch . ' ' : '') .
$ts . ($mt ? ' <span class="time">' . $mt . ' UTC</span>' : ''));
}
+function ws_has_sbom(string $version, string $fullVersion): bool {
+ if (version_compare($version, '8.6', '>=')) {
+ return true;
+ }
+
+ $minimumVersions = [
+ '8.2' => '8.2.33',
+ '8.3' => '8.3.33',
+ '8.4' => '8.4.24',
+ '8.5' => '8.5.9',
+ ];
+
+ return isset($minimumVersions[$version]) &&
version_compare($fullVersion, $minimumVersions[$version], '>=');
+}
+
+$hasSbom = ws_has_sbom($version, $fullVersion);
+
echo <<<'HTML'
<strong>Architecture</strong>
<p>It is recommended to use x64 builds of PHP as almost all Windows
installations currently support x64.</p>
@@ -111,7 +128,13 @@ function ws_build_label(string $k, array $entry): string {
if (!empty($entry[$type]['path'])) {
$p = $entry[$type]['path'];
echo "\t", '<p><strong><a href="' .
$baseDownloads . $p . '">' . $package_names[$type] . '</a></strong> <span
class="size">' . $entry[$type]['size'] . '</span><br>', PHP_EOL;
- echo "\t", '<span
class="sha256"><strong>sha256:</strong> ' . $entry[$type]['sha256'] ?? '' .
'</span></p>', PHP_EOL;
+ if (!empty($entry[$type]['sha256'])) {
+ echo "\t",
sha256_html($entry[$type]['sha256']), PHP_EOL;
+ }
+ if ($type === 'zip' && $hasSbom) {
+ echo "\t", '<span class="sbom"><a
href="' . $baseDownloads . $p . '.spdx.json">SPDX</a>|<a href="' .
$baseDownloads . $p . '.cdx.json">CDX</a></span>', PHP_EOL;
+ }
+ echo '</p>', PHP_EOL;
}
}
diff --git a/include/header.inc b/include/header.inc
index fc7117d33f..5cedcb97aa 100644
--- a/include/header.inc
+++ b/include/header.inc
@@ -54,7 +54,7 @@ if ($config["cache"]) {
}
if ($config["cache_control"] && is_numeric($config["cache_control"])) {
- header("Cache-Control: public, max-age=" . (int)
$config["cache_control"]);
+ header("Cache-Control: public, max-age=" . (int) $config["cache_control"]);
}
if (!isset($config["languages"])) {
diff --git a/include/layout.inc b/include/layout.inc
index 49bf51acdc..33c7655cbc 100644
--- a/include/layout.inc
+++ b/include/layout.inc
@@ -505,6 +505,13 @@ function site_footer(array $config = []): void
require __DIR__ . "/footer.inc";
}
+function sha256_html(string $checksum): string
+{
+ $checksum = htmlspecialchars($checksum, ENT_QUOTES, 'UTF-8');
+
+ return '<span class="sha256-row"><span class="sha256">' . $checksum .
'</span><button type="button" class="sha256-copy" data-copy-text="' . $checksum
. '" aria-label="Copy sha256 checksum">Copy</button></span>';
+}
+
function get_nav_items(): array {
return [
new NavItem(
diff --git a/include/prepend.inc b/include/prepend.inc
index b2f3969f11..c1fa1f99bd 100644
--- a/include/prepend.inc
+++ b/include/prepend.inc
@@ -21,20 +21,39 @@ header("Permissions-Policy: interest-cohort=()");
/* Fix Silly Same Origin Policies */
(function (): void {
+ // The presence of CORS headers below depends on the Origin request header,
+ // so shared caches must not reuse a response across different origins.
+ header("Vary: Origin", false);
+
if (!isset($_SERVER["HTTP_ORIGIN"])) {
return;
}
+ // Browsers send a literal "null" origin for sandboxed iframes, documents
+ // loaded from data:/file: URLs and some cross origin redirects.
parse_url()
+ // reports no host at all for those, so treat them as untrusted.
$host = parse_url($_SERVER["HTTP_ORIGIN"]);
- if (!preg_match('/^(.+\.)?php\.net$/', $host["host"])) {
- if ($host["host"] != $_SERVER["SERVER_NAME"]) {
- exit(10);
+ $hostname = $host["host"] ?? "";
+
+ $isTrustedOrigin = $hostname !== "" && (
+ preg_match('/^(.+\.)?php\.net$/', $hostname) === 1
+ || $hostname === ($_SERVER["SERVER_NAME"] ?? "")
+ );
+
+ if (!$isTrustedOrigin) {
+ // Serve the page normally, only without any CORS headers.
+ if (in_array($_SERVER["REQUEST_METHOD"] ?? "GET", ["GET", "HEAD",
"OPTIONS"], true)) {
+ return;
}
+
+ // Never respond with an empty body here: that is what ended up cached.
+ header("Cache-Control: no-store");
+ http_response_code(403);
+ exit("Cross-origin requests are not allowed for this endpoint.\n");
}
+
if (isset($host["port"])) {
- $hostname = $host["host"] . ":" . $host["port"];
- } else {
- $hostname = $host["host"];
+ $hostname .= ":" . $host["port"];
}
header("Access-Control-Allow-Origin: http://$hostname");
diff --git a/include/release-qa.php b/include/release-qa.php
index cb3ac41bd3..59f16e0f08 100644
--- a/include/release-qa.php
+++ b/include/release-qa.php
@@ -71,7 +71,7 @@
],
],
- '8.4.23' => [
+ '8.4.24' => [
'active' => true,
'release' => [
'type' => 'RC',
@@ -79,12 +79,12 @@
'sha256_bz2' => '',
'sha256_gz' => '',
'sha256_xz' => '',
- 'date' => '18 Jun 2026',
+ 'date' => '16 July 2026',
'baseurl' => 'https://downloads.php.net/',
],
],
- '8.5.8' => [
+ '8.5.9' => [
'active' => true,
'release' => [
'type' => 'RC',
@@ -92,8 +92,8 @@
'sha256_bz2' => '',
'sha256_gz' => '',
'sha256_xz' => '',
- 'date' => '18 June 2026',
- 'baseurl' => 'https://downloads.php.net/~daniels/',
+ 'date' => '16 July 2026',
+ 'baseurl' => 'https://downloads.php.net/~edorian/',
],
],
@@ -101,11 +101,11 @@
'active' => true,
'release' => [
'type' => 'alpha',
- 'number' => 1,
- 'sha256_bz2' =>
'c4f1733b93f3c0d7fcfe381bdafc28daf283bac42441a2809645897b1f557a1a',
- 'sha256_gz' =>
'253d9ff1f03bd17ddf0aaed423b59a37d8f9567858df44d30d3c42c14301a7ab',
- 'sha256_xz' =>
'2d4cba8e5511b026b0c786c69b3272fe53dc8643f086cd10fc0e902c20a1757c',
- 'date' => '2 July 2026',
+ 'number' => 3,
+ 'sha256_bz2' =>
'34bf91f3c6f880ed196ff6855f850ec466a75540f78320540d367b349e49bf16',
+ 'sha256_gz' =>
'e63ffdbae7ee90b43ce11b2ec16f62c6b623eec39c726060dba920af6088527b',
+ 'sha256_xz' =>
'5eec9db06195860097005309eb6176309ae738df28f56eb23c87be5887d86c78',
+ 'date' => '30 July 2026',
'baseurl' => 'https://downloads.php.net/~mbeccati/',
],
],
diff --git a/include/releases.inc b/include/releases.inc
index 1bab620f27..11149c0341 100644
--- a/include/releases.inc
+++ b/include/releases.inc
@@ -2,6 +2,154 @@
$OLDRELEASES = array (
8 =>
array (
+ '8.4.23' =>
+ array (
+ 'announcement' =>
+ array (
+ 'English' => '/releases/8_4_23.php',
+ ),
+ 'tags' =>
+ array (
+ 0 => 'security',
+ ),
+ 'date' => '02 Jul 2026',
+ 'source' =>
+ array (
+ 0 =>
+ array (
+ 'filename' => 'php-8.4.23.tar.gz',
+ 'name' => 'PHP 8.4.23 (tar.gz)',
+ 'sha256' =>
'f43b69572cabfb91c023356f3ce197c782d8a255bc084c1a6af58c0e86cf7573',
+ 'date' => '02 Jul 2026',
+ ),
+ 1 =>
+ array (
+ 'filename' => 'php-8.4.23.tar.bz2',
+ 'name' => 'PHP 8.4.23 (tar.bz2)',
+ 'sha256' =>
'c142c063b10cff68d072766e3ffbfb3654a089b938668b0830356437ee95e0fa',
+ 'date' => '02 Jul 2026',
+ ),
+ 2 =>
+ array (
+ 'filename' => 'php-8.4.23.tar.xz',
+ 'name' => 'PHP 8.4.23 (tar.xz)',
+ 'sha256' =>
'1ab9f52008414e43bb2427ffa288eff2a4de39e1a830f957e800ba368d887a72',
+ 'date' => '02 Jul 2026',
+ ),
+ ),
+ 'museum' => false,
+ ),
+ '8.3.32' =>
+ array (
+ 'announcement' =>
+ array (
+ 'English' => '/releases/8_3_32.php',
+ ),
+ 'tags' =>
+ array (
+ 0 => 'security',
+ ),
+ 'date' => '02 Jul 2026',
+ 'source' =>
+ array (
+ 0 =>
+ array (
+ 'filename' => 'php-8.3.32.tar.gz',
+ 'name' => 'PHP 8.3.32 (tar.gz)',
+ 'sha256' =>
'8e1f03eea0b07bc29e1f94d3cfcf0532b0421ec63c1792346b58c3ad8e40fc9b',
+ 'date' => '02 Jul 2026',
+ ),
+ 1 =>
+ array (
+ 'filename' => 'php-8.3.32.tar.bz2',
+ 'name' => 'PHP 8.3.32 (tar.bz2)',
+ 'sha256' =>
'f777ca24661966f94b31f6840cdad437cf30501537db8b872b1b7a1c244b8d02',
+ 'date' => '02 Jul 2026',
+ ),
+ 2 =>
+ array (
+ 'filename' => 'php-8.3.32.tar.xz',
+ 'name' => 'PHP 8.3.32 (tar.xz)',
+ 'sha256' =>
'8698ec1f9402fa5e5e872ae3d0916b62f5f27503c1fbfc9cc3521e113355ea92',
+ 'date' => '02 Jul 2026',
+ ),
+ ),
+ 'museum' => false,
+ ),
+ '8.5.8' =>
+ array (
+ 'announcement' =>
+ array (
+ 'English' => '/releases/8_5_8.php',
+ ),
+ 'tags' =>
+ array (
+ 0 => 'security',
+ ),
+ 'date' => '02 Jul 2026',
+ 'source' =>
+ array (
+ 0 =>
+ array (
+ 'filename' => 'php-8.5.8.tar.gz',
+ 'name' => 'PHP 8.5.8 (tar.gz)',
+ 'sha256' =>
'6ebc55e52af4396385e689f7af0f28944fbbf966843433b573e9dc1dc03df539',
+ 'date' => '02 Jul 2026',
+ ),
+ 1 =>
+ array (
+ 'filename' => 'php-8.5.8.tar.bz2',
+ 'name' => 'PHP 8.5.8 (tar.bz2)',
+ 'sha256' =>
'22f938efc6c4eaa8bf2e40ae11466140309496aa5d5a19204272fb2596fd11dd',
+ 'date' => '02 Jul 2026',
+ ),
+ 2 =>
+ array (
+ 'filename' => 'php-8.5.8.tar.xz',
+ 'name' => 'PHP 8.5.8 (tar.xz)',
+ 'sha256' =>
'58910198d19e873048fe87cdfe16bc790025417ede3d1651bfa1c4b533d573f2',
+ 'date' => '02 Jul 2026',
+ ),
+ ),
+ 'museum' => false,
+ ),
+ '8.2.32' =>
+ array (
+ 'announcement' =>
+ array (
+ 'English' => '/releases/8_2_32.php',
+ ),
+ 'tags' =>
+ array (
+ 0 => 'security',
+ ),
+ 'date' => '02 Jul 2026',
+ 'source' =>
+ array (
+ 0 =>
+ array (
+ 'filename' => 'php-8.2.32.tar.gz',
+ 'name' => 'PHP 8.2.32 (tar.gz)',
+ 'sha256' =>
'56c9d6911da0d337e2c1681f6a767ac0571821e1f16c8fdf9c248bf317d99b94',
+ 'date' => '02 Jul 2026',
+ ),
+ 1 =>
+ array (
+ 'filename' => 'php-8.2.32.tar.bz2',
+ 'name' => 'PHP 8.2.32 (tar.bz2)',
+ 'sha256' =>
'8f21e988ca4dd5e14dd9fb889884487843566e487280027c4efab6c93188a2d1',
+ 'date' => '02 Jul 2026',
+ ),
+ 2 =>
+ array (
+ 'filename' => 'php-8.2.32.tar.xz',
+ 'name' => 'PHP 8.2.32 (tar.xz)',
+ 'sha256' =>
'e02aa173c236c12791696254d607da680e6d5516f8f5c2339642de7c4f944bd2',
+ 'date' => '02 Jul 2026',
+ ),
+ ),
+ 'museum' => false,
+ ),
'8.5.7' =>
array (
'announcement' =>
diff --git a/include/version.inc b/include/version.inc
index 31e4ff7a8a..d7f0acd87a 100644
--- a/include/version.inc
+++ b/include/version.inc
@@ -20,51 +20,51 @@ $RELEASES = (function () {
/* PHP 8.5 Release */
$data['8.5'] = [
- 'version' => '8.5.8',
- 'date' => '02 Jul 2026',
+ 'version' => '8.5.9',
+ 'date' => '30 Jul 2026',
'tags' => ['security'], // Set to ['security'] for security releases.
'sha256' => [
// WARNING: Order of SHA256 entries here is DIFFERENT from the
// order in the manifest
- 'tar.gz' =>
'6ebc55e52af4396385e689f7af0f28944fbbf966843433b573e9dc1dc03df539',
- 'tar.bz2' =>
'22f938efc6c4eaa8bf2e40ae11466140309496aa5d5a19204272fb2596fd11dd',
- 'tar.xz' =>
'58910198d19e873048fe87cdfe16bc790025417ede3d1651bfa1c4b533d573f2',
+ 'tar.gz' =>
'd735459c2cbaeb0673d416c33d372d9ff261d562f6b29da48f3e6aeaeca083af',
+ 'tar.bz2' =>
'703c082ad9d2946ac647f3596812300d2c62b360d2f31a999021692a9b39476c',
+ 'tar.xz' =>
'0db7855f25bcd0ab1d592cdb35e284d6f6a5d2ae0f6f621122e364cc39b708f4',
]
];
/* PHP 8.4 Release */
$data['8.4'] = [
- 'version' => '8.4.23',
- 'date' => '02 Jul 2026',
+ 'version' => '8.4.24',
+ 'date' => '30 Jul 2026',
'tags' => ['security'], // Set to ['security'] for security releases.
'sha256' => [
- 'tar.gz' =>
'f43b69572cabfb91c023356f3ce197c782d8a255bc084c1a6af58c0e86cf7573',
- 'tar.bz2' =>
'c142c063b10cff68d072766e3ffbfb3654a089b938668b0830356437ee95e0fa',
- 'tar.xz' =>
'1ab9f52008414e43bb2427ffa288eff2a4de39e1a830f957e800ba368d887a72',
+ 'tar.gz' =>
'd5fe6a1d7633e70645dc757461eeb7b764ff6a04d0487f076dd56f1f9d8059db',
+ 'tar.bz2' =>
'286890447588510df110ede9e9ce09f1eb4f9856630b47fdc40ece70e20373cf',
+ 'tar.xz' =>
'e127be09a8506f4327c5cfa78a614b00d210714484ec215ce0011b4a03c00731',
]
];
/* PHP 8.3 Release */
$data['8.3'] = [
- 'version' => '8.3.32',
- 'date' => '02 Jul 2026',
+ 'version' => '8.3.33',
+ 'date' => '30 Jul 2026',
'tags' => ['security'], // Set to ['security'] for security releases.
'sha256' => [
- 'tar.gz' =>
'8e1f03eea0b07bc29e1f94d3cfcf0532b0421ec63c1792346b58c3ad8e40fc9b',
- 'tar.bz2' =>
'f777ca24661966f94b31f6840cdad437cf30501537db8b872b1b7a1c244b8d02',
- 'tar.xz' =>
'8698ec1f9402fa5e5e872ae3d0916b62f5f27503c1fbfc9cc3521e113355ea92',
+ 'tar.gz' =>
'f43566da482abeb1614a512dabeda74967847ce8e176a977390d7a115e7812fd',
+ 'tar.bz2' =>
'f9c9f4d0cd7692c6e3da363cd4ca72a826a49ae18f5ed430b6fcae7bc2881e18',
+ 'tar.xz' =>
'e293ed620cec74651bb4a071317892a478aa6840fab22db45c72d77cd42f9676',
]
];
/* PHP 8.2 Release */
$data['8.2'] = [
- 'version' => '8.2.32',
- 'date' => '02 Jul 2026',
+ 'version' => '8.2.33',
+ 'date' => '30 Jul 2026',
'tags' => ['security'], // Set to ['security'] for security releases.
'sha256' => [
- 'tar.gz' =>
'56c9d6911da0d337e2c1681f6a767ac0571821e1f16c8fdf9c248bf317d99b94',
- 'tar.bz2' =>
'8f21e988ca4dd5e14dd9fb889884487843566e487280027c4efab6c93188a2d1',
- 'tar.xz' =>
'e02aa173c236c12791696254d607da680e6d5516f8f5c2339642de7c4f944bd2',
+ 'tar.gz' =>
'9a525d4db1237ede408e454b46f5a93b9e45d83d71753592e3f921903d917e07',
+ 'tar.bz2' =>
'5362f2a7a0e7168ce722fea0048b1a1d28e0f7cc265c417df670c65670695018',
+ 'tar.xz' =>
'fbdeace9b38220436a4c8fd79b900df92878151db145e641750743a283b514c1',
]
];
@@ -139,8 +139,9 @@ function show_source_releases()
<?php download_link($rel['filename'], $rel['filename']); ?>
<span class="releasedate"><?php echo date('d M Y',
strtotime($rel['date'])); ?></span>
<?php
- if (isset($rel['md5'])) echo '<span class="md5sum">',
$rel['md5'], '</span>';
- if (isset($rel['sha256'])) echo '<span class="sha256">',
$rel['sha256'], '</span>';
+ if (isset($rel['sha256'])) {
+ echo sha256_html($rel['sha256']);
+ }
?>
<?php if (isset($rel['note']) && $rel['note']): ?>
<p>
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index eba441413e..b9444947e1 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -339,7 +339,7 @@ parameters:
-
message: '#^Variable \$config might not be defined\.$#'
identifier: variable.undefined
- count: 3
+ count: 6
path: include/header.inc
-
diff --git a/public/ChangeLog-8.php b/public/ChangeLog-8.php
index 9857eec8f1..f8600dd3af 100644
--- a/public/ChangeLog-8.php
+++ b/public/ChangeLog-8.php
@@ -9,6 +9,133 @@
<a id="PHP_8_5"></a>
+<section class="version" id="8.5.9"><!-- {{{ 8.5.9 -->
+<h3>Version 8.5.9</h3>
+<b><?php release_date('30-Jul-2026'); ?></b>
+<ul><li>Core:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22290); ?> (AST pretty
printing does not correctly handle strings containing NUL).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22206); ?> (missing return
in global register detection).</li>
+ <li>Lock unmodified readonly properties for modification after
clone-with.</li>
+</ul></li>
+<li>BCMath:
+<ul>
+ <li>Fixed <?php githubsecurityl('php/php-src', 'x692-q9x7-8c3f'); ?>
(Out-of-bounds write in bccomp()). (CVE-2026-17544)</li>
+</ul></li>
+<li>Calendar:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22602); ?> (gregoriantojd()
and juliantojd() integer overflow with INT_MAX year).</li>
+</ul></li>
+<li>Date:
+<ul>
+ <li>Update timelib to 2022.17.</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 19803); ?> (Parsing a string
with a single white space does create an error).</li>
+ <li>Fixed Unix timestamps in February of the year 0 are misparsed with
@-notation.</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 11310); ?> (__debugInfo does
nothing on userland classes extending Date classes).</li>
+</ul></li>
+<li>DBA:
+<ul>
+ <li>Fixed OOB read on malformed length field in dba flatfile handler.</li>
+</ul></li>
+<li>DOM:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22570); ?> (Stack overflow
when serializing a deeply nested Dom\XMLDocument).</li>
+ <li>Fixed getElementsByClassName() item() returning the wrong element on
random access.</li>
+</ul></li>
+<li>Exif:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 11020); ?> (exif_read_data()
emits a spurious "Illegal IFD size" warning when an IFD is not followed by a
next-IFD offset).</li>
+</ul></li>
+<li>GD:
+<ul>
+ <li>Upgrade libgd. (CVE-2026-9672)</li>
+</ul></li>
+<li>Hash:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 18173); ?> (ext/hash relies
on implementation-defined malloc alignment).</li>
+</ul></li>
+<li>ODBC:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22668); ?> (Heap buffer
over-read when a column value exceeds the driver-reported display size).</li>
+</ul></li>
+<li>Opcache:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22158); ?> (Tracing JIT
dispatches the observer begin handler through the wrong run_time_cache slot on
megamorphic calls).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22443); ?> (Tracing JIT
SIGSEGV on megamorphic dynamic calls from an undereferenced run_time_cache
map_ptr offset).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 21770); ?> (Infinite
recursion in property hook getter in opcache preloaded trait).</li>
+</ul></li>
+<li>OpenSSL:
+<ul>
+ <li>Fixed timeout for supplemental read at end of a blocking stream in SSL
stream wrapper.</li>
+</ul></li>
+<li>Intl:
+<ul>
+ <li>Fixed Locale::lookup() and locale_lookup() to return NULL instead of the
fallback locale when a language tag cannot be canonicalized.</li>
+ <li>Fixed memory leaks when calling Collator::__construct() or
Spoofchecker::__construct() twice.</li>
+ <li>Fixed memory leak when calling IntlListFormatter::__construct()
twice.</li>
+ <li>Fixed IntlChar methods leaving stale global error state after successful
calls.</li>
+</ul></li>
+<li>PDO_ODBC:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 20726); ?> (Crash with ODBC
connection pooling when the DSN carries no credentials).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22667); ?> (Heap buffer
over-read when a column value exceeds the driver-reported display size).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22666); ?> (Heap buffer
overflow when an output parameter value is longer than the declared
maxlen).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22665); ?> (Out-of-bounds
write when the ODBC driver reports a diagnostic message length beyond the error
buffer).</li>
+</ul></li>
+<li>PGSQL:
+<ul>
+ <li>Fixed <?php githubsecurityl('php/php-src', '7qpv-r5mr-78m4'); ?> (SQL
injection via E'...' backslash breakout). (CVE-2026-17543)</li>
+</ul></li>
+<li>Phar:
+<ul>
+ <li>Fixed inconsistent handling of the magic ".phar" directory. Paths such
as "/.phar" remain protected, while non-magic paths that merely start with
".phar" are handled consistently across file and directory creation, copying,
ArrayAccess, stream lookup, directory iteration and extraction.</li>
+ <li>Fixed <?php githubsecurityl('php/php-src', 'vc5h-9ppw-p5f3'); ?> (Crash
via recursive symlinks). (CVE-2026-7260)</li>
+</ul></li>
+<li>PHPDBG:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 17387); ?> (Trivial crash in
phpdbg lexer).</li>
+ <li>Fixed fleaked lowercased lookup keys in phpdbg_resolve_opline_break.</li>
+ <li>Fixed off-by-one in phpdbg_safe_class_lookup() causing class lookups to
always fail during phpdbg's signal-safe interruption path.</li>
+</ul></li>
+<li>Reflection:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22324); ?> (Ignore leading
namespace separator in ReflectionParameter::__construct()).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22441); ?>
(ReflectionClass::hasProperty() and getProperty() ignore dynamic properties
shadowing a private parent property).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22658); ?>
(ReflectionConstant::__toString() with a string value with null bytes truncates
output).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22683); ?>
(Reflection(Class)Constant::__toString() should not warn on NAN
conversions).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22681); ?>
(Reflection*::__toString() truncates on null bytes).</li>
+</ul></li>
+<li>Session:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 21314); ?> (Different
session garbage collector behavior between PHP 8.3 and PHP 8.5).</li>
+</ul></li>
+<li>SPL:
+<ul>
+ <li>Fix class_parents for classes with leading slash in non-autoload
mode.</li>
+ <li>Ignore leading back-slash in class_parents(), class_implements(), and
class_uses().</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 16217); ?>
(SplFileObject::fputcsv() on an uninitialized object segfaults).</li>
+</ul></li>
+<li>Standard:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22395); ?> (base_convert()
outputs at most 64 characters).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22678); ?> (Use-after-free
in array_multisort() when the comparator mutates the array being sorted).</li>
+</ul></li>
+<li>URI:
+<ul>
+ <li>Fixed behavior of Uri\WhatWg\Url wither methods with regards to empty
opaque hosts.</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22628); ?> (Percent-encoding
of caret in WHATWG URL paths is not performed).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22629); ?> (WHATWG
Validation error incorrect with empty host and non-empty userinfo).</li>
+</ul></li>
+<li>Zip:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22649); ?>
(ZipArchive::setCommentName() and setCommentIndex() could crash after
overwriting an entry and resetting its inherited unchanged comment).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 21705); ?>
(ZipArchive::getFromIndex() ignores ZipArchive::FL_UNCHANGED for deleted
entries).</li>
+</ul></li>
+</ul>
+<!-- }}} --></section>
+
+
+
<section class="version" id="8.5.8"><!-- {{{ 8.5.8 -->
<h3>Version 8.5.8</h3>
<b><?php release_date('02-Jul-2026'); ?></b>
@@ -230,7 +357,7 @@
</ul></li>
<li>Streams:
<ul>
- <li>Fixed bug <?php githubissuel('php/php-src', 21468); ?> (Segfault in
file_get_contents w/ a https URL and a proxy set).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 21468); ?> (Segfault in
file_get_contents w/ a https URL and a proxy set). (CVE-2026-12184)</li>
</ul></li>
<li>URI:
<ul>
@@ -1109,6 +1236,118 @@
<a id="PHP_8_4"></a>
+<section class="version" id="8.4.24"><!-- {{{ 8.4.24 -->
+<h3>Version 8.4.24</h3>
+<b><?php release_date('30-Jul-2026'); ?></b>
+<ul><li>BCMath:
+<ul>
+ <li>Fixed <?php githubsecurityl('php/php-src', 'x692-q9x7-8c3f'); ?>
(Out-of-bounds write in bccomp()). (CVE-2026-17544)</li>
+</ul></li>
+<li>Calendar:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22602); ?> (gregoriantojd()
and juliantojd() integer overflow with INT_MAX year).</li>
+</ul></li>
+<li>Date:
+<ul>
+ <li>Update timelib to 2022.17.</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 19803); ?> (Parsing a string
with a single white space does create an error).</li>
+ <li>Fixed Unix timestamps in February of the year 0 are misparsed with
@-notation.</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 11310); ?> (__debugInfo does
nothing on userland classes extending Date classes).</li>
+</ul></li>
+<li>DBA:
+<ul>
+ <li>Fixed OOB read on malformed length field in dba flatfile handler.</li>
+</ul></li>
+<li>DOM:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22570); ?> (Stack overflow
when serializing a deeply nested Dom\XMLDocument).</li>
+</ul></li>
+<li>Exif:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 11020); ?> (exif_read_data()
emits a spurious "Illegal IFD size" warning when an IFD is not followed by a
next-IFD offset).</li>
+</ul></li>
+<li>GD:
+<ul>
+ <li>Upgrade libgd. (CVE-2026-9672)</li>
+</ul></li>
+<li>Hash:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 18173); ?> (ext/hash relies
on implementation-defined malloc alignment).</li>
+</ul></li>
+<li>Intl:
+<ul>
+ <li>Fixed Locale::lookup() and locale_lookup() to return NULL instead of the
fallback locale when a language tag cannot be canonicalized.</li>
+ <li>Fixed memory leaks when calling Collator::__construct() or
Spoofchecker::__construct() twice.</li>
+ <li>Fixed IntlChar methods leaving stale global error state after successful
calls.</li>
+</ul></li>
+<li>ODBC:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22668); ?> (Heap buffer
over-read when a column value exceeds the driver-reported display size).</li>
+</ul></li>
+<li>OpenSSL:
+<ul>
+ <li>Fixed timeout for supplemental read at end of a blocking stream in SSL
stream wrapper.</li>
+</ul></li>
+<li>PDO_ODBC:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 20726); ?> (Crash with ODBC
connection pooling when the DSN carries no credentials).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22667); ?> (Heap buffer
over-read when a column value exceeds the driver-reported display size).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22666); ?> (Heap buffer
overflow when an output parameter value is longer than the declared
maxlen).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22665); ?> (Out-of-bounds
write when the ODBC driver reports a diagnostic message length beyond the error
buffer).</li>
+</ul></li>
+<li>PGSQL:
+<ul>
+ <li>Fixed <?php githubsecurityl('php/php-src', '7qpv-r5mr-78m4'); ?> (SQL
injection via E'...' backslash breakout). (CVE-2026-17543)</li>
+</ul></li>
+<li>Phar:
+<ul>
+ <li>Fixed inconsistent handling of the magic ".phar" directory. Paths such
as "/.phar" remain protected, while non-magic paths that merely start with
".phar" are handled consistently across file and directory creation, copying,
ArrayAccess, stream lookup, directory iteration and extraction.</li>
+ <li>Fixed <?php githubsecurityl('php/php-src', 'vc5h-9ppw-p5f3'); ?> (Crash
via recursive symlinks). (CVE-2026-7260)</li>
+</ul></li>
+<li>PHPDBG:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 17387); ?> (Trivial crash in
phpdbg lexer).</li>
+ <li>Fixed fleaked lowercased lookup keys in phpdbg_resolve_opline_break.</li>
+ <li>Fixed off-by-one in phpdbg_safe_class_lookup() causing class lookups to
always fail during phpdbg's signal-safe interruption path.</li>
+</ul></li>
+<li>Reflection:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22324); ?> (Ignore leading
namespace separator in ReflectionParameter::__construct()).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22441); ?>
(ReflectionClass::hasProperty() and getProperty() ignore dynamic properties
shadowing a private parent property).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22658); ?>
(ReflectionConstant::__toString() with a string value with null bytes truncates
output).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22681); ?>
(Reflection*::__toString() truncates on null bytes).</li>
+</ul></li>
+<li>Session:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 21314); ?> (Different
session garbage collector behavior between PHP 8.3 and PHP 8.5).</li>
+</ul></li>
+<li>SPL:
+<ul>
+ <li>Fix class_parents for classes with leading slash in non-autoload
mode.</li>
+ <li>Ignore leading back-slash in class_parents(), class_implements(), and
class_uses().</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 16217); ?>
(SplFileObject::fputcsv() on an uninitialized object segfaults).</li>
+</ul></li>
+<li>Standard:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22360); ?>
(convert.base64-encode corruption on incremental flush).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22395); ?> (base_convert()
outputs at most 64 characters).</li>
+ <li>Fixed integer overflow in getimagesize() and getimagesizefromstring()
when parsing an IFF chunk with a size of INT_MAX.</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22678); ?> (Use-after-free
in array_multisort() when the comparator mutates the array being sorted).</li>
+</ul></li>
+<li>Streams:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22617); ?> (persistent
stream keys truncated at null bytes, causing distinct abstract unix domain
sockets to share a resource).</li>
+</ul></li>
+<li>Zip:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22649); ?>
(ZipArchive::setCommentName() and setCommentIndex() could crash after
overwriting an entry and resetting its inherited unchanged comment).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 21705); ?>
(ZipArchive::getFromIndex() ignores ZipArchive::FL_UNCHANGED for deleted
entries).</li>
+</ul></li>
+</ul>
+<!-- }}} --></section>
+
+
+
<section class="version" id="8.4.23"><!-- {{{ 8.4.23 -->
<h3>Version 8.4.23</h3>
<b><?php release_date('03-Jul-2026'); ?></b>
@@ -1155,7 +1394,7 @@
</ul></li>
<li>OpenSSL:
<ul>
- <li>Fixed bug <?php githubissuel('php/php-src', 22187); ?> (Memory
corruption (zend_mm_heap corrupted) in openssl_encrypt with AES-WRAP-PAD).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 22187); ?> (Memory
corruption (zend_mm_heap corrupted) in openssl_encrypt with AES-WRAP-PAD).
(CVE-2026-14355)</li>
</ul></li>
<li>Phar:
<ul>
@@ -1313,7 +1552,7 @@
</ul></li>
<li>Streams:
<ul>
- <li>Fixed bug <?php githubissuel('php/php-src', 21468); ?> (Segfault in
file_get_contents w/ a https URL and a proxy set).</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 21468); ?> (Segfault in
file_get_contents w/ a https URL and a proxy set). (CVE-2026-12184)</li>
</ul></li>
<li>XSL:
<ul>
@@ -3506,6 +3745,30 @@
<a id="PHP_8_3"></a>
+<section class="version" id="8.3.33"><!-- {{{ 8.3.33 -->
+<h3>Version 8.3.33</h3>
+<b><?php release_date('30-Jul-2026'); ?></b>
+<ul><li>Date:
+<ul>
+ <li>Fixed leak on double DatePeriod::__construct() call.</li>
+</ul></li>
+<li>GD:
+<ul>
+ <li>Upgrade libgd. (CVE-2026-9672)</li>
+</ul></li>
+<li>PGSQL:
+<ul>
+ <li>Fixed <?php githubsecurityl('php/php-src', '7qpv-r5mr-78m4'); ?> (SQL
injection via E'...' backslash breakout). (CVE-2026-17543)</li>
+</ul></li>
+<li>Phar:
+<ul>
+ <li>Fixed <?php githubsecurityl('php/php-src', 'vc5h-9ppw-p5f3'); ?> (Crash
via recursive symlinks). (CVE-2026-7260)</li>
+</ul></li>
+</ul>
+<!-- }}} --></section>
+
+
+
<section class="version" id="8.3.32"><!-- {{{ 8.3.32 -->
<h3>Version 8.3.32</h3>
<b><?php release_date('02-Jul-2026'); ?></b>
@@ -6231,6 +6494,30 @@
<a id="PHP_8_2"></a>
+<section class="version" id="8.2.33"><!-- {{{ 8.2.33 -->
+<h3>Version 8.2.33</h3>
+<b><?php release_date('30-Jul-2026'); ?></b>
+<ul><li>Date:
+<ul>
+ <li>Fixed leak on double DatePeriod::__construct() call.</li>
+</ul></li>
+<li>GD:
+<ul>
+ <li>Upgrade libgd. (CVE-2026-9672)</li>
+</ul></li>
+<li>PGSQL:
+<ul>
+ <li>Fixed <?php githubsecurityl('php/php-src', '7qpv-r5mr-78m4'); ?> (SQL
injection via E'...' backslash breakout). (CVE-2026-17543)</li>
+</ul></li>
+<li>Phar:
+<ul>
+ <li>Fixed <?php githubsecurityl('php/php-src', 'vc5h-9ppw-p5f3'); ?> (Crash
via recursive symlinks). (CVE-2026-7260)</li>
+</ul></li>
+</ul>
+<!-- }}} --></section>
+
+
+
<section class="version" id="8.2.32"><!-- {{{ 8.2.32 -->
<h3>Version 8.2.32</h3>
<b><?php release_date('02-Jul-2026'); ?></b>
diff --git a/public/archive/2026.php b/public/archive/2026.php
index 7e5ef1b4be..82d4c513d6 100644
--- a/public/archive/2026.php
+++ b/public/archive/2026.php
@@ -5,7 +5,7 @@
$_SERVER['BASE_PAGE'] = 'archive/2026.php';
require_once __DIR__ . '/../../include/prepend.inc';
news_archive_sidebar();
-site_header("News Archive - 2026");
+site_header("News Archive - 2026", ['cache' => true, 'cache_control' => 15 *
60]);
?>
<h1>News Archive - 2026</h1>
diff --git a/public/archive/archive.xml b/public/archive/archive.xml
index f9a9d1af80..68b70ac5b9 100644
--- a/public/archive/archive.xml
+++ b/public/archive/archive.xml
@@ -9,6 +9,14 @@
<uri>http://php.net/contact</uri>
<email>[email protected]</email>
</author>
+ <xi:include href="entries/2026-07-30-5.xml"/>
+ <xi:include href="entries/2026-07-30-4.xml"/>
+ <xi:include href="entries/2026-07-30-3.xml"/>
+ <xi:include href="entries/2026-07-30-2.xml"/>
+ <xi:include href="entries/2026-07-30-1.xml"/>
+ <xi:include href="entries/2026-07-16-1.xml"/>
+ <xi:include href="entries/2026-07-13-1.xml"/>
+ <xi:include href="entries/2026-07-07-1.xml"/>
<xi:include href="entries/2026-07-02-5.xml"/>
<xi:include href="entries/2026-07-02-4.xml"/>
<xi:include href="entries/2026-07-02-3.xml"/>
diff --git a/public/archive/entries/2026-07-07-1.xml
b/public/archive/entries/2026-07-07-1.xml
new file mode 100644
index 0000000000..acbfa7f02e
--- /dev/null
+++ b/public/archive/entries/2026-07-07-1.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:default="http://php.net/ns/news">
+ <title>PHP Tek 2027</title>
+ <id>https://www.php.net/archive/2026.php#2026-07-07-1</id>
+ <published>2026-07-07T16:47:27+00:00</published>
+ <updated>2026-07-07T16:47:27+00:00</updated>
+ <link href="https://www.php.net/conferences/index.php#2026-07-07-1"
rel="alternate" type="text/html"/>
+ <link href="https://phptek.io" rel="via" type="text/html"/>
+ <default:finalTeaserDate
xmlns="http://php.net/ns/news">2027-08-31</default:finalTeaserDate>
+ <category term="cfp" label="Call for Papers"/>
+ <default:newsImage xmlns="http://php.net/ns/news" link="https://phptek.io"
title="PHP Tek 2027 Logo">php-tek-2027.png</default:newsImage>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ <p>Join us for the 19th Annual Web Developer Conference, PHP Tek 2027,
April 27-29 2026.</p>
+
+ <p>PHP Tek combines leadership, expertise, and networking in one event. A
relaxing atmosphere for tech leaders and developers to share, learn and grow
professionally while also providing you with the knowledge to solve your
everyday problems.</p>
+
+ <p>We are the longest-running web developer conference in the United
States, focusing on the PHP programming language. The event is broken up into
multiple days. The main conference happens over the course of 3 days (April
27-29) and includes keynotes, talks, and networking options. It will be broken
into three tracks and will cover a range of topics. There will be two
dedicated PHP Tracks, and then each day will have a different 3rd track
(JS/Laravel/DevOps)</p>
+
+ <p>Head over to <a href="https://phptek.io">https://phptek.io</a> and get
yours today!</p>
+ </div>
+ </content>
+</entry>
diff --git a/public/archive/entries/2026-07-13-1.xml
b/public/archive/entries/2026-07-13-1.xml
new file mode 100644
index 0000000000..870a4491e5
--- /dev/null
+++ b/public/archive/entries/2026-07-13-1.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:default="http://php.net/ns/news">
+ <title>International PHP Conference Munich 2026</title>
+ <id>https://www.php.net/archive/2026.php#2026-07-13-1</id>
+ <published>2026-07-13T17:01:37+00:00</published>
+ <updated>2026-07-13T17:01:37+00:00</updated>
+ <link href="https://www.php.net/conferences/index.php#2026-07-13-1"
rel="alternate" type="text/html"/>
+ <link href="https://phpconference.com/munich/" rel="via" type="text/html"/>
+ <default:finalTeaserDate
xmlns="http://php.net/ns/news">2026-10-26</default:finalTeaserDate>
+ <category term="conferences" label="Conference announcement"/>
+ <default:newsImage xmlns="http://php.net/ns/news"
link="https://phpconference.com/munich/" title="International PHP Conference
Munich 2026">IPC.png</default:newsImage>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ <p>
+ <a href="https://phpconference.com/munich/">The International PHP
Conference</a>
+ is the world's first PHP conference and has stood for more than two
decades for top-notch
+ pragmatic expertise in PHP and web technologies. At the IPC,
internationally renowned
+ experts from the PHP industry meet up with PHP users and developers
from large and small
+ companies. Here is the place where concepts emerge and ideas are born
– the IPC signifies
+ knowledge transfer at the highest level.
+ </p>
+
+ <p>Basic facts:</p>
+
+ <p>
+ <strong>Date: October 26 – 30, 2026</strong>
+ </p>
+
+ <p>
+ <strong>Location: Holiday Inn Munich City Centre, Munich or
Online</strong>
+ </p>
+
+ <p>Highlights:</p>
+ <ul>
+ <li>60+ best practice sessions</li>
+ <li>50+ international top speakers</li>
+ <li>PHPower: Hands-on Power Workshops</li>
+ <li>2-Day Bootcamp on Thursday and Friday</li>
+ <li>Expo with exciting exhibitors on October 27 & 28</li>
+ <li>All inclusive: Changing buffets, snacks & refreshing
drinks</li>
+ <li>Official certificate for attendees</li>
+ <li>Free Goodies: Developer bag, T-Shirt, magazines etc.</li>
+ <li>Exclusive networking events</li>
+ </ul>
+
+ <p>
+ For further information on the International PHP Conference Munich
visit:
+ <a
href="https://phpconference.com/munich/">https://phpconference.com/munich/</a>
+ </p>
+ </div>
+ </content>
+</entry>
diff --git a/public/archive/entries/2026-07-16-1.xml
b/public/archive/entries/2026-07-16-1.xml
new file mode 100644
index 0000000000..6c8cef04c1
--- /dev/null
+++ b/public/archive/entries/2026-07-16-1.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom">
+ <title>PHP 8.6.0 Alpha 2 available for testing</title>
+ <id>https://www.php.net/archive/2026.php#2026-07-16-1</id>
+ <published>2026-07-16T13:28:29+00:00</published>
+ <updated>2026-07-16T13:28:29+00:00</updated>
+ <link href="https://www.php.net/index.php#2026-07-16-1" rel="alternate"
type="text/html"/>
+ <link href="https://www.php.net/archive/2026.php#2026-07-16-1" rel="via"
type="text/html"/>
+ <category term="frontpage" label="PHP.net frontpage news"/>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ <p>The PHP team is pleased to announce the second testing release of PHP
8.6.0, Alpha 2. This continues the PHP 8.6 release cycle, the rough outline of
which is specified in the <a href="https://wiki.php.net/todo/php86">PHP
Wiki</a>.</p>
+ <p>For source downloads of PHP 8.6.0 Alpha 2 please visit the <a
href="https://downloads.php.net/~svpernova09/">download page</a>.</p>
+ <p>Please carefully test this version and report any issues found in the
<a
href="https://github.com/php/php-src/issues/new?template=bug_report.yml">GitHub
Issues</a>.</p>
+ <p><strong>Please DO NOT use this version in production, it is an early
test version.</strong></p>
+ <p>For more information on the new features and other changes, you can
read the <a
href="https://github.com/php/php-src/blob/php-8.6.0alpha2/NEWS">NEWS</a> file,
or the <a
href="https://github.com/php/php-src/blob/php-8.6.0alpha2/UPGRADING">UPGRADING</a>
file for a complete list of upgrading notes. These files can also be found in
the release archive.</p>
+ <p>The next release will be Alpha 3, planned for 30 July 2026.</p>
+ <p>The signatures for the release can be found in the <a
href="https://gist.github.com/svpernova09/9fe74e859313cf4dee4953fae81b558a">manifest</a>
or on the <a href="https://www.php.net/pre-release-builds.php">pre-release
builds</a> page.</p>
+ <p>Thank you for helping us make PHP better.</p>
+ </div>
+ </content>
+</entry>
diff --git a/public/archive/entries/2026-07-30-1.xml
b/public/archive/entries/2026-07-30-1.xml
new file mode 100644
index 0000000000..9d916ec535
--- /dev/null
+++ b/public/archive/entries/2026-07-30-1.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom">
+ <title>PHP 8.2.33 Released!</title>
+ <id>https://www.php.net/archive/2026.php#2026-07-30-1</id>
+ <published>2026-07-30T11:00:24+00:00</published>
+ <updated>2026-07-30T11:00:24+00:00</updated>
+ <link href="https://www.php.net/index.php#2026-07-30-1" rel="alternate"
type="text/html"/>
+ <link href="https://www.php.net/archive/2026.php#2026-07-30-1" rel="via"
type="text/html"/>
+ <category term="releases" label="New PHP release"/>
+ <category term="frontpage" label="PHP.net frontpage news"/>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><p>The PHP development team
announces the immediate availability of PHP 8.2.33. This is a security
release.</p>
+
+<p>All PHP 8.2 users are encouraged to upgrade to this version.</p>
+
+<p>For source downloads of PHP 8.2.33 please visit our <a
href="https://www.php.net/downloads.php">downloads page</a>,
+Windows source and binaries can also be found <a
href="https://www.php.net/downloads.php?os=windows&version=8.2">there</a>.
+The list of changes is recorded in the <a
href="https://www.php.net/ChangeLog-8.php#8.2.33">ChangeLog</a>.
+</p> </div>
+ </content>
+</entry>
diff --git a/public/archive/entries/2026-07-30-2.xml
b/public/archive/entries/2026-07-30-2.xml
new file mode 100644
index 0000000000..3c57d3c74d
--- /dev/null
+++ b/public/archive/entries/2026-07-30-2.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom">
+ <title>PHP 8.5.9 Released!</title>
+ <id>https://www.php.net/archive/2026.php#2026-07-30-2</id>
+ <published>2026-07-30T11:38:53+00:00</published>
+ <updated>2026-07-30T11:38:53+00:00</updated>
+ <link href="https://www.php.net/index.php#2026-07-30-2" rel="alternate"
type="text/html"/>
+ <link href="https://www.php.net/archive/2026.php#2026-07-30-2" rel="via"
type="text/html"/>
+ <category term="releases" label="New PHP release"/>
+ <category term="frontpage" label="PHP.net frontpage news"/>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><p>The PHP development team
announces the immediate availability of PHP 8.5.9. This is a security
release.</p>
+
+<p>All PHP 8.5 users are encouraged to upgrade to this version.</p>
+
+<p>For source downloads of PHP 8.5.9 please visit our <a
href="https://www.php.net/downloads.php">downloads page</a>,
+Windows source and binaries can also be found <a
href="https://www.php.net/downloads.php?os=windows&version=8.5">there</a>.
+The list of changes is recorded in the <a
href="https://www.php.net/ChangeLog-8.php#8.5.9">ChangeLog</a>.
+</p> </div>
+ </content>
+</entry>
diff --git a/public/archive/entries/2026-07-30-3.xml
b/public/archive/entries/2026-07-30-3.xml
new file mode 100644
index 0000000000..4e1bd1f910
--- /dev/null
+++ b/public/archive/entries/2026-07-30-3.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom">
+ <title>PHP 8.6.0 Alpha 3 available for testing</title>
+ <id>https://www.php.net/archive/2026.php#2026-07-30-3</id>
+ <published>2026-07-30T13:24:32+00:00</published>
+ <updated>2026-07-30T13:24:32+00:00</updated>
+ <link href="https://www.php.net/index.php#2026-07-30-3" rel="alternate"
type="text/html"/>
+ <link href="https://www.php.net/archive/2026.php#2026-07-30-3" rel="via"
type="text/html"/>
+ <category term="frontpage" label="PHP.net frontpage news"/>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ <p>The PHP team is pleased to announce the second testing release of PHP
8.6.0, Alpha 3. This continues the PHP 8.6 release cycle, the rough outline of
which is specified in the <a href="https://wiki.php.net/todo/php86">PHP
Wiki</a>.</p>
+ <p>For source downloads of PHP 8.6.0 Alpha 3 please visit the <a
href="https://downloads.php.net/~mbeccati/">download page</a>.</p>
+ <p>Please carefully test this version and report any issues found in the
<a
href="https://github.com/php/php-src/issues/new?template=bug_report.yml">GitHub
Issues</a>.</p>
+ <p><strong>Please DO NOT use this version in production, it is an early
test version.</strong></p>
+ <p>For more information on the new features and other changes, you can
read the <a
href="https://github.com/php/php-src/blob/php-8.6.0alpha3/NEWS">NEWS</a> file,
or the <a
href="https://github.com/php/php-src/blob/php-8.6.0alpha3/UPGRADING">UPGRADING</a>
file for a complete list of upgrading notes. These files can also be found in
the release archive.</p>
+ <p>The next release will be Beta 1, planned for 13 August 2026.</p>
+ <p>The signatures for the release can be found in the <a
href="https://gist.github.com/mbeccati/a78ae3c3bafa22839c619d1c81d286ae">manifest</a>
or on the <a href="https://www.php.net/pre-release-builds.php">pre-release
builds</a> page.</p>
+ <p>Thank you for helping us make PHP better.</p>
+ </div>
+ </content>
+</entry>
diff --git a/public/archive/entries/2026-07-30-4.xml
b/public/archive/entries/2026-07-30-4.xml
new file mode 100644
index 0000000000..58a5e1b1d1
--- /dev/null
+++ b/public/archive/entries/2026-07-30-4.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom">
+ <title>PHP 8.3.33 Released!</title>
+ <id>https://www.php.net/archive/2026.php#2026-07-30-4</id>
+ <published>2026-07-30T14:48:58+00:00</published>
+ <updated>2026-07-30T14:48:58+00:00</updated>
+ <link href="https://www.php.net/index.php#2026-07-30-4" rel="alternate"
type="text/html"/>
+ <link href="https://www.php.net/archive/2026.php#2026-07-30-4" rel="via"
type="text/html"/>
+ <category term="releases" label="New PHP release"/>
+ <category term="frontpage" label="PHP.net frontpage news"/>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><p>The PHP development team
announces the immediate availability of PHP 8.3.33. This is a security
release.</p>
+
+<p>All PHP 8.3 users are encouraged to upgrade to this version.</p>
+
+<p>For source downloads of PHP 8.3.33 please visit our <a
href="https://www.php.net/downloads.php">downloads page</a>,
+Windows source and binaries can also be found <a
href="https://www.php.net/downloads.php?os=windows&version=8.3">there</a>.
+The list of changes is recorded in the <a
href="https://www.php.net/ChangeLog-8.php#8.3.33">ChangeLog</a>.
+</p> </div>
+ </content>
+</entry>
diff --git a/public/archive/entries/2026-07-30-5.xml
b/public/archive/entries/2026-07-30-5.xml
new file mode 100644
index 0000000000..5d571ac51e
--- /dev/null
+++ b/public/archive/entries/2026-07-30-5.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom">
+ <title>PHP 8.4.24 Released!</title>
+ <id>https://www.php.net/archive/2026.php#2026-07-30-5</id>
+ <published>2026-07-30T14:55:16+00:00</published>
+ <updated>2026-07-30T14:55:16+00:00</updated>
+ <link href="https://www.php.net/index.php#2026-07-30-5" rel="alternate"
type="text/html"/>
+ <link href="https://www.php.net/archive/2026.php#2026-07-30-5" rel="via"
type="text/html"/>
+ <category term="releases" label="New PHP release"/>
+ <category term="frontpage" label="PHP.net frontpage news"/>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><p>The PHP development team
announces the immediate availability of PHP 8.4.24. This is a security
release.</p>
+
+<p>All PHP 8.4 users are encouraged to upgrade to this version.</p>
+
+<p>For source downloads of PHP 8.4.24 please visit our <a
href="https://www.php.net/downloads.php">downloads page</a>,
+Windows source and binaries can also be found <a
href="https://www.php.net/downloads.php?os=windows&version=8.4">there</a>.
+The list of changes is recorded in the <a
href="https://www.php.net/ChangeLog-8.php#8.4.24">ChangeLog</a>.
+</p> </div>
+ </content>
+</entry>
diff --git a/public/backend/win-releases.json b/public/backend/win-releases.json
index 6ef58ee1ef..b778aedd0d 100644
--- a/public/backend/win-releases.json
+++ b/public/backend/win-releases.json
@@ -256,342 +256,342 @@
}
},
"8.2": {
- "version": "8.2.30",
+ "version": "8.2.33",
"ts-vs16-x64": {
- "mtime": "2025-12-16T18:06:10+00:00",
+ "mtime": "2026-07-28T11:35:03+00:00",
"zip": {
- "path": "php-8.2.30-Win32-vs16-x64.zip",
- "size": "30.49MB",
- "sha256":
"abf3b5c31dc93fc0141cf7844e3322fd862b8510a091099599a16b3847fc58c1"
+ "path": "php-8.2.33-Win32-vs16-x64.zip",
+ "size": "32.01MB",
+ "sha256":
"7d2568dfaad6ac1391e57994f52c8aed835baf9e6d89f4328770e2843311291c"
},
"debug_pack": {
- "path": "php-debug-pack-8.2.30-Win32-vs16-x64.zip",
- "size": "25.68MB",
- "sha256":
"1f19f442062dc8b53a8dcfc6962fcab31d80163cb9c26f7eb031a08664882f1c"
+ "path": "php-debug-pack-8.2.33-Win32-vs16-x64.zip",
+ "size": "26.22MB",
+ "sha256":
"dc801832634f3dd84ace7092bb88ce157bffe4bc0743542eaef1f272ed5e70b0"
},
"devel_pack": {
- "path": "php-devel-pack-8.2.30-Win32-vs16-x64.zip",
+ "path": "php-devel-pack-8.2.33-Win32-vs16-x64.zip",
"size": "1.24MB",
- "sha256":
"5c2cf253941779a1a917b6018ea12c86f552ba0e111fd5f6579ae686381604ed"
+ "sha256":
"46c00fc49b8cf6c35a4a8b5269114b1da90ef3a001f5ee1cd577f7c12ab6aad9"
}
},
"source": {
- "path": "php-8.2.30-src.zip",
- "size": "25.81MB",
- "sha256":
"9c8bebd700b66292d67da08484d42a4d9b57206b99903bcd1ca163355f1500fe"
+ "path": "php-8.2.33-src.zip",
+ "size": "25.92MB",
+ "sha256":
"9c611ab5f3fac588ff654b405a82b964a3d433e8268e57bc135abebfaf0494b8"
},
"test_pack": {
- "path": "php-test-pack-8.2.30.zip",
+ "path": "php-test-pack-8.2.33.zip",
"size": "15.89MB",
- "sha256":
"f5d43c4ff6148a02d1f387f6801223ab9360f9a0f4fdd781bc62a12f2106147f"
+ "sha256":
"c969ebfcd5f397ccaa0e74b611c0d2a2b030e1cba3cf3f90891423547b304f8a"
},
"ts-vs16-x86": {
- "mtime": "2025-12-16T18:06:08+00:00",
+ "mtime": "2026-07-28T11:35:03+00:00",
"zip": {
- "path": "php-8.2.30-Win32-vs16-x86.zip",
- "size": "27.25MB",
- "sha256":
"e380bc8e635b4c7e5ff423465e71e2cc3f5b7fe7cea1ee301dcea658fe1029de"
+ "path": "php-8.2.33-Win32-vs16-x86.zip",
+ "size": "28.76MB",
+ "sha256":
"329eb8d71b6d186e8b01d500a14021eb7d430e0fdd83f69802beefd31150bf18"
},
"debug_pack": {
- "path": "php-debug-pack-8.2.30-Win32-vs16-x86.zip",
- "size": "25.52MB",
- "sha256":
"2e5e9bd61451049f789b2fde26f0c76e15f59ac111718faec0a4e74a5ce5c33d"
+ "path": "php-debug-pack-8.2.33-Win32-vs16-x86.zip",
+ "size": "26.17MB",
+ "sha256":
"49ff0c3812dd2e36480abdd8ddaea905091e029a9d43e046486dd32cab2e5009"
},
"devel_pack": {
- "path": "php-devel-pack-8.2.30-Win32-vs16-x86.zip",
+ "path": "php-devel-pack-8.2.33-Win32-vs16-x86.zip",
"size": "1.24MB",
- "sha256":
"bbc007d2500a145181d8c09bec7943ddbfc9595812a02a797129cfe4ca5d8ffd"
+ "sha256":
"9de2041263c9e10096423a89b17bdc6d4d15e44a8d2b86a08dd20236f9f4ac9d"
}
},
"nts-vs16-x64": {
- "mtime": "2025-12-16T18:06:08+00:00",
+ "mtime": "2026-07-28T11:35:03+00:00",
"zip": {
- "path": "php-8.2.30-nts-Win32-vs16-x64.zip",
- "size": "30.38MB",
- "sha256":
"8a6e409adb5f7fb196c07315c69195c4eb87eec8acae2e74a0e04ec50745a055"
+ "path": "php-8.2.33-nts-Win32-vs16-x64.zip",
+ "size": "31.9MB",
+ "sha256":
"d0bd189522fa50255ee94ed4b340ed4330f5ae33a90a74205275b0f0b221d388"
},
"debug_pack": {
- "path": "php-debug-pack-8.2.30-nts-Win32-vs16-x64.zip",
- "size": "25.74MB",
- "sha256":
"1047dc844372a65fb3e1a0a9939c61f0e9de54bd07cf006ada66527f887eaad1"
+ "path": "php-debug-pack-8.2.33-nts-Win32-vs16-x64.zip",
+ "size": "26.15MB",
+ "sha256":
"3af565b068310231d37f3670fa741e32cfc238ad3a18acb37067a9470e1f049a"
},
"devel_pack": {
- "path": "php-devel-pack-8.2.30-nts-Win32-vs16-x64.zip",
+ "path": "php-devel-pack-8.2.33-nts-Win32-vs16-x64.zip",
"size": "1.24MB",
- "sha256":
"1d5eadf5f5ef68daaf0ba543ee9fdbf669def165432cc9e6e53aaf45dc4d3e55"
+ "sha256":
"d4d0da6e6f1ad3f9e058262261fc43d7fa329b212207e4bfb2a39ad0b39ee891"
}
},
"nts-vs16-x86": {
- "mtime": "2025-12-16T18:06:08+00:00",
+ "mtime": "2026-07-28T11:35:03+00:00",
"zip": {
- "path": "php-8.2.30-nts-Win32-vs16-x86.zip",
- "size": "27.27MB",
- "sha256":
"6f00e490c4cad59f0ebe2f6891208e0630a14af54e81070b20480ecc5f67912b"
+ "path": "php-8.2.33-nts-Win32-vs16-x86.zip",
+ "size": "28.78MB",
+ "sha256":
"8732dac6084bcad5e8fc363efcd9bdc50afbfc469bc858eeee92da05bd21d8cc"
},
"debug_pack": {
- "path": "php-debug-pack-8.2.30-nts-Win32-vs16-x86.zip",
- "size": "25.86MB",
- "sha256":
"64d09a696319b1add4e24f53db00c5a970dc13d308d13d431835bfd4e98e9499"
+ "path": "php-debug-pack-8.2.33-nts-Win32-vs16-x86.zip",
+ "size": "26.53MB",
+ "sha256":
"1c3caf9fa33dfa14a3cfb0629a18072100561d6fb680c0c1fcc29197e0b0361c"
},
"devel_pack": {
- "path": "php-devel-pack-8.2.30-nts-Win32-vs16-x86.zip",
+ "path": "php-devel-pack-8.2.33-nts-Win32-vs16-x86.zip",
"size": "1.24MB",
- "sha256":
"5073e9740b7fd311812e0e3b9cee29f86ef8e678c757504965268945a5e63d76"
+ "sha256":
"5544c533374fc0acb211f30971e1da034e0b77d1284abeff484e00bf6c6777a3"
}
}
},
"8.3": {
- "version": "8.3.30",
+ "version": "8.3.33",
"ts-vs16-x64": {
- "mtime": "2026-01-13T23:11:40+00:00",
+ "mtime": "2026-07-28T19:05:03+00:00",
"zip": {
- "path": "php-8.3.30-Win32-vs16-x64.zip",
- "size": "30.91MB",
- "sha256":
"606c69912d7a1fbd9215ad5b6941e081d0cc12fce7f00b95d612da032244f45f"
+ "path": "php-8.3.33-Win32-vs16-x64.zip",
+ "size": "32.43MB",
+ "sha256":
"b089e370ff99eb7038b0d22617dec2f3a1d0e93ca26b11fd218f2f5b60422271"
},
"debug_pack": {
- "path": "php-debug-pack-8.3.30-Win32-vs16-x64.zip",
- "size": "30.46MB",
- "sha256":
"d907554159f043fbc37be0de22e63177a2e3a9201dc5931add47ec420a53728d"
+ "path": "php-debug-pack-8.3.33-Win32-vs16-x64.zip",
+ "size": "31.03MB",
+ "sha256":
"8f5dc9cfc477a0b58f74c025ed866d8a4711e3b6c14fb9be2c5eb8bc67c4ffb0"
},
"devel_pack": {
- "path": "php-devel-pack-8.3.30-Win32-vs16-x64.zip",
+ "path": "php-devel-pack-8.3.33-Win32-vs16-x64.zip",
"size": "1.26MB",
- "sha256":
"00d834344e841ee08a8e4067cfe0425313677dbb7e0a6b9fc99a510194e922c5"
+ "sha256":
"d58cedfa76b74b49f88ee54d25426700a27dad76dbad4732440cf28ca8267a7c"
}
},
"source": {
- "path": "php-8.3.30-src.zip",
- "size": "26.76MB",
- "sha256":
"8445a8b612630d2934df066c6f73aaa48703c2242392b79740eeb8f79728be22"
+ "path": "php-8.3.33-src.zip",
+ "size": "26.87MB",
+ "sha256":
"89d28bf8c208b5d25962c87c07ef9fd1c3a9198fc879b6479bdb6511b275a5af"
},
"test_pack": {
- "path": "php-test-pack-8.3.30.zip",
+ "path": "php-test-pack-8.3.33.zip",
"size": "16.71MB",
- "sha256":
"df76b27cde1ab240e20c92253da10abaa4a3581106d3e4bb90580bb856955a41"
+ "sha256":
"f21a2eb6f3d6300d44686afbff826658b1bcd18e148d8c7eb928124340c21542"
},
"ts-vs16-x86": {
- "mtime": "2026-01-13T23:11:40+00:00",
+ "mtime": "2026-07-28T19:05:03+00:00",
"zip": {
- "path": "php-8.3.30-Win32-vs16-x86.zip",
- "size": "27.61MB",
- "sha256":
"c34ce725f12c2f567e381896a54c29241748850d7b362085151e0a3529c6ccad"
+ "path": "php-8.3.33-Win32-vs16-x86.zip",
+ "size": "29.12MB",
+ "sha256":
"ba37894e00a37012631ffa062556e85a64cecaa44746c6c0b65f1a0915e869bf"
},
"debug_pack": {
- "path": "php-debug-pack-8.3.30-Win32-vs16-x86.zip",
- "size": "30.27MB",
- "sha256":
"922d877593b4f6e54225265db6b965ed6a5bc6803920d8bec0f436788d665ad9"
+ "path": "php-debug-pack-8.3.33-Win32-vs16-x86.zip",
+ "size": "30.83MB",
+ "sha256":
"cf2286c0d8012b57b41d08a1e0e52fabc2509185ef65189678e89590686b3afa"
},
"devel_pack": {
- "path": "php-devel-pack-8.3.30-Win32-vs16-x86.zip",
+ "path": "php-devel-pack-8.3.33-Win32-vs16-x86.zip",
"size": "1.26MB",
- "sha256":
"71e80af94434fd1aa00e778ed2ba39096a07253751e186bda3a3113a9fafd729"
+ "sha256":
"03ad5c05b272e1b6ebfcc9876c59d2d184c3cb3ed90a42b75e7c6e8e01ab62aa"
}
},
"nts-vs16-x64": {
- "mtime": "2026-01-13T23:11:40+00:00",
+ "mtime": "2026-07-28T19:05:03+00:00",
"zip": {
- "path": "php-8.3.30-nts-Win32-vs16-x64.zip",
- "size": "30.76MB",
- "sha256":
"42637b42b38b9c0d731e59c5cb8b755693a01b110cd2f31951f67de5cb4cd129"
+ "path": "php-8.3.33-nts-Win32-vs16-x64.zip",
+ "size": "32.28MB",
+ "sha256":
"534399107056313246f424adbbb7937337e40fbbf6aa7bc26287ba9cfd2e4a2a"
},
"debug_pack": {
- "path": "php-debug-pack-8.3.30-nts-Win32-vs16-x64.zip",
- "size": "30.56MB",
- "sha256":
"b8641a6b9d56c37c206e3db7b753f3d0363ac160b8af4b4b14d5db8f747e89bc"
+ "path": "php-debug-pack-8.3.33-nts-Win32-vs16-x64.zip",
+ "size": "31.02MB",
+ "sha256":
"6dd2caaa50b16617bc5f987f2d73dd3d542e0a91e633213c3427022a22ecb216"
},
"devel_pack": {
- "path": "php-devel-pack-8.3.30-nts-Win32-vs16-x64.zip",
+ "path": "php-devel-pack-8.3.33-nts-Win32-vs16-x64.zip",
"size": "1.26MB",
- "sha256":
"1d70c81e6aa835104122519c1a96ef653cc6d4e255025efeb79699dc79285c2f"
+ "sha256":
"49fa1880cea4233b8c6128c84f01a1d5fc4de7e9c97854b1b832eef37f558a1c"
}
},
"nts-vs16-x86": {
- "mtime": "2026-01-13T23:11:40+00:00",
+ "mtime": "2026-07-28T19:05:03+00:00",
"zip": {
- "path": "php-8.3.30-nts-Win32-vs16-x86.zip",
- "size": "27.62MB",
- "sha256":
"0fa4d5d4711ec28df0909ef20092407a8480c52b0e2587fc0f280379d2ce61ce"
+ "path": "php-8.3.33-nts-Win32-vs16-x86.zip",
+ "size": "29.14MB",
+ "sha256":
"590cc24bed2b3ce52d0ca387d7912e9500715848af834d5346b98d3a81892e07"
},
"debug_pack": {
- "path": "php-debug-pack-8.3.30-nts-Win32-vs16-x86.zip",
- "size": "30.55MB",
- "sha256":
"3e213ffc473694992f8b7ea5cd54e2fe1a92cbcc688c5a6fa3208d93645c6bad"
+ "path": "php-debug-pack-8.3.33-nts-Win32-vs16-x86.zip",
+ "size": "31.24MB",
+ "sha256":
"3e38b8079fcfb581c33247cfb46304b73a77512c3c2c9d7efb834ec18f9e7c70"
},
"devel_pack": {
- "path": "php-devel-pack-8.3.30-nts-Win32-vs16-x86.zip",
+ "path": "php-devel-pack-8.3.33-nts-Win32-vs16-x86.zip",
"size": "1.26MB",
- "sha256":
"2431f8b4ce2f30172976060c05787e045a4265967750e1c1138cf2769ca8cd1c"
+ "sha256":
"1d5fb322dd66626141b952dc417f0993205c2dc6ddb7448eed0e7ad893b043d7"
}
}
},
"8.4": {
- "version": "8.4.19",
+ "version": "8.4.24",
"ts-vs17-x64": {
- "mtime": "2026-03-10T16:11:02+00:00",
+ "mtime": "2026-07-29T06:35:03+00:00",
"zip": {
- "path": "php-8.4.19-Win32-vs17-x64.zip",
- "size": "32.5MB",
- "sha256":
"145712ab250a8a1855ade60b7ce8dbe177064f61f31c3edda8cb2af8400e1e8f"
+ "path": "php-8.4.24-Win32-vs17-x64.zip",
+ "size": "33.48MB",
+ "sha256":
"7b57fc9840273ab153834d0e2bd06e0bcf4fead36e381182b4b8fe9cedff3174"
},
"debug_pack": {
- "path": "php-debug-pack-8.4.19-Win32-vs17-x64.zip",
- "size": "37.66MB",
- "sha256":
"766c9def2c4e4b3439e6add687d7ae35bfbc48b55fb90edaa3cd6d777a43784b"
+ "path": "php-debug-pack-8.4.24-Win32-vs17-x64.zip",
+ "size": "39.42MB",
+ "sha256":
"c42a7dcb6bf2c03c36b86b8d407e487dd3b765dbfb770f408bbe94236a814cd3"
},
"devel_pack": {
- "path": "php-devel-pack-8.4.19-Win32-vs17-x64.zip",
+ "path": "php-devel-pack-8.4.24-Win32-vs17-x64.zip",
"size": "1.36MB",
- "sha256":
"85b015e29c26e18fd9a36b84412ebff49c5d30db47e6031a2b66a85d3ca0c28e"
+ "sha256":
"893f5b8ffe515eb07c080e1bdba8cbb0ddf935c76fc1088ddbe46d46f528236c"
}
},
"source": {
- "path": "php-8.4.19-src.zip",
- "size": "29.62MB",
- "sha256":
"8aec529db0f309575629dc087a29383d979b8da22d7adcbdc93361adb7b8a813"
+ "path": "php-8.4.24-src.zip",
+ "size": "29.92MB",
+ "sha256":
"866602124a220d12428c4ef4233d0ce9a3d4eb5d84bbfa043ea2b69ad6e451a4"
},
"test_pack": {
- "path": "php-test-pack-8.4.19.zip",
- "size": "17.48MB",
- "sha256":
"5fccb9618f973a525a70079537d8f94245127ff7cf6116a01bd9c957eb7e71c3"
+ "path": "php-test-pack-8.4.24.zip",
+ "size": "17.58MB",
+ "sha256":
"1eafd40b24758214349275cd505fcccc6776c0b0b59c554e4ac9134f766a48ac"
},
"ts-vs17-x86": {
- "mtime": "2026-03-10T16:11:02+00:00",
+ "mtime": "2026-07-29T06:35:03+00:00",
"zip": {
- "path": "php-8.4.19-Win32-vs17-x86.zip",
- "size": "29.08MB",
- "sha256":
"2a9289593fb26dff8c45fb370c766bb0b661c22bffcf2bee09da33b706a7790b"
+ "path": "php-8.4.24-Win32-vs17-x86.zip",
+ "size": "30.08MB",
+ "sha256":
"f4d04d99aed1e7d93f7c452eb99b31741ade48a80308e8210414aafbd23d10b3"
},
"debug_pack": {
- "path": "php-debug-pack-8.4.19-Win32-vs17-x86.zip",
- "size": "38.29MB",
- "sha256":
"b86d08057202b9b95b1be8559af18a2d19bb7add1445be624b330761b5b2761e"
+ "path": "php-debug-pack-8.4.24-Win32-vs17-x86.zip",
+ "size": "39.94MB",
+ "sha256":
"968c36a8c4bef2e366c5ded34b2d582a51f99979bee779318f77711ac36782c8"
},
"devel_pack": {
- "path": "php-devel-pack-8.4.19-Win32-vs17-x86.zip",
+ "path": "php-devel-pack-8.4.24-Win32-vs17-x86.zip",
"size": "1.36MB",
- "sha256":
"60bf801af1611126574df0779a7967881c31d7d4da93e36642940145ba9c43dd"
+ "sha256":
"17ce0c33671f80c2d8aa8baab254a05d783a8b90e3c72ab65ff318672d304e31"
}
},
"nts-vs17-x64": {
- "mtime": "2026-03-10T16:11:02+00:00",
+ "mtime": "2026-07-29T06:35:03+00:00",
"zip": {
- "path": "php-8.4.19-nts-Win32-vs17-x64.zip",
- "size": "32.35MB",
- "sha256":
"1e26901fdb155d49a1a0eb8a0167a4f8528c0c700ae62e8af1c48230b68af1d9"
+ "path": "php-8.4.24-nts-Win32-vs17-x64.zip",
+ "size": "33.45MB",
+ "sha256":
"86470a30cbbaeafb259e727dfa5cd336f2f3f0a462cd6f8e3eac00fdbded13cb"
},
"debug_pack": {
- "path": "php-debug-pack-8.4.19-nts-Win32-vs17-x64.zip",
- "size": "37.5MB",
- "sha256":
"2ec9e85966824ea8039e66c93c88df21c716ab473652bf3971cb67579f08b1f4"
+ "path": "php-debug-pack-8.4.24-nts-Win32-vs17-x64.zip",
+ "size": "39.52MB",
+ "sha256":
"f75bfb7be18192b8966e94df853691043972f5b34f7087b76d2c5126ad9eb6fc"
},
"devel_pack": {
- "path": "php-devel-pack-8.4.19-nts-Win32-vs17-x64.zip",
+ "path": "php-devel-pack-8.4.24-nts-Win32-vs17-x64.zip",
"size": "1.35MB",
- "sha256":
"fbd2ca7d1dba0cdd427e6dd3d6369818d53a5c6b1fa613494cc1b6ad2b9b36e3"
+ "sha256":
"11ba8f24e5ed779025c8634a7b9cab44f5b20769007df44abbbc9fdc7cb5da5f"
}
},
"nts-vs17-x86": {
- "mtime": "2026-03-10T16:11:02+00:00",
+ "mtime": "2026-07-29T06:35:03+00:00",
"zip": {
- "path": "php-8.4.19-nts-Win32-vs17-x86.zip",
- "size": "29.01MB",
- "sha256":
"9672ef9929dbd0f3cbf6500af8cc0e15226cb801e91fbc5f5e25fb630d0ab873"
+ "path": "php-8.4.24-nts-Win32-vs17-x86.zip",
+ "size": "30.02MB",
+ "sha256":
"42f00095f1ee7bd85a12f0be48fc30be3d1ea4a93423de560b83da5521242305"
},
"debug_pack": {
- "path": "php-debug-pack-8.4.19-nts-Win32-vs17-x86.zip",
- "size": "38.18MB",
- "sha256":
"63a8244528e46ac21162e48a0c66e7371b69a9f0f95ecfac86aad594946eb20e"
+ "path": "php-debug-pack-8.4.24-nts-Win32-vs17-x86.zip",
+ "size": "39.86MB",
+ "sha256":
"659cc530b571af71a96e20614ea47c24bf4f3bc1c0474ffa2b53bf0d23317f8c"
},
"devel_pack": {
- "path": "php-devel-pack-8.4.19-nts-Win32-vs17-x86.zip",
- "size": "1.35MB",
- "sha256":
"cf5ce8b3558c09bb8f4010d6edd6f26da5366718d54c727d85543008844b0d7b"
+ "path": "php-devel-pack-8.4.24-nts-Win32-vs17-x86.zip",
+ "size": "1.36MB",
+ "sha256":
"9d4249e342bc99549ecbc732600a9b86bfa1a608c4c3092664e10d7850e88b32"
}
}
},
"8.5": {
- "version": "8.5.4",
+ "version": "8.5.9",
"ts-vs17-x64": {
- "mtime": "2026-03-10T23:37:20+00:00",
+ "mtime": "2026-07-28T16:05:03+00:00",
"zip": {
- "path": "php-8.5.4-Win32-vs17-x64.zip",
- "size": "33.49MB",
- "sha256":
"4fdf52526a892aaa9c99a4f32ad4b4e18c400134b4a414941f97121a0925d8a3"
+ "path": "php-8.5.9-Win32-vs17-x64.zip",
+ "size": "34.48MB",
+ "sha256":
"6a8af9f5d2a35b81cd9f1db04bd4037c3609828db62f81589e29e13faffd45f9"
},
"debug_pack": {
- "path": "php-debug-pack-8.5.4-Win32-vs17-x64.zip",
- "size": "38.42MB",
- "sha256":
"9df2029d3698a99334584cd2b4a6aaafa9e66da3cf370e4ec4af85dd7d6337af"
+ "path": "php-debug-pack-8.5.9-Win32-vs17-x64.zip",
+ "size": "39.98MB",
+ "sha256":
"f84b8565ae63cf640fdae9d954bb5d220e8c2eec01ff0d93fb75a4bb0961c636"
},
"devel_pack": {
- "path": "php-devel-pack-8.5.4-Win32-vs17-x64.zip",
- "size": "1.64MB",
- "sha256":
"724017412573e7e3a7a06049680bf8b9c353bf1090f0f015859d0ef9edfeab35"
+ "path": "php-devel-pack-8.5.9-Win32-vs17-x64.zip",
+ "size": "1.66MB",
+ "sha256":
"a0769216467c3f4563fe67a9bc989f3a6c13c2e4b2128f349a4aeee80b34a3e7"
}
},
"source": {
- "path": "php-8.5.4-src.zip",
- "size": "31.73MB",
- "sha256":
"880e3cf4977e479973b792b92fe124e3b99a741c0f03499dd13ce1fa515875e3"
+ "path": "php-8.5.9-src.zip",
+ "size": "32.13MB",
+ "sha256":
"e15b19a235c4cb774f8ddd9e38512ff0b26f68f133ccfef228e6a7f5199072ec"
},
"test_pack": {
- "path": "php-test-pack-8.5.4.zip",
- "size": "18.05MB",
- "sha256":
"ba6ffa908228a1b1ccdb70cadd70d7f7082872e450f80f8a80b49b00c53368a6"
+ "path": "php-test-pack-8.5.9.zip",
+ "size": "18.17MB",
+ "sha256":
"d1a7f8d210ed7d46437540e34f0212f95c418919045767ca79b6e5f495648e8b"
},
"ts-vs17-x86": {
- "mtime": "2026-03-10T23:37:20+00:00",
+ "mtime": "2026-07-28T16:05:03+00:00",
"zip": {
- "path": "php-8.5.4-Win32-vs17-x86.zip",
- "size": "29.9MB",
- "sha256":
"760557d90e12bdb8fd67ddf43f318efb10082c4624ca0e6345fa86974bbdf444"
+ "path": "php-8.5.9-Win32-vs17-x86.zip",
+ "size": "30.88MB",
+ "sha256":
"a87b6475fbbdd6c12c74cfb3c8095032f324d6813604cbbbb236cac3f5bc4171"
},
"debug_pack": {
- "path": "php-debug-pack-8.5.4-Win32-vs17-x86.zip",
- "size": "39.07MB",
- "sha256":
"562cf5cef23600752fbce96aeb79201c5e2969f1a70ac578ae38a7b56dcf986f"
+ "path": "php-debug-pack-8.5.9-Win32-vs17-x86.zip",
+ "size": "40.47MB",
+ "sha256":
"3e7a9393a85f2ff30e7be5a09e6af91e8bf21d8e3d05117c8cdaa8d37b3c1f86"
},
"devel_pack": {
- "path": "php-devel-pack-8.5.4-Win32-vs17-x86.zip",
- "size": "1.64MB",
- "sha256":
"fcdf8e906858cc211f176b260a41d66dad5ce3c40e7daa6d04703f4981bf6d30"
+ "path": "php-devel-pack-8.5.9-Win32-vs17-x86.zip",
+ "size": "1.66MB",
+ "sha256":
"00c75f6a40cbf36afcc051125e674e1ca995c3031211c05392764f801493e1a1"
}
},
"nts-vs17-x64": {
- "mtime": "2026-03-10T23:37:22+00:00",
+ "mtime": "2026-07-28T16:05:04+00:00",
"zip": {
- "path": "php-8.5.4-nts-Win32-vs17-x64.zip",
- "size": "33.36MB",
- "sha256":
"42ac025dbcbd0692d8cf873590653534c5e6b96fedc0a51adb9db6d8a95a977a"
+ "path": "php-8.5.9-nts-Win32-vs17-x64.zip",
+ "size": "34.35MB",
+ "sha256":
"516c2d72231bd035c8a910120834add0ad208098b790b4909b2cbeb93ce135fc"
},
"debug_pack": {
- "path": "php-debug-pack-8.5.4-nts-Win32-vs17-x64.zip",
- "size": "38.32MB",
- "sha256":
"24003710e99a9ab92a157190ff45e6fa15dafd608ac0ea42e2511f0aacd989a5"
+ "path": "php-debug-pack-8.5.9-nts-Win32-vs17-x64.zip",
+ "size": "39.7MB",
+ "sha256":
"a55fb5a002b96241bd957233ccc324ef366693b5746bf43078cf214473575189"
},
"devel_pack": {
- "path": "php-devel-pack-8.5.4-nts-Win32-vs17-x64.zip",
- "size": "1.64MB",
- "sha256":
"8680c6b7525f0e27446bcaa5be5d28ddcc25e668e0a7ca8fef68b2739e772810"
+ "path": "php-devel-pack-8.5.9-nts-Win32-vs17-x64.zip",
+ "size": "1.66MB",
+ "sha256":
"397667ce56d2437dbd29ca596e7e4c9d35045da1b302faf6339680a9bc226d2d"
}
},
"nts-vs17-x86": {
- "mtime": "2026-03-10T23:37:18+00:00",
+ "mtime": "2026-07-28T16:05:04+00:00",
"zip": {
- "path": "php-8.5.4-nts-Win32-vs17-x86.zip",
- "size": "29.8MB",
- "sha256":
"bf22aa14accdfd92ab701a9e22c0a0300e515d1a0f936c652cb2efcf29ff4d65"
+ "path": "php-8.5.9-nts-Win32-vs17-x86.zip",
+ "size": "30.83MB",
+ "sha256":
"702494c2b573aff8ab364d667a9c8897dd96a498a78aacbd33442bcf19b1e7dc"
},
"debug_pack": {
- "path": "php-debug-pack-8.5.4-nts-Win32-vs17-x86.zip",
- "size": "38.96MB",
- "sha256":
"d08554ccdb3ad8ca5b38dfcf7fd42e9c238b361c91a0c9de36fd213fd5b57413"
+ "path": "php-debug-pack-8.5.9-nts-Win32-vs17-x86.zip",
+ "size": "40.51MB",
+ "sha256":
"79617c4e16b13430e4c9bd71bf9f81410fc6727b24c773393d2cb61ca0b26d46"
},
"devel_pack": {
- "path": "php-devel-pack-8.5.4-nts-Win32-vs17-x86.zip",
- "size": "1.64MB",
- "sha256":
"4bd2f878454943b2fee9114d8c05e3beaa2ed5209e973e8416d69fda7b2be66a"
+ "path": "php-devel-pack-8.5.9-nts-Win32-vs17-x86.zip",
+ "size": "1.66MB",
+ "sha256":
"b16be79c3abff27833beec8cb292c08e94c0269c72ec0d7557e3c3207fb6f911"
}
}
}
diff --git a/public/docs.php b/public/docs.php
index da6271275b..eabc831e0c 100644
--- a/public/docs.php
+++ b/public/docs.php
@@ -10,7 +10,6 @@
"Documentation",
[
"current" => "docs",
- 'intro' => $intro,
'cache_control' => 5 * 60, // 5 minutes
]
);
diff --git a/public/eol.php b/public/eol.php
index 9a675c43aa..a2f797f8cd 100644
--- a/public/eol.php
+++ b/public/eol.php
@@ -23,7 +23,7 @@
'4.4' => '<a
href="https://php-legacy-docs.zend.com/manual/php5/en/migration5">A guide is
available for migrating from PHP 4 to 5.0.</a>',
];
-site_header('Unsupported Branches');
+site_header('Unsupported Branches', ['cache' => true, 'cache_control' => 60 *
60 * 24]);
?>
<h1>Unsupported Branches</h1>
diff --git a/public/images/news/php-tek-2027.png
b/public/images/news/php-tek-2027.png
new file mode 100644
index 0000000000..feaa644e80
Binary files /dev/null and b/public/images/news/php-tek-2027.png differ
diff --git a/public/js/common.js b/public/js/common.js
index 86b4862fd5..fe45d50041 100644
--- a/public/js/common.js
+++ b/public/js/common.js
@@ -879,3 +879,18 @@ function applyTheme(theme) {
}
applyTheme(savedTheme)
+
+const downloads = document.querySelector('.downloads');
+downloads?.addEventListener('click', function (event) {
+ var button = event.target.closest('.sha256-copy');
+ if (!button || !navigator.clipboard) {
+ return;
+ }
+
+ navigator.clipboard.writeText(button.dataset.copyText).then(function () {
+ button.textContent = 'Copied';
+ setTimeout(function () {
+ button.textContent = 'Copy';
+ }, 1500);
+ });
+});
diff --git a/public/pre-release-builds.php b/public/pre-release-builds.php
index 6b47f713ec..f168638a07 100644
--- a/public/pre-release-builds.php
+++ b/public/pre-release-builds.php
@@ -100,9 +100,8 @@
<a href="<?php echo $file_info['path'] ?>"><?php echo
"php-{$info['version']}.tar.{$file_type}"; ?></a>
<span class="releasedate"><?php echo date('d M Y',
strtotime($info['date'])); ?></span>
<?php foreach ($QA_CHECKSUM_TYPES as $algo): ?>
- <span class="<?php echo $algo; ?>">
<?php if (isset($file_info[$algo]) && strlen($file_info[$algo]))
: ?>
- <?php echo $file_info[$algo]; ?>
+ <?php echo sha256_html($file_info[$algo]); ?>
<?php else: ?>
<em><small>No checksum value available</small></em>)
<?php endif; ?>
@@ -192,7 +191,7 @@
}
if ($includeSha && $sha !== '') {
- $parts[] = '<span class="sha256">' . htmlspecialchars($sha,
ENT_QUOTES, 'UTF-8') . '</span>';
+ $parts[] = sha256_html($sha);
}
return '<li>' . implode(' ', $parts) . '</li>';
@@ -314,4 +313,3 @@
<?php
site_footer(['sidebar' => $SIDEBAR_DATA]);
-
diff --git a/public/releases/8_2_33.php b/public/releases/8_2_33.php
new file mode 100644
index 0000000000..2f61bd440d
--- /dev/null
+++ b/public/releases/8_2_33.php
@@ -0,0 +1,16 @@
+<?php
+$_SERVER['BASE_PAGE'] = 'releases/8_2_33.php';
+include_once __DIR__ . '/../include/prepend.inc';
+site_header('PHP 8.2.33 Release Announcement');
+?>
+<h1>PHP 8.2.33 Release Announcement</h1>
+
+<p>The PHP development team announces the immediate availability of PHP
8.2.33. This is a security release.</p>
+
+<p>All PHP 8.2 users are encouraged to upgrade to this version.</p>
+
+<p>For source downloads of PHP 8.2.33 please visit our <a
href="https://www.php.net/downloads.php">downloads page</a>,
+Windows source and binaries can also be found <a
href="https://www.php.net/downloads.php?os=windows&version=8.2">there</a>.
+The list of changes is recorded in the <a
href="https://www.php.net/ChangeLog-8.php#8.2.33">ChangeLog</a>.
+</p>
+<?php site_footer();
diff --git a/public/releases/8_3_33.php b/public/releases/8_3_33.php
new file mode 100644
index 0000000000..8ed9cb517c
--- /dev/null
+++ b/public/releases/8_3_33.php
@@ -0,0 +1,16 @@
+<?php
+$_SERVER['BASE_PAGE'] = 'releases/8_3_33.php';
+include_once __DIR__ . '/../include/prepend.inc';
+site_header('PHP 8.3.33 Release Announcement', ['cache' => true,
'cache_control' => 30 * 60]);
+?>
+<h1>PHP 8.3.33 Release Announcement</h1>
+
+<p>The PHP development team announces the immediate availability of PHP
8.3.33. This is a security release.</p>
+
+<p>All PHP 8.3 users are encouraged to upgrade to this version.</p>
+
+<p>For source downloads of PHP 8.3.33 please visit our <a
href="https://www.php.net/downloads.php">downloads page</a>,
+Windows source and binaries can also be found <a
href="https://www.php.net/downloads.php?os=windows&version=8.3">there</a>.
+The list of changes is recorded in the <a
href="https://www.php.net/ChangeLog-8.php#8.3.33">ChangeLog</a>.
+</p>
+<?php site_footer();
diff --git a/public/releases/8_4_24.php b/public/releases/8_4_24.php
new file mode 100644
index 0000000000..3d0890e713
--- /dev/null
+++ b/public/releases/8_4_24.php
@@ -0,0 +1,16 @@
+<?php
+$_SERVER['BASE_PAGE'] = 'releases/8_4_24.php';
+include_once __DIR__ . '/../include/prepend.inc';
+site_header('PHP 8.4.24 Release Announcement', ['cache' => true,
'cache_control' => 30 * 60]);
+?>
+<h1>PHP 8.4.24 Release Announcement</h1>
+
+<p>The PHP development team announces the immediate availability of PHP
8.4.24. This is a security release.</p>
+
+<p>All PHP 8.4 users are encouraged to upgrade to this version.</p>
+
+<p>For source downloads of PHP 8.4.24 please visit our <a
href="https://www.php.net/downloads.php">downloads page</a>,
+Windows source and binaries can also be found <a
href="https://www.php.net/downloads.php?os=windows&version=8.4">there</a>.
+The list of changes is recorded in the <a
href="https://www.php.net/ChangeLog-8.php#8.4.24">ChangeLog</a>.
+</p>
+<?php site_footer();
diff --git a/public/releases/8_5_9.php b/public/releases/8_5_9.php
new file mode 100644
index 0000000000..854553c793
--- /dev/null
+++ b/public/releases/8_5_9.php
@@ -0,0 +1,16 @@
+<?php
+$_SERVER['BASE_PAGE'] = 'releases/8_5_9.php';
+include_once __DIR__ . '/../include/prepend.inc';
+site_header('PHP 8.5.9 Release Announcement');
+?>
+<h1>PHP 8.5.9 Release Announcement</h1>
+
+<p>The PHP development team announces the immediate availability of PHP 8.5.9.
This is a security release.</p>
+
+<p>All PHP 8.5 users are encouraged to upgrade to this version.</p>
+
+<p>For source downloads of PHP 8.5.9 please visit our <a
href="https://www.php.net/downloads.php">downloads page</a>,
+Windows source and binaries can also be found <a
href="https://www.php.net/downloads.php?os=windows&version=8.5">there</a>.
+The list of changes is recorded in the <a
href="https://www.php.net/ChangeLog-8.php#8.5.9">ChangeLog</a>.
+</p>
+<?php site_footer();
diff --git a/public/releases/index.php b/public/releases/index.php
index b1ecec840d..305940245e 100644
--- a/public/releases/index.php
+++ b/public/releases/index.php
@@ -216,13 +216,8 @@ function mk_rel(int $major,
echo " <li>\n";
if (isset($src['filename'])) {
download_link($src["filename"], $src["name"]); echo "<br>\n";
- $linebreak = '';
- foreach (['md5', 'sha256'] as $cs) {
- if (isset($src[$cs])) {
- echo $linebreak;
- echo "<span class=\"{$cs}sum\">{$cs}:
{$src[$cs]}</span>\n";
- $linebreak = "<br/>";
- }
+ if (isset($src['sha256'])) {
+ echo sha256_html($src['sha256']), "\n";
}
} else {
echo "<a href=\"{$src['link']}\">{$src['name']}</a>";
diff --git a/public/styles/code-syntax.css b/public/styles/code-syntax.css
index 02f927911e..e303671312 100644
--- a/public/styles/code-syntax.css
+++ b/public/styles/code-syntax.css
@@ -97,6 +97,16 @@ button.copy-to-clipboard-button:hover {
word-break: break-all;
}
+.instructions .sbom:before {
+ content: "SBOM: ";
+ font-family: var(--font-family-sans-serif);
+}
+
+.instructions .sha256:before,
+.instructions .sbom:before {
+ font-weight: 700;
+}
+
.content-box .code-toolbar {
margin: 0 0 1rem;
}
diff --git a/public/styles/theme-base.css b/public/styles/theme-base.css
index faeab9d6b4..74a5351714 100644
--- a/public/styles/theme-base.css
+++ b/public/styles/theme-base.css
@@ -783,20 +783,50 @@ fieldset {
.content-header .changelog {
color:#369;
}
-.content-box .md5sum, .content-box .sha256 {
+.content-box .sha256,
+.downloads .sha256,
+.downloads .sbom {
display: block;
font: normal 0.875rem/1.5rem "Fira Mono", "Source Code Pro", monospace;
overflow: hidden;
text-overflow: ellipsis;
}
-.content-box .md5sum:before {
- content: "md5: ";
- font-family: var(--font-family-sans-serif);
-}
-.content-box .sha256:before {
+.content-box .sha256:before,
+.downloads .sha256:before {
content: "sha256: ";
font-family: var(--font-family-sans-serif);
}
+.content-box .sha256-row,
+.downloads .sha256-row {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+.content-box .sha256-row .sha256,
+.downloads .sha256-row .sha256 {
+ min-width: 0;
+}
+.content-box .sha256-copy,
+.downloads .sha256-copy {
+ border: 1px solid var(--dark-blue-color);
+ border-radius: 30px;
+ background-color: var(--dark-blue-color);
+ color: #fff;
+ padding: 0.2rem 0.65rem;
+ font-size: 0.75rem;
+ line-height: 1rem;
+ cursor: pointer;
+ min-width: 4.25rem;
+ text-align: center;
+ white-space: nowrap;
+}
+.content-box .sha256-copy:hover,
+.content-box .sha256-copy:focus,
+.downloads .sha256-copy:hover,
+.downloads .sha256-copy:focus {
+ border-color: var(--dark-magenta-color);
+ background-color: var(--dark-magenta-color);
+}
.content-box .releasedate {
float: right;
font-size: 0.9rem;
diff --git a/tests/EndToEnd/OriginHeaderTest.php
b/tests/EndToEnd/OriginHeaderTest.php
new file mode 100644
index 0000000000..e62f30acd6
--- /dev/null
+++ b/tests/EndToEnd/OriginHeaderTest.php
@@ -0,0 +1,256 @@
+<?php
+
+declare(strict_types=1);
+
+namespace phpweb\Test\EndToEnd;
+
+use PHPUnit\Framework;
+
+/**
+ * Regression tests for the blank-page bug reported in
+ * https://github.com/php/web-php/issues/1955.
+ *
+ * The CORS guard in include/prepend.inc used to terminate the request with
+ * exit(10) whenever the Origin request header did not belong to php.net.
+ * exit(10) emits an integer exit status, not a body, so the response was a
+ * perfectly valid "200 OK" with a zero byte body.
+ *
+ * Since Origin was not part of the CDN cache key and no Vary header was sent,
+ * a single request carrying a foreign Origin header was enough for the CDN to
+ * store that empty 200 and replay it to every subsequent visitor as a blank
+ * white page, until the cache was purged.
+ *
+ * SmokeTest only asserts the status code, so it could not catch this: a blank
+ * page is still a 200.
+ */
+#[Framework\Attributes\CoversNothing]
+final class OriginHeaderTest extends Framework\TestCase
+{
+ /**
+ * A cross-origin request must never produce an empty body, because that
+ * body is what the CDN caches and replays to everyone else.
+ */
+ #[Framework\Attributes\DataProvider('provideForeignOrigin')]
+ public function testForeignOriginDoesNotReturnBlankPage(string $origin):
void
+ {
+ $response = self::get('/', $origin);
+
+ self::assertSame(200, $response['status'], sprintf(
+ 'Expected "/" to return 200 for Origin "%s", got "%d".',
+ $origin,
+ $response['status'],
+ ));
+
+ self::assertNotSame('', $response['body'], sprintf(
+ 'Blank page: "/" returned a %d response with a zero byte body for
Origin "%s". '
+ . 'The CDN caches this empty body and serves it to all
visitors.',
+ $response['status'],
+ $origin,
+ ));
+ }
+
+ /**
+ * Every page is affected, not just the homepage.
+ */
+ #[Framework\Attributes\DataProvider('providePath')]
+ public function testPathDoesNotReturnBlankPageForForeignOrigin(string
$path): void
+ {
+ $response = self::get($path, 'https://example.com');
+
+ self::assertNotSame('', $response['body'], sprintf(
+ 'Blank page: "%s" returned a %d response with a zero byte body for
a foreign Origin.',
+ $path,
+ $response['status'],
+ ));
+ }
+
+ /**
+ * Guards the fix from the other side: legitimate php.net origins, and
+ * requests with no Origin at all, must keep working.
+ */
+ #[Framework\Attributes\DataProvider('provideAllowedOrigin')]
+ public function testAllowedOriginReturnsContent(?string $origin): void
+ {
+ $response = self::get('/', $origin);
+
+ self::assertSame(200, $response['status']);
+ self::assertNotSame('', $response['body']);
+ }
+
+ /**
+ * The CORS headers depend on the Origin request header, so shared caches
+ * have to be told not to reuse a response across origins.
+ */
+ public function testResponseVariesOnOrigin(): void
+ {
+ $response = self::get('/');
+
+ self::assertStringContainsStringIgnoringCase('origin',
$response['vary'], sprintf(
+ 'Expected a "Vary: Origin" response header, got "%s".',
+ $response['vary'],
+ ));
+ }
+
+ /**
+ * The blank page must not be traded for a cross site request forgery hole:
+ * the state changing endpoints have no CSRF tokens, so a cross origin POST
+ * still has to be rejected.
+ */
+ public function testCrossOriginPostIsRejected(): void
+ {
+ $response = self::post('/manual/vote-note.php', 'https://example.com');
+
+ self::assertSame(403, $response['status'], sprintf(
+ 'Expected a cross-origin POST to be rejected with 403, got "%d".',
+ $response['status'],
+ ));
+ }
+
+ /**
+ * Rejections still need a body, otherwise they are just the blank page
+ * again wearing a different status code.
+ */
+ public function testRejectedCrossOriginPostStillHasABody(): void
+ {
+ $response = self::post('/manual/vote-note.php', 'https://example.com');
+
+ self::assertNotSame('', $response['body'], 'A rejected cross-origin
POST returned an empty body.');
+ }
+
+ /**
+ * Same-origin POSTs must keep working.
+ */
+ public function testSameOriginPostIsNotRejected(): void
+ {
+ $httpHost = getenv('HTTP_HOST');
+
+ $response = self::post('/manual/vote-note.php', sprintf('http://%s',
$httpHost));
+
+ self::assertNotSame(403, $response['status'], 'A same-origin POST was
rejected.');
+ }
+
+ /**
+ * @return \Generator<string, array{0: string}>
+ */
+ public static function provideForeignOrigin(): \Generator
+ {
+ $origins = [
+ // Any unrelated site embedding or fetching php.net.
+ 'https://example.com',
+ // Browsers send a literal "null" origin for sandboxed iframes,
+ // documents from data:/file: URLs, and some cross-origin
redirects.
+ 'null',
+ // Must not be treated as php.net just because it contains it.
+ 'https://evil-php.net.attacker.com',
+ 'https://notphp.net',
+ ];
+
+ foreach ($origins as $origin) {
+ yield $origin => [$origin];
+ }
+ }
+
+ /**
+ * @return \Generator<string, array{0: ?string}>
+ */
+ public static function provideAllowedOrigin(): \Generator
+ {
+ $origins = [
+ 'no Origin header' => null,
+ 'https://www.php.net' => 'https://www.php.net',
+ 'https://php.net' => 'https://php.net',
+ 'https://qa.php.net' => 'https://qa.php.net',
+ ];
+
+ foreach ($origins as $name => $origin) {
+ yield $name => [$origin];
+ }
+ }
+
+ /**
+ * @return \Generator<string, array{0: string}>
+ */
+ public static function providePath(): \Generator
+ {
+ $paths = [
+ '/',
+ '/downloads.php',
+ '/contact.php',
+ '/manual/en/function.str-replace.php',
+ '/releases/',
+ ];
+
+ foreach ($paths as $path) {
+ yield $path => [$path];
+ }
+ }
+
+ /**
+ * @return array{status: int, body: string, vary: string}
+ */
+ private static function post(string $path, string $origin): array
+ {
+ return self::get($path, $origin, ['vote' => 'up']);
+ }
+
+ /**
+ * @param ?array<string, string> $postFields
+ *
+ * @return array{status: int, body: string, vary: string}
+ */
+ private static function get(
+ string $path,
+ ?string $origin = null,
+ ?array $postFields = null,
+ ): array
+ {
+ $httpHost = getenv('HTTP_HOST');
+
+ if (!is_string($httpHost)) {
+ throw new \RuntimeException('Environment variable "HTTP_HOST" is
not set.');
+ }
+
+ $headers = [];
+
+ if (is_string($origin)) {
+ $headers[] = sprintf('Origin: %s', $origin);
+ }
+
+ $vary = '';
+
+ $handle = curl_init();
+
+ if (is_array($postFields)) {
+ curl_setopt($handle, CURLOPT_POST, true);
+ curl_setopt($handle, CURLOPT_POSTFIELDS,
http_build_query($postFields));
+ }
+
+ curl_setopt_array($handle, [
+ CURLOPT_RETURNTRANSFER => true,
+ CURLOPT_HTTPHEADER => $headers,
+ CURLOPT_URL => sprintf('http://%s%s', $httpHost, $path),
+ CURLOPT_HEADERFUNCTION => static function ($handle, string
$header) use (&$vary): int {
+ if (stripos($header, 'vary:') === 0) {
+ $vary = trim(substr($header, strlen('vary:')));
+ }
+
+ return strlen($header);
+ },
+ ]);
+
+ $body = curl_exec($handle);
+ $status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
+
+ curl_close($handle);
+
+ if (!is_string($body)) {
+ throw new \RuntimeException(sprintf('Failed to request "%s".',
$path));
+ }
+
+ return [
+ 'status' => $status,
+ 'body' => $body,
+ 'vary' => $vary,
+ ];
+ }
+}