diff --git a/app/Controllers/updateController.php b/app/Controllers/updateController.php index 051303047..7e7044cb8 100644 --- a/app/Controllers/updateController.php +++ b/app/Controllers/updateController.php @@ -231,9 +231,9 @@ class FreshRSS_update_Controller extends FreshRSS_ActionController { curl_setopt($curlResource, CURLOPT_SSL_VERIFYHOST, 2); $curl_options = []; - if (defined('CURLOPT_PROTOCOLS_STR')) { + if (defined('CURLOPT_PROTOCOLS_STR') && is_int(CURLOPT_PROTOCOLS_STR)) { $curl_options[CURLOPT_PROTOCOLS_STR] = 'http,https'; - if (defined('CURLOPT_REDIR_PROTOCOLS_STR')) { + if (defined('CURLOPT_REDIR_PROTOCOLS_STR') && is_int(CURLOPT_REDIR_PROTOCOLS_STR)) { $curl_options[CURLOPT_REDIR_PROTOCOLS_STR] = 'http,https'; } } elseif (defined('CURLPROTO_HTTP') && defined('CURLPROTO_HTTPS')) { diff --git a/app/Models/Feed.php b/app/Models/Feed.php index e10bd2c40..83621436e 100644 --- a/app/Models/Feed.php +++ b/app/Models/Feed.php @@ -1457,9 +1457,9 @@ class FreshRSS_Feed extends Minz_Model { ]); $curl_options = []; - if (defined('CURLOPT_PROTOCOLS_STR')) { + if (defined('CURLOPT_PROTOCOLS_STR') && is_int(CURLOPT_PROTOCOLS_STR)) { $curl_options[CURLOPT_PROTOCOLS_STR] = 'http,https'; - if (defined('CURLOPT_REDIR_PROTOCOLS_STR')) { + if (defined('CURLOPT_REDIR_PROTOCOLS_STR') && is_int(CURLOPT_REDIR_PROTOCOLS_STR)) { $curl_options[CURLOPT_REDIR_PROTOCOLS_STR] = 'http,https'; } } elseif (defined('CURLPROTO_HTTP') && defined('CURLPROTO_HTTPS')) { diff --git a/app/Models/SimplePieCustom.php b/app/Models/SimplePieCustom.php index af2b05714..89b98c701 100644 --- a/app/Models/SimplePieCustom.php +++ b/app/Models/SimplePieCustom.php @@ -44,9 +44,9 @@ final class FreshRSS_SimplePieCustom extends \SimplePie\SimplePie unset($curl_options[CURLOPT_PROXY]); } } - if (defined('CURLOPT_PROTOCOLS_STR')) { + if (defined('CURLOPT_PROTOCOLS_STR') && is_int(CURLOPT_PROTOCOLS_STR)) { $curl_options[CURLOPT_PROTOCOLS_STR] = 'http,https'; - if (defined('CURLOPT_REDIR_PROTOCOLS_STR')) { + if (defined('CURLOPT_REDIR_PROTOCOLS_STR') && is_int(CURLOPT_REDIR_PROTOCOLS_STR)) { $curl_options[CURLOPT_REDIR_PROTOCOLS_STR] = 'http,https'; } } elseif (defined('CURLPROTO_HTTP') && defined('CURLPROTO_HTTPS')) { diff --git a/app/Utils/httpUtil.php b/app/Utils/httpUtil.php index 9a66c7fcf..57a508a01 100644 --- a/app/Utils/httpUtil.php +++ b/app/Utils/httpUtil.php @@ -369,9 +369,9 @@ final class FreshRSS_http_Util { } } - if (defined('CURLOPT_PROTOCOLS_STR')) { + if (defined('CURLOPT_PROTOCOLS_STR') && is_int(CURLOPT_PROTOCOLS_STR)) { $curl_options[CURLOPT_PROTOCOLS_STR] = 'http,https'; - if (defined('CURLOPT_REDIR_PROTOCOLS_STR')) { + if (defined('CURLOPT_REDIR_PROTOCOLS_STR') && is_int(CURLOPT_REDIR_PROTOCOLS_STR)) { $curl_options[CURLOPT_REDIR_PROTOCOLS_STR] = 'http,https'; } } elseif (defined('CURLPROTO_HTTP') && defined('CURLPROTO_HTTPS')) { diff --git a/composer.lock b/composer.lock index 3f8b6efc7..5d9623fe9 100644 --- a/composer.lock +++ b/composer.lock @@ -245,11 +245,11 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.46", + "version": "2.1.54", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/a193923fc2d6325ef4e741cf3af8c3e8f54dbf25", - "reference": "a193923fc2d6325ef4e741cf3af8c3e8f54dbf25", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/8be50c3992107dc837b17da4d140fbbdf9a5c5bd", + "reference": "8be50c3992107dc837b17da4d140fbbdf9a5c5bd", "shasum": "" }, "require": { @@ -294,7 +294,7 @@ "type": "github" } ], - "time": "2026-04-01T09:25:14+00:00" + "time": "2026-04-29T13:31:09+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", @@ -404,16 +404,16 @@ }, { "name": "phpstan/phpstan-strict-rules", - "version": "2.0.10", + "version": "2.0.11", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "1aba28b697c1e3b6bbec8a1725f8b11b6d3e5a5f" + "reference": "9b000a578b85b32945b358b172c7b20e91189024" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/1aba28b697c1e3b6bbec8a1725f8b11b6d3e5a5f", - "reference": "1aba28b697c1e3b6bbec8a1725f8b11b6d3e5a5f", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/9b000a578b85b32945b358b172c7b20e91189024", + "reference": "9b000a578b85b32945b358b172c7b20e91189024", "shasum": "" }, "require": { @@ -449,9 +449,9 @@ ], "support": { "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", - "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.10" + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.11" }, - "time": "2026-02-11T14:17:32+00:00" + "time": "2026-05-02T06:54:10+00:00" }, { "name": "phpunit/php-code-coverage", @@ -2003,5 +2003,5 @@ "platform-overrides": { "php": "8.1" }, - "plugin-api-version": "2.9.0" + "plugin-api-version": "2.6.0" } diff --git a/lib/Minz/ModelPdo.php b/lib/Minz/ModelPdo.php index 1c21a5ed0..7005a9e83 100644 --- a/lib/Minz/ModelPdo.php +++ b/lib/Minz/ModelPdo.php @@ -58,11 +58,12 @@ class Minz_ModelPdo { $dsn .= ';port=' . $dbServer['port']; } if (class_exists('Pdo\Mysql')) { - $driver_options[Pdo\Mysql::ATTR_INIT_COMMAND] = 'SET NAMES utf8mb4'; // @phpstan-ignore offsetAccess.invalidOffset + assert(is_int(Pdo\Mysql::ATTR_INIT_COMMAND)); // For PHPStan with PHP 8.4+ + $driver_options[Pdo\Mysql::ATTR_INIT_COMMAND] = 'SET NAMES utf8mb4'; } else { $driver_options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES utf8mb4'; // PHP < 8.4 } - $this->pdo = new Minz_PdoMysql($dsn . $dsnParams, $db['user'], $db['password'], $driver_options); // @phpstan-ignore argument.type + $this->pdo = new Minz_PdoMysql($dsn . $dsnParams, $db['user'], $db['password'], $driver_options); $this->pdo->setPrefix($db['prefix'] . $this->current_user . '_'); break; case 'sqlite': diff --git a/lib/Minz/PdoMysql.php b/lib/Minz/PdoMysql.php index 98156ad0e..1ad6b44cf 100644 --- a/lib/Minz/PdoMysql.php +++ b/lib/Minz/PdoMysql.php @@ -14,7 +14,8 @@ class Minz_PdoMysql extends Minz_Pdo { public function __construct(string $dsn, ?string $username = null, ?string $passwd = null, ?array $options = null) { parent::__construct($dsn, $username, $passwd, $options); if (class_exists('Pdo\Mysql')) { - $this->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, false); // @phpstan-ignore argument.type + assert(is_int(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY)); // For PHPStan with PHP 8.4+ + $this->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, false); } else { $this->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); // PHP < 8.4 } diff --git a/lib/lib_rss.php b/lib/lib_rss.php index e293e530b..afe4d7681 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -146,7 +146,7 @@ function echoJson($json, int $optimisationDepth = -1): void { } function safe_ascii(?string $text): string { - return $text === null ? '' : (filter_var($text, FILTER_DEFAULT, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH) ?: ''); + return $text === null ? '' : (filter_var($text, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH) ?: ''); } if (function_exists('mb_convert_encoding')) { diff --git a/phpstan.dist.neon b/phpstan.dist.neon index 0132b7c4a..093c15364 100644 --- a/phpstan.dist.neon +++ b/phpstan.dist.neon @@ -60,6 +60,14 @@ parameters: - message: '#Access to deprecated#' path: app/Models/Context.php + - + # For PHP 8.2 and PHP 8.3 + identifier: function.alreadyNarrowedType + message: '#Call to function is_int\(\) with 1\d{3} will always evaluate to true\.#' + paths: + - lib/Minz/ModelPdo.php + - lib/Minz/PdoMysql.php + reportUnmatched: false includes: - vendor/phpstan/phpstan-deprecation-rules/rules.neon - vendor/phpstan/phpstan-phpunit/extension.neon