From fd3f75b3a225309d2255a7f221e10028d527edec Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Mon, 26 Oct 2026 20:02:32 +0000 Subject: [PATCH] Require PHP 8.2+ (#9470) Drop PHP 8.1 (EOL December 2025), drop Ubuntu 22.04 (EOL May 2027, and there is now 24.04 and 26.04 LTS). PHP 8.1 is already EOL, and Debian, Alpine, Fedora, Red Hat, Synology have dropped PHP 8.1 already. See https://github.com/FreshRSS/FreshRSS/discussions/5474#discussioncomment-16791937 With PHP 8.6 around the corner and in particular a relevant `FILTER_FLAG_GLOBAL_RANGE` in PHP 8.2+. * https://www.php.net/releases/8.2 * https://www.php.net/filter.constants.validation#constant.filter-flag-global-range * https://www.php.net/class.sensitiveparameter * https://php.watch/versions/8.2/readonly-classes * https://www.php.net/function.ini-parse-quantity Allows updating to PHPUnit 11.x instead of 10.x https://phpunit.de/supported-versions.html Contributes to https://github.com/FreshRSS/FreshRSS/issues/9475 * Add regression test for FILTER_FLAG_GLOBAL_RANGE https://github.com/FreshRSS/FreshRSS/pull/9470#discussion_r4371168720 --- .github/ISSUE_TEMPLATE/bug_report_form.yaml | 2 +- .github/ISSUE_TEMPLATE/feed-report-form.yml | 2 +- CHANGELOG.md | 7 +- Docker/Dockerfile-Oldest | 14 +- README.fr.md | 2 +- README.md | 2 +- app/Controllers/importExportController.php | 14 +- app/Models/SimplePieFetch.php | 8 +- app/Models/ViewMode.php | 2 +- app/Utils/httpUtil.php | 41 +- composer.json | 8 +- composer.lock | 564 ++++++++++++-------- constants.php | 2 +- docs/en/admins/02_Prerequisites.md | 2 +- docs/en/admins/10_ServerConfig.md | 2 +- docs/fr/users/01_Installation.md | 4 +- lib/Minz/Hook.php | 2 +- phpstan.dist.neon | 2 +- tests/app/Models/BooleanSearchTest.php | 7 +- tests/app/Models/EntryTest.php | 4 +- tests/app/Models/SearchTest.php | 28 +- tests/app/Models/SimplePieCustomTest.php | 4 +- tests/app/Models/UserQueryTest.php | 4 +- tests/app/Utils/httpUtilTest.php | 58 +- 24 files changed, 434 insertions(+), 351 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report_form.yaml b/.github/ISSUE_TEMPLATE/bug_report_form.yaml index 2bd744390..02e81216b 100644 --- a/.github/ISSUE_TEMPLATE/bug_report_form.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report_form.yaml @@ -44,7 +44,7 @@ body: attributes: label: System information description: Please complete the following information - value: "- Database version: [e.g. SQLite, PostgreSQL 17]\n- PHP version: [e.g. PHP 8.2]\n- Installation type: [e.g. Docker, Docker image source, git, Yunohost]\n- Web server type: [e.g. Apache, nginx]\n- Device: [e.g. iPhone13]\n- OS: [e.g. Ubuntu 24.04, Win11, MacOS14]\n- Browser: [e.g. Firefox 134]" + value: "- Database version: [e.g. PostgreSQL 18, MySQL 8.4, SQLite]\n- PHP version: [e.g. PHP 8.2]\n- Installation type: [e.g. Docker, Docker image source, git, YunoHost]\n- Web server type: [e.g. Apache, nginx]\n- Device: [e.g. iPhone13]\n- OS: [e.g. Ubuntu 24.04, Win11, macOS 27]\n- Browser: [e.g. Firefox 157]" validations: required: true - type: textarea diff --git a/.github/ISSUE_TEMPLATE/feed-report-form.yml b/.github/ISSUE_TEMPLATE/feed-report-form.yml index 65b88018d..bb5fcebfc 100644 --- a/.github/ISSUE_TEMPLATE/feed-report-form.yml +++ b/.github/ISSUE_TEMPLATE/feed-report-form.yml @@ -49,7 +49,7 @@ body: attributes: label: System information description: Please complete the following information - value: "Database version: [e.g. Mysql 5.7, SQLite]\n- PHP version: [e.g. PHP 8.1]\n- Installation type: [e.g. Docker, Docker image source, git, Yunohost]\n- Web server type: [e.g. Apache, nginx]\n- Device: [e.g. iPhone13]\n- OS: [e.g. Ubuntu 22.04, Win10, MacOS14]\n- Browser: [e.g. Firefox 124]" + value: "- Database version: [e.g. PostgreSQL 18, MySQL 8.4, SQLite]\n- PHP version: [e.g. PHP 8.2]\n- Installation type: [e.g. Docker, Docker image source, git, YunoHost]\n- Web server type: [e.g. Apache, nginx]\n- Device: [e.g. iPhone13]\n- OS: [e.g. Ubuntu 24.04, Win11, macOS 27]\n- Browser: [e.g. Firefox 157]" validations: required: true - type: textarea diff --git a/CHANGELOG.md b/CHANGELOG.md index e442c9d0d..ba93d3d96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,14 +4,19 @@ See also [the FreshRSS releases](https://github.com/FreshRSS/FreshRSS/releases). ## 2026-XX-XX FreshRSS 1.30.5-dev +* Compatibility + * 💥 Require PHP 8.2+ (drop PHP 8.1) [#9470](https://github.com/FreshRSS/FreshRSS/pull/9470) * Bug fixes * Fix 32-bit systems provide a string for SQL BIGINT [#9486](https://github.com/FreshRSS/FreshRSS/pull/9486) * Security * Fix escape labels during JSON import and render tag dropdown as text [#9504](https://github.com/FreshRSS/FreshRSS/pull/9504) +* Deployment + * Docker: dev image `freshrss/freshrss:oldest` updated to Alpine 3.18 with PHP 8.2.16 and Apache 2.4.62 [#9470](https://github.com/FreshRSS/FreshRSS/pull/9470) * I18n * Add Arabic [#9502](https://github.com/FreshRSS/FreshRSS/pull/9502) * CI/CD * Add a link checker workflow using lychee [#9209](https://github.com/FreshRSS/FreshRSS/pull/9209), [#9495](https://github.com/FreshRSS/FreshRSS/pull/9495), [#9507](https://github.com/FreshRSS/FreshRSS/pull/9507) + * Update to PHPUnit 11.x (PHP 8.2+) [#9470](https://github.com/FreshRSS/FreshRSS/pull/9470) * Group auto dependency updates into one PR per ecosystem [#9496](https://github.com/FreshRSS/FreshRSS/pull/9496) * Update dev dependencies [#9494](https://github.com/FreshRSS/FreshRSS/pull/9494), [#9497](https://github.com/FreshRSS/FreshRSS/pull/9497), [#9498](https://github.com/FreshRSS/FreshRSS/pull/9498), [#9499](https://github.com/FreshRSS/FreshRSS/pull/9499),[#9500](https://github.com/FreshRSS/FreshRSS/pull/9500),[#9501](https://github.com/FreshRSS/FreshRSS/pull/9501), @@ -79,7 +84,7 @@ See also [the FreshRSS releases](https://github.com/FreshRSS/FreshRSS/releases). * Accept a trusted proxy address given without a subnet [#9301](https://github.com/FreshRSS/FreshRSS/pull/9301) * Warn during session regenerate fail [#9311](https://github.com/FreshRSS/FreshRSS/pull/9311), [#9376](https://github.com/FreshRSS/FreshRSS/pull/9376) * CI/CD add zizmor workflow for action security checks [#9228](https://github.com/FreshRSS/FreshRSS/pull/9228), [#9331](https://github.com/FreshRSS/FreshRSS/pull/9331) - * Use PHP `#[\SensitiveParameter]` [#9322](https://github.com/FreshRSS/FreshRSS/pull/9322) + * Use PHP 8.2+ `#[\SensitiveParameter]` [#9322](https://github.com/FreshRSS/FreshRSS/pull/9322) * Reject token access (RSS/OPML export, feed refresh) for disabled accounts [#9336](https://github.com/FreshRSS/FreshRSS/pull/9336) * Require POST+CSRF for self-update mutations [#9335](https://github.com/FreshRSS/FreshRSS/pull/9335) * Make the login challenge nonce one-time [#9334](https://github.com/FreshRSS/FreshRSS/pull/9334) diff --git a/Docker/Dockerfile-Oldest b/Docker/Dockerfile-Oldest index 55c3b011f..ba710d0e8 100644 --- a/Docker/Dockerfile-Oldest +++ b/Docker/Dockerfile-Oldest @@ -1,15 +1,15 @@ # Test image for development -FROM alpine:3.16 +FROM alpine:3.18 ENV TZ=UTC SHELL ["/bin/ash", "-eo", "pipefail", "-c"] RUN apk add --no-cache \ tzdata \ - apache2 php81-apache2 \ - php81 php81-curl php81-gmp php81-intl php81-mbstring php81-xml php81-zip \ - php81-ctype php81-dom php81-fileinfo php81-iconv php81-json php81-opcache php81-openssl php81-phar php81-session php81-simplexml php81-xmlreader php81-xmlwriter php81-xml php81-tokenizer php81-zlib \ - php81-pdo_sqlite php81-pdo_mysql php81-pdo_pgsql + apache2 php82-apache2 \ + php82 php82-curl php82-gmp php82-intl php82-mbstring php82-xml php82-zip \ + php82-ctype php82-dom php82-fileinfo php82-iconv php82-json php82-opcache php82-openssl php82-phar php82-session php82-simplexml php82-xmlreader php82-xmlwriter php82-xml php82-tokenizer php82-zlib \ + php82-pdo_sqlite php82-pdo_mysql php82-pdo_pgsql RUN mkdir -p /var/www/FreshRSS /run/apache2/ WORKDIR /var/www/FreshRSS @@ -43,8 +43,8 @@ RUN \ sed -r -i "/^\s*#\s*LoadModule .*mod_(deflate|expires|filter|headers|mime|remoteip|setenvif).so$/s/^\s*#//" \ /etc/apache2/httpd.conf && \ # PHP configuration - if [ ! -f /usr/bin/php ]; then ln -s /usr/bin/php81 /usr/bin/php; else true; fi && \ - echo 'memory_limit = 256M' > /etc/php81/conf.d/10_memory.ini && \ + if [ ! -f /usr/bin/php ]; then ln -s /usr/bin/php82 /usr/bin/php; else true; fi && \ + echo 'memory_limit = 256M' > /etc/php82/conf.d/10_memory.ini && \ # Disable built-in FreshRSS updates when using Docker, as the full image is supposed to be updated instead. sed -r -i "\\#disable_update#s#^.*#\t'disable_update' => true,#" ./config.default.php && \ # Configure cron job diff --git a/README.fr.md b/README.fr.md index 5d8e7bc5b..8de07aab0 100644 --- a/README.fr.md +++ b/README.fr.md @@ -63,7 +63,7 @@ FreshRSS n’est fourni avec aucune garantie. * Serveur modeste, par exemple sous Linux ou Windows * Fonctionne même sur un Raspberry Pi 1 avec des temps de réponse < 1s (testé sur 150 flux, 22k articles) * Serveur Web Apache2.4+ (recommandé), ou nginx, lighttpd (non testé sur les autres) -* PHP 8.1+ +* PHP 8.2+ * Extensions requises : [cURL](https://www.php.net/curl), [DOM](https://www.php.net/dom), [JSON](https://www.php.net/json), [XML](https://www.php.net/xml), [session](https://www.php.net/features.sessions), [ctype](https://www.php.net/ctype) * Extensions recommandées : [PDO_SQLite](https://www.php.net/pdo-sqlite) (pour l’export/import), [GMP](https://www.php.net/gmp) (pour accès API sur plateformes < 64 bits), [IDN](https://www.php.net/intl.idn) (pour les noms de domaines internationalisés), [mbstring](https://www.php.net/mbstring) (pour le texte Unicode), [iconv](https://www.php.net/iconv) (pour conversion d’encodages), [ZIP](https://www.php.net/zip) (pour import/export), [zlib](https://www.php.net/zlib) (pour les flux compressés) * Extension pour base de données : [PDO_PGSQL](https://www.php.net/pdo-pgsql) ou [PDO_SQLite](https://www.php.net/pdo-sqlite) ou [PDO_MySQL](https://www.php.net/pdo-mysql) diff --git a/README.md b/README.md index 4db491913..667e32ac9 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ FreshRSS comes with absolutely no warranty. * Light server running Linux or Windows * It even works on Raspberry Pi 1 with response time under a second (tested with 150 feeds, 22k articles) * A Web server: Apache2.4+ (recommended), nginx, lighttpd (not tested on others) -* PHP 8.1+ +* PHP 8.2+ * Required extensions: [cURL](https://www.php.net/curl), [DOM](https://www.php.net/dom), [JSON](https://www.php.net/json), [XML](https://www.php.net/xml), [session](https://www.php.net/features.sessions), [ctype](https://www.php.net/ctype) * Recommended extensions: [PDO_SQLite](https://www.php.net/pdo-sqlite) (for export/import), [GMP](https://www.php.net/gmp) (for API access on 32-bit platforms), [IDN](https://www.php.net/intl.idn) (for Internationalized Domain Names), [mbstring](https://www.php.net/mbstring) (for Unicode strings), [iconv](https://www.php.net/iconv) (for charset conversion), [ZIP](https://www.php.net/zip) (for import/export), [zlib](https://www.php.net/zlib) (for compressed feeds) * Extension for database: [PDO_PGSQL](https://www.php.net/pdo-pgsql) or [PDO_SQLite](https://www.php.net/pdo-sqlite) or [PDO_MySQL](https://www.php.net/pdo-mysql) diff --git a/app/Controllers/importExportController.php b/app/Controllers/importExportController.php index 0ed4f0508..f8fa6ba22 100644 --- a/app/Controllers/importExportController.php +++ b/app/Controllers/importExportController.php @@ -80,19 +80,11 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController { $this->listSqliteArchives(); } - private static function megabytes(string $size_str): float|int|string { - return match (substr($size_str, -1)) { - 'M', 'm' => (int)$size_str, - 'K', 'k' => (int)$size_str / 1024, - 'G', 'g' => (int)$size_str * 1024, - default => $size_str, - }; - } - private static function minimumMemory(int|string $mb): void { $mb = (int)$mb; - $ini = self::megabytes(ini_get('memory_limit') ?: '0'); - if ($ini < $mb) { + // `ini_get('memory_limit')` returns e.g. `128M`, or `-1` for unlimited + $ini = (int)(ini_parse_quantity(ini_get('memory_limit') ?: '0') / 1048576); + if ($ini >= 0 && $ini < $mb) { ini_set('memory_limit', $mb . 'M'); } } diff --git a/app/Models/SimplePieFetch.php b/app/Models/SimplePieFetch.php index 113799de6..eb5cf98a2 100644 --- a/app/Models/SimplePieFetch.php +++ b/app/Models/SimplePieFetch.php @@ -25,10 +25,10 @@ final class FreshRSS_SimplePieFetch extends \SimplePie\File } } - $redirects = $curl_options[CURLOPT_MAXREDIRS] ?? $redirects; - if (!is_int($redirects)) { - $redirects = 4; - } elseif ($redirects < 0) { + if (is_int($curl_options[CURLOPT_MAXREDIRS] ?? null)) { + $redirects = $curl_options[CURLOPT_MAXREDIRS]; + } + if ($redirects < 0) { $redirects = -1; // infinite redirects } if (isset($curl_options[CURLOPT_FOLLOWLOCATION])) { diff --git a/app/Models/ViewMode.php b/app/Models/ViewMode.php index fde073097..5fe4d2870 100644 --- a/app/Models/ViewMode.php +++ b/app/Models/ViewMode.php @@ -4,7 +4,7 @@ declare(strict_types=1); /** * Represents a view mode option for the reading configuration */ -final class FreshRSS_ViewMode { +final readonly class FreshRSS_ViewMode { private string $id; private string $name; private string $controller; diff --git a/app/Utils/httpUtil.php b/app/Utils/httpUtil.php index c29d07f2c..2872faa79 100644 --- a/app/Utils/httpUtil.php +++ b/app/Utils/httpUtil.php @@ -4,23 +4,8 @@ declare(strict_types=1); final class FreshRSS_http_Util { private const RETRY_AFTER_PATH = DATA_PATH . '/Retry-After/'; - private const PRIVATE_SUBNETS = [ - '127.0.0.0/8', // RFC1700 (Loopback) - '10.0.0.0/8', // RFC1918 - '192.168.0.0/16', // RFC1918 - '172.16.0.0/12', // RFC1918 - '169.254.0.0/16', // RFC3927 - '0.0.0.0/8', // RFC5735 - '240.0.0.0/4', // RFC1112 - '100.64.0.0/10', // RFC6598 (Shared Address Space of Carrier-Grade NAT) - '::1/128', // Loopback - 'fc00::/7', // Unique Local Address - 'fe80::/10', // Link Local Address - '::ffff:0:0/96', // IPv4 translations - '64:ff9b::/96', // RFC6052 (IPv6 Addressing of IPv4/IPv6 Translators, NAT64) - '64:ff9b:1::/48', // RFC8215 (Local-Use IPv4/IPv6 Translation Prefix) - '::/128', // Unspecified address - ]; + private const NAT64_PREFIX_RFC6052 = '64:ff9b::/96'; + private const NAT64_PREFIX_RFC8215 = '64:ff9b:1::/48'; /** @var array $resolve_ok */ private static array $resolve_ok = []; /** @var array $retry_after_domain_wide */ @@ -398,7 +383,7 @@ final class FreshRSS_http_Util { // NAT64 addresses use the RFC 6052 well-known prefix. // Validate the embedded IPv4 address because the NAT64 IPv6 address itself // is globally routable even when it maps to a private/reserved IPv4 address. - if (self::checkCIDR($ip, '64:ff9b::/96')) { + if (self::checkCIDR($ip, self::NAT64_PREFIX_RFC6052)) { $packed = @inet_pton($ip); if ($packed === false || strlen($packed) !== 16) { continue; @@ -409,31 +394,19 @@ final class FreshRSS_http_Util { continue; } - if (filter_var($embedded_ipv4, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) { + if (filter_var($embedded_ipv4, FILTER_VALIDATE_IP, FILTER_FLAG_GLOBAL_RANGE) === false) { continue; } - // Extra check because the above one might not be enough: https://github.com/php/php-src/issues/16944 - foreach (self::PRIVATE_SUBNETS as $cidr) { - if (self::checkCIDR($embedded_ipv4, $cidr)) { - continue 2; - } - } - $ips_ok[] = $add_ip; continue; } - if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) { + // `FILTER_FLAG_GLOBAL_RANGE` does not reject the NAT64 prefixes + if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_GLOBAL_RANGE) === false || + self::checkCIDR($ip, self::NAT64_PREFIX_RFC8215)) { continue; } - // Extra check because the above one might not be enough: https://github.com/php/php-src/issues/16944 - // Workaround is available by using `FILTER_FLAG_GLOBAL_RANGE` instead, but that was only added in PHP 8.2, and we need to support PHP 8.1+ - foreach (self::PRIVATE_SUBNETS as $cidr) { - if (self::checkCIDR($ip, $cidr)) { - continue 2; - } - } $ips_ok[] = $add_ip; } diff --git a/composer.json b/composer.json index 82210cf8c..521981786 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "WebSub" ], "require": { - "php": ">=8.1", + "php": ">=8.2", "ext-ctype": "*", "ext-curl": "*", "ext-dom": "*", @@ -49,11 +49,11 @@ "phpstan/extension-installer": false }, "platform": { - "php": "8.1" + "php": "8.2" } }, "require-dev": { - "php": ">=8.1", + "php": ">=8.2", "ext-phar": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", @@ -61,7 +61,7 @@ "phpstan/phpstan-deprecation-rules": "^2.0", "phpstan/phpstan-phpunit": "^2.0", "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^10", + "phpunit/phpunit": "^11", "squizlabs/php_codesniffer": "^4.0" }, "scripts": { diff --git a/composer.lock b/composer.lock index 8223ae9dd..3e1c33e69 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": "d9c253337f8342684f2f8f37c331a81f", + "content-hash": "a98d34205a998ade47ad94d4e7c2ed09", "packages": [], "packages-dev": [ { @@ -469,35 +469,35 @@ }, { "name": "phpunit/php-code-coverage", - "version": "10.1.16", + "version": "11.0.12", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77" + "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2c1ed04922802c15e1de5d7447b4856de949cf56", + "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.19.1 || ^5.1.0", - "php": ">=8.1", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-text-template": "^3.0.1", - "sebastian/code-unit-reverse-lookup": "^3.0.0", - "sebastian/complexity": "^3.2.0", - "sebastian/environment": "^6.1.0", - "sebastian/lines-of-code": "^2.0.2", - "sebastian/version": "^4.0.1", - "theseer/tokenizer": "^1.2.3" + "nikic/php-parser": "^5.7.0", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-text-template": "^4.0.1", + "sebastian/code-unit-reverse-lookup": "^4.0.1", + "sebastian/complexity": "^4.0.1", + "sebastian/environment": "^7.2.1", + "sebastian/lines-of-code": "^3.0.1", + "sebastian/version": "^5.0.2", + "theseer/tokenizer": "^1.3.1" }, "require-dev": { - "phpunit/phpunit": "^10.1" + "phpunit/phpunit": "^11.5.46" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -506,7 +506,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.1.x-dev" + "dev-main": "11.0.x-dev" } }, "autoload": { @@ -535,40 +535,52 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.12" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", + "type": "tidelift" } ], - "time": "2024-08-22T04:31:57+00:00" + "time": "2025-12-24T07:01:01+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "4.1.0", + "version": "5.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" + "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/2f3a64888c814fc235386b7387dd5b5ed92ad903", + "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -596,36 +608,48 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-file-iterator", + "type": "tidelift" } ], - "time": "2023-08-31T06:24:48+00:00" + "time": "2026-02-02T13:52:54+00:00" }, { "name": "phpunit/php-invoker", - "version": "4.0.0", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { "ext-pcntl": "*", - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "suggest": { "ext-pcntl": "*" @@ -633,7 +657,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -659,7 +683,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" }, "funding": [ { @@ -667,32 +692,32 @@ "type": "github" } ], - "time": "2023-02-03T06:56:09+00:00" + "time": "2024-07-03T05:07:44+00:00" }, { "name": "phpunit/php-text-template", - "version": "3.0.1", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -719,7 +744,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" }, "funding": [ { @@ -727,32 +752,32 @@ "type": "github" } ], - "time": "2023-08-31T14:07:24+00:00" + "time": "2024-07-03T05:08:43+00:00" }, { "name": "phpunit/php-timer", - "version": "6.0.0", + "version": "7.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -778,7 +803,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" }, "funding": [ { @@ -786,20 +812,20 @@ "type": "github" } ], - "time": "2023-02-03T06:57:52+00:00" + "time": "2024-07-03T05:09:35+00:00" }, { "name": "phpunit/phpunit", - "version": "10.5.65", + "version": "11.5.57", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "b4f678d4ebb686d6d3bd6a7c193e8a067d1a7f01" + "reference": "36b75bf56a8535623f5b3e24b27ea1823759da1a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b4f678d4ebb686d6d3bd6a7c193e8a067d1a7f01", - "reference": "b4f678d4ebb686d6d3bd6a7c193e8a067d1a7f01", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/36b75bf56a8535623f5b3e24b27ea1823759da1a", + "reference": "36b75bf56a8535623f5b3e24b27ea1823759da1a", "shasum": "" }, "require": { @@ -812,23 +838,24 @@ "myclabs/deep-copy": "^1.14.0", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", - "php": ">=8.1", - "phpunit/php-code-coverage": "^10.1.16", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-invoker": "^4.0.0", - "phpunit/php-text-template": "^3.0.1", - "phpunit/php-timer": "^6.0.0", - "sebastian/cli-parser": "^2.0.1", - "sebastian/code-unit": "^2.0.0", - "sebastian/comparator": "^5.0.5", - "sebastian/diff": "^5.1.1", - "sebastian/environment": "^6.1.0", - "sebastian/exporter": "^5.1.4", - "sebastian/global-state": "^6.0.2", - "sebastian/object-enumerator": "^5.0.0", - "sebastian/recursion-context": "^5.0.2", - "sebastian/type": "^4.0.0", - "sebastian/version": "^4.0.1" + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.12", + "phpunit/php-file-iterator": "^5.1.1", + "phpunit/php-invoker": "^5.0.1", + "phpunit/php-text-template": "^4.0.1", + "phpunit/php-timer": "^7.0.1", + "sebastian/cli-parser": "^3.0.2", + "sebastian/code-unit": "^3.0.3", + "sebastian/comparator": "^6.3.3", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.1", + "sebastian/exporter": "^6.3.2", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/recursion-context": "^6.0.3", + "sebastian/type": "^5.1.3", + "sebastian/version": "^5.0.2", + "staabm/side-effects-detector": "^1.0.5" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files" @@ -839,7 +866,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.5-dev" + "dev-main": "11.5-dev" } }, "autoload": { @@ -871,7 +898,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.65" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.57" }, "funding": [ { @@ -879,32 +906,32 @@ "type": "other" } ], - "time": "2026-09-23T10:01:12+00:00" + "time": "2026-10-05T05:47:54+00:00" }, { "name": "sebastian/cli-parser", - "version": "2.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -928,7 +955,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" }, "funding": [ { @@ -936,32 +963,32 @@ "type": "github" } ], - "time": "2024-03-02T07:12:49+00:00" + "time": "2024-07-03T04:41:36+00:00" }, { "name": "sebastian/code-unit", - "version": "2.0.0", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.5" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -984,7 +1011,8 @@ "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3" }, "funding": [ { @@ -992,32 +1020,32 @@ "type": "github" } ], - "time": "2023-02-03T06:58:43+00:00" + "time": "2025-03-19T07:56:08+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "3.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -1039,7 +1067,8 @@ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" }, "funding": [ { @@ -1047,36 +1076,39 @@ "type": "github" } ], - "time": "2023-02-03T06:59:15+00:00" + "time": "2024-07-03T04:45:54+00:00" }, { "name": "sebastian/comparator", - "version": "5.0.5", + "version": "6.3.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d" + "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55dfef806eb7dfeb6e7a6935601fef866f8ca48d", - "reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2c95e1e86cb8dd41beb8d502057d1081ccc8eca9", + "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9", "shasum": "" }, "require": { "ext-dom": "*", "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/diff": "^5.0", - "sebastian/exporter": "^5.0" + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^10.5" + "phpunit/phpunit": "^11.4" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "6.3-dev" } }, "autoload": { @@ -1116,7 +1148,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.5" + "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.3" }, "funding": [ { @@ -1136,33 +1168,33 @@ "type": "tidelift" } ], - "time": "2026-01-24T09:25:16+00:00" + "time": "2026-01-24T09:26:40+00:00" }, { "name": "sebastian/complexity", - "version": "3.2.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "68ff824baeae169ec9f2137158ee529584553799" + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", - "reference": "68ff824baeae169ec9f2137158ee529584553799", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" + "nikic/php-parser": "^5.0", + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.2-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -1186,7 +1218,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" }, "funding": [ { @@ -1194,33 +1226,33 @@ "type": "github" } ], - "time": "2023-12-21T08:37:17+00:00" + "time": "2024-07-03T04:49:50+00:00" }, { "name": "sebastian/diff", - "version": "5.1.1", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0", - "symfony/process": "^6.4" + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.1-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -1253,7 +1285,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" }, "funding": [ { @@ -1261,27 +1293,27 @@ "type": "github" } ], - "time": "2024-03-02T07:15:17+00:00" + "time": "2024-07-03T04:53:05+00:00" }, { "name": "sebastian/environment", - "version": "6.1.0", + "version": "7.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a5c75038693ad2e8d4b6c15ba2403532647830c4", + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.3" }, "suggest": { "ext-posix": "*" @@ -1289,7 +1321,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "6.1-dev" + "dev-main": "7.2-dev" } }, "autoload": { @@ -1317,42 +1349,54 @@ "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", + "type": "tidelift" } ], - "time": "2024-03-23T08:47:14+00:00" + "time": "2025-05-21T11:55:47+00:00" }, { "name": "sebastian/exporter", - "version": "5.1.4", + "version": "6.3.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "0735b90f4da94969541dac1da743446e276defa6" + "reference": "70a298763b40b213ec087c51c739efcaa90bcd74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/0735b90f4da94969541dac1da743446e276defa6", - "reference": "0735b90f4da94969541dac1da743446e276defa6", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/70a298763b40b213ec087c51c739efcaa90bcd74", + "reference": "70a298763b40b213ec087c51c739efcaa90bcd74", "shasum": "" }, "require": { "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/recursion-context": "^5.0" + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^10.5" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.1-dev" + "dev-main": "6.3-dev" } }, "autoload": { @@ -1395,7 +1439,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.4" + "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.2" }, "funding": [ { @@ -1415,35 +1459,35 @@ "type": "tidelift" } ], - "time": "2025-09-24T06:09:11+00:00" + "time": "2025-09-24T06:12:51+00:00" }, { "name": "sebastian/global-state", - "version": "6.0.2", + "version": "7.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", "shasum": "" }, "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -1469,7 +1513,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" }, "funding": [ { @@ -1477,33 +1521,33 @@ "type": "github" } ], - "time": "2024-03-02T07:19:19+00:00" + "time": "2024-07-03T04:57:36+00:00" }, { "name": "sebastian/lines-of-code", - "version": "2.0.2", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" + "nikic/php-parser": "^5.0", + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -1527,7 +1571,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" }, "funding": [ { @@ -1535,34 +1579,34 @@ "type": "github" } ], - "time": "2023-12-21T08:38:20+00:00" + "time": "2024-07-03T04:58:38+00:00" }, { "name": "sebastian/object-enumerator", - "version": "5.0.0", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", "shasum": "" }, "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -1584,7 +1628,8 @@ "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" }, "funding": [ { @@ -1592,32 +1637,32 @@ "type": "github" } ], - "time": "2023-02-03T07:08:32+00:00" + "time": "2024-07-03T05:00:13+00:00" }, { "name": "sebastian/object-reflector", - "version": "3.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -1639,7 +1684,8 @@ "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" }, "funding": [ { @@ -1647,32 +1693,32 @@ "type": "github" } ], - "time": "2023-02-03T07:06:18+00:00" + "time": "2024-07-03T05:01:32+00:00" }, { "name": "sebastian/recursion-context", - "version": "5.0.2", + "version": "6.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "5d32fe257a9b39cb63146924d6b4e32a22d4502a" + "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5d32fe257a9b39cb63146924d6b4e32a22d4502a", - "reference": "5d32fe257a9b39cb63146924d6b4e32a22d4502a", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/f6458abbf32a6c8174f8f26261475dc133b3d9dc", + "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.5" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -1703,7 +1749,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.2" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.3" }, "funding": [ { @@ -1723,32 +1769,32 @@ "type": "tidelift" } ], - "time": "2026-08-11T05:27:39+00:00" + "time": "2025-08-13T04:42:22+00:00" }, { "name": "sebastian/type", - "version": "4.0.0", + "version": "5.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" + "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/f77d2d4e78738c98d9a68d2596fe5e8fa380f449", + "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -1771,37 +1817,50 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.1.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/type", + "type": "tidelift" } ], - "time": "2023-02-03T07:10:45+00:00" + "time": "2025-08-09T06:55:48+00:00" }, { "name": "sebastian/version", - "version": "4.0.1", + "version": "5.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -1824,7 +1883,8 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" }, "funding": [ { @@ -1832,7 +1892,7 @@ "type": "github" } ], - "time": "2023-02-07T11:34:05+00:00" + "time": "2024-10-09T05:16:32+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -1918,6 +1978,58 @@ ], "time": "2026-08-06T02:45:27+00:00" }, + { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+00:00" + }, { "name": "theseer/tokenizer", "version": "1.3.1", @@ -1975,7 +2087,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=8.1", + "php": ">=8.2", "ext-ctype": "*", "ext-curl": "*", "ext-dom": "*", @@ -1998,13 +2110,13 @@ "ext-zlib": "*" }, "platform-dev": { - "php": ">=8.1", + "php": ">=8.2", "ext-phar": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*" }, "platform-overrides": { - "php": "8.1" + "php": "8.2" }, "plugin-api-version": "2.9.0" } diff --git a/constants.php b/constants.php index fca08c0a4..8bd6b9f9c 100644 --- a/constants.php +++ b/constants.php @@ -4,7 +4,7 @@ declare(strict_types=1); // /** @var string */ -const FRESHRSS_MIN_PHP_VERSION = '8.1.0'; +const FRESHRSS_MIN_PHP_VERSION = '8.2.0'; /** @var string */ const FRESHRSS_VERSION = '1.30.5-dev'; /** @var string */ diff --git a/docs/en/admins/02_Prerequisites.md b/docs/en/admins/02_Prerequisites.md index 0fe8793df..864a316b9 100644 --- a/docs/en/admins/02_Prerequisites.md +++ b/docs/en/admins/02_Prerequisites.md @@ -7,7 +7,7 @@ You need to verify that your server can run FreshRSS before installing it. If yo | Software | Recommended | Also Works With | | ------------- | ----------------------- | ----------------------- | | Web server | **Apache 2.4** | nginx, lighttpd | -| PHP | **PHP 8.1+** | FreshRSS 1.24.3: PHP 7.4+
FreshRSS 1.22.1: PHP 7.2+ | +| PHP | **PHP 8.2+** | FreshRSS 1.30.4: PHP 8.1+ | | PHP modules | Required: libxml, cURL, JSON, PDO_MySQL, PCRE and ctype.
Required (32-bit only): GMP
Recommended: Zlib, mbstring, iconv, ZipArchive
*For the whole modules list see [Dockerfile](https://github.com/FreshRSS/FreshRSS/blob/edge/Docker/Dockerfile-Alpine#L9-L11)* | | | Database | **PostgreSQL 10+** | SQLite, MariaDB 10.6+, MySQL 8.0+ | | Browser | **Firefox** | Chrome, Opera, Safari, or Edge | diff --git a/docs/en/admins/10_ServerConfig.md b/docs/en/admins/10_ServerConfig.md index 1ca99883c..f90d336f8 100644 --- a/docs/en/admins/10_ServerConfig.md +++ b/docs/en/admins/10_ServerConfig.md @@ -95,7 +95,7 @@ server { # php files handling # this regex is mandatory because of the API location ~ ^.+?\.php(/.*)?$ { - fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; + fastcgi_pass unix:/var/run/php/php8.2-fpm.sock; fastcgi_split_path_info ^(.+\.php)(/.*)$; # By default, the variable PATH_INFO is not set under PHP-FPM # But FreshRSS APIs greader.php and misc.php need it. If you have a “Bad Request” error, double check this var! diff --git a/docs/fr/users/01_Installation.md b/docs/fr/users/01_Installation.md index 6880e0059..a6b09be93 100644 --- a/docs/fr/users/01_Installation.md +++ b/docs/fr/users/01_Installation.md @@ -7,7 +7,7 @@ Il est toutefois de votre responsabilité de vérifier que votre hébergement pe | Logiciel | Recommandé | Fonctionne aussi avec | | -------- | ----------- | --------------------- | | Serveur web | **Apache 2.4+** | nginx, lighttpd | -| PHP | **PHP 8.1+** | FreshRSS 1.24.3 : PHP 7.4+
FreshRSS 1.22.1 : PHP 7.2+ | +| PHP | **PHP 8.2+** | FreshRSS 1.30.4 : PHP 8.1+ | | Modules PHP | Requis : libxml, cURL, JSON, PDO_MySQL, PCRE et ctype
Requis (32 bits seulement) : GMP
Recommandé : Zlib, mbstring et iconv, ZipArchive
*Pour une liste complète des modules nécessaires voir le [Dockerfile](https://github.com/FreshRSS/FreshRSS/blob/edge/Docker/Dockerfile-Alpine#L9-L11)* | | | Base de données | **PostgreSQL 10+** | SQLite, MariaDB 10.6+, MySQL 8.0+ | | Navigateur | **Firefox** | Chrome, Opera, Safari, or Edge | @@ -118,7 +118,7 @@ server { # gestion des fichiers php # il est nécessaire d’utiliser cette expression régulière pour le bon fonctionnement de l’API location ~ ^.+?\.php(/.*)?$ { - fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; + fastcgi_pass unix:/var/run/php/php8.2-fpm.sock; fastcgi_split_path_info ^(.+\.php)(/.*)$; # Par défaut la variable PATH_INFO n’est pas définie sous PHP-FPM # mais les APIs FreshRSS greader.php et misc.php en ont besoin. Si vous avez un “Bad Request”, vérifiez bien cette dernière ! diff --git a/lib/Minz/Hook.php b/lib/Minz/Hook.php index cd56de646..fb21fd83a 100644 --- a/lib/Minz/Hook.php +++ b/lib/Minz/Hook.php @@ -1,7 +1,7 @@ */ public static function provideTooLongOrTooDeepSearches(): array { + if (!FreshRSS_Context::hasSystemConf()) { + FreshRSS_Context::initSystem(); + } $tooLong = str_repeat('a', FreshRSS_Context::systemConf()->limits['max_search_length'] + 1); $tooDeep = str_repeat('(', FreshRSS_Context::systemConf()->limits['max_search_parentheses_depth'] + 1) . 'ab' . str_repeat(')', FreshRSS_Context::systemConf()->limits['max_search_parentheses_depth'] + 1); diff --git a/tests/app/Models/EntryTest.php b/tests/app/Models/EntryTest.php index 7dcaa2850..37874a909 100644 --- a/tests/app/Models/EntryTest.php +++ b/tests/app/Models/EntryTest.php @@ -3,8 +3,8 @@ declare(strict_types=1); final class EntryTest extends \PHPUnit\Framework\TestCase { - public function __construct(string $name) { - parent::__construct($name); + #[\Override] + protected function setUp(): void { if (!FreshRSS_Context::hasSystemConf()) { FreshRSS_Context::initSystem(); } diff --git a/tests/app/Models/SearchTest.php b/tests/app/Models/SearchTest.php index 1daa460c8..a376fda31 100644 --- a/tests/app/Models/SearchTest.php +++ b/tests/app/Models/SearchTest.php @@ -7,8 +7,8 @@ require_once LIB_PATH . '/lib_date.php'; final class SearchTest extends \PHPUnit\Framework\TestCase { - public function __construct(string $name) { - parent::__construct($name); + #[\Override] + protected function setUp(): void { if (!FreshRSS_Context::hasSystemConf()) { FreshRSS_Context::initSystem(); } @@ -866,10 +866,8 @@ final class SearchTest extends \PHPUnit\Framework\TestCase { ]; } - /** - * @dataProvider provideRegexPostreSQL - * @param array $values - */ + /** @param array $values */ + #[DataProvider('provideRegexPostreSQL')] public function test__regex_postgresql(string $input, string $sql, array $values): void { [$filterValues, $filterSearch] = FreshRSS_EntryDAOPGSQL::sqlBooleanSearch('e.', new FreshRSS_BooleanSearch($input)); self::assertSame(trim($sql), trim($filterSearch)); @@ -977,10 +975,8 @@ final class SearchTest extends \PHPUnit\Framework\TestCase { ]; } - /** - * @dataProvider provideRegexMariaDB - * @param array $values - */ + /** @param array $values */ + #[DataProvider('provideRegexMariaDB')] public function test__regex_mariadb(string $input, string $sql, array $values): void { FreshRSS_DatabaseDAO::$dummyConnection = true; FreshRSS_DatabaseDAO::setStaticVersion('11.4.3-MariaDB-ubu2404'); @@ -1030,10 +1026,8 @@ final class SearchTest extends \PHPUnit\Framework\TestCase { ]; } - /** - * @dataProvider provideRegexMySQL - * @param array $values - */ + /** @param array $values */ + #[DataProvider('provideRegexMySQL')] public function test__regex_mysql(string $input, string $sql, array $values): void { FreshRSS_DatabaseDAO::$dummyConnection = true; FreshRSS_DatabaseDAO::setStaticVersion('9.0.1'); @@ -1078,10 +1072,8 @@ final class SearchTest extends \PHPUnit\Framework\TestCase { ]; } - /** - * @dataProvider provideRegexSQLite - * @param array $values - */ + /** @param array $values */ + #[DataProvider('provideRegexSQLite')] public function test__regex_sqlite(string $input, string $sql, array $values): void { [$filterValues, $filterSearch] = FreshRSS_EntryDAOSQLite::sqlBooleanSearch('e.', new FreshRSS_BooleanSearch($input)); self::assertSame(trim($sql), trim($filterSearch)); diff --git a/tests/app/Models/SimplePieCustomTest.php b/tests/app/Models/SimplePieCustomTest.php index 7b7b13ba9..764cfc965 100644 --- a/tests/app/Models/SimplePieCustomTest.php +++ b/tests/app/Models/SimplePieCustomTest.php @@ -9,8 +9,8 @@ use PHPUnit\Framework\Attributes\DataProvider; */ final class SimplePieCustomTest extends \PHPUnit\Framework\TestCase { - public function __construct(string $name) { - parent::__construct($name); + #[\Override] + protected function setUp(): void { if (!FreshRSS_Context::hasSystemConf()) { FreshRSS_Context::initSystem(); } diff --git a/tests/app/Models/UserQueryTest.php b/tests/app/Models/UserQueryTest.php index fb6d12e0a..93f2d1a61 100644 --- a/tests/app/Models/UserQueryTest.php +++ b/tests/app/Models/UserQueryTest.php @@ -8,8 +8,8 @@ use PHPUnit\Framework\TestCase; */ class UserQueryTest extends TestCase { - public function __construct(string $name) { - parent::__construct($name); + #[\Override] + protected function setUp(): void { if (!FreshRSS_Context::hasSystemConf()) { FreshRSS_Context::initSystem(); } diff --git a/tests/app/Utils/httpUtilTest.php b/tests/app/Utils/httpUtilTest.php index 5284a75e5..471703ed9 100644 --- a/tests/app/Utils/httpUtilTest.php +++ b/tests/app/Utils/httpUtilTest.php @@ -114,33 +114,34 @@ final class httpUtilTest extends \PHPUnit\Framework\TestCase { ); } - public function test_getCurlResolveInfoRejectsPrivateNat64Address(): void { + #[DataProvider('providePrivateSubnets')] + public function test_getCurlResolveInfoRejectsPrivateSubnets(string $ip): void { FreshRSS_Context::initSystem(); $resolveOk = new ReflectionProperty(FreshRSS_http_Util::class, 'resolve_ok'); - $resolveOk->setValue(null, [ - 'example.test' => [ - '64:ff9b::a9fe:a9fe', - ], - ]); - - self::assertNull( - FreshRSS_http_Util::getCurlResolveInfo('https://example.test/feed') - ); + $resolveOk->setValue(null, ['example.test' => [$ip]]); + self::assertNull(FreshRSS_http_Util::getCurlResolveInfo('https://example.test/feed')); } - public function test_getCurlResolveInfoRejectsLocalUseNat64Address(): void { - FreshRSS_Context::initSystem(); - $resolveOk = new ReflectionProperty(FreshRSS_http_Util::class, 'resolve_ok'); - $resolveOk->setValue(null, [ - 'example.test' => [ - '64:ff9b:1::c000:4260', - '64:ff9b:1::a9fe:a9fe', - ], - ]); - - self::assertNull( - FreshRSS_http_Util::getCurlResolveInfo('https://example.test/feed') - ); + /** @return array */ + public static function providePrivateSubnets(): array { + return [ + // One example per range, ensuring FILTER_FLAG_GLOBAL_RANGE and custom checks are sufficient + '127.0.0.0/8' => ['127.0.0.1'], // RFC1700 (Loopback) + '10.0.0.0/8' => ['10.0.0.5'], // RFC1918 + '192.168.0.0/16' => ['192.168.1.5'], // RFC1918 + '172.16.0.0/12' => ['172.16.5.5'], // RFC1918 + '169.254.0.0/16' => ['169.254.5.5'], // RFC3927 + '0.0.0.0/8' => ['0.0.0.5'], // RFC5735 + '240.0.0.0/4' => ['240.0.0.5'], // RFC1112 + '100.64.0.0/10' => ['100.64.5.5'], // RFC6598 (Shared Address Space of Carrier-Grade NAT) + '::1/128' => ['::1'], // Loopback + 'fc00::/7' => ['fc00::5'], // Unique Local Address + 'fe80::/10' => ['fe80::5'], // Link Local Address + '::ffff:0:0/96' => ['::ffff:10.0.0.5'], // IPv4 translations + '64:ff9b::/96' => ['64:ff9b::a9fe:a9fe'], // RFC6052 (IPv4/IPv6 Translator, NAT64) + '64:ff9b:1::/48' => ['64:ff9b:1::c000:4260'], // RFC8215 (Local-Use IPv4/IPv6 Translation Prefix) + '::/128' => ['::'], // Unspecified address + ]; } /** Socks schemes default to port 1080, and an IP address proxy produces no resolve entry */ @@ -171,11 +172,16 @@ final class httpUtilTest extends \PHPUnit\Framework\TestCase { FreshRSS_http_Util::getCurlResolveInfo('socks5h://proxy.example.test:1080') ); - // An entry is still produced without allowlisting, because the address is public + // Applications must not emit resolve entries for an address that is not guaranteed public. + // TEST-NET-2 is a reserved range, so without an allowlist entry, no entry is produced. FreshRSS_Context::systemConf()->internal_host_allowlist = []; + self::assertNull(FreshRSS_http_Util::getCurlResolveInfo('socks5h://proxy.example.test:1080')); + + // A genuinely public address produces an entry without allowlisting + $resolveOk->setValue(null, ['public-proxy.example.test' => ['8.8.8.8']]); self::assertSame( - ['proxy.example.test:1080:198.51.100.7'], - FreshRSS_http_Util::getCurlResolveInfo('socks5h://proxy.example.test:1080') + ['public-proxy.example.test:1080:8.8.8.8'], + FreshRSS_http_Util::getCurlResolveInfo('socks5h://public-proxy.example.test:1080') ); // A proxy resolving to a private address is rejected unless allowlisted