mirror of
https://github.com/FreshRSS/FreshRSS.git
synced 2026-10-28 05:58:40 -04:00
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
89 lines
3.2 KiB
PHP
89 lines
3.2 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
final class FreshRSS_SimplePieFetch extends \SimplePie\File
|
|
{
|
|
public function __construct(string $url, int $timeout = 10, int $redirects = 5,
|
|
?array $headers = null, ?string $useragent = null, bool $force_fsockopen = false, array $curl_options = []) {
|
|
|
|
// Remove case-insensitively default HTTP headers passed by $headers if they are overridden by $curl_options[CURLOPT_HTTPHEADER]
|
|
if (is_array($curl_options[CURLOPT_HTTPHEADER] ?? null) && is_array($headers)) {
|
|
$existingKeys = [];
|
|
foreach ($curl_options[CURLOPT_HTTPHEADER] as $headerLine) {
|
|
if (!is_string($headerLine)) {
|
|
continue;
|
|
}
|
|
$parts = explode(':', $headerLine, 2);
|
|
if (count($parts) >= 2) {
|
|
$existingKeys[strtolower(trim($parts[0]))] = true;
|
|
}
|
|
}
|
|
foreach ($headers as $key => $value) {
|
|
if (isset($existingKeys[strtolower($key)])) {
|
|
unset($headers[$key]);
|
|
}
|
|
}
|
|
}
|
|
|
|
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])) {
|
|
if ($curl_options[CURLOPT_FOLLOWLOCATION] == true) {
|
|
unset($curl_options[CURLOPT_FOLLOWLOCATION]); // Favour the custom SimplePie redirects for security
|
|
} else {
|
|
$curl_options[CURLOPT_FOLLOWLOCATION] = false;
|
|
unset($curl_options[CURLOPT_MAXREDIRS]);
|
|
$redirects = 0;
|
|
}
|
|
}
|
|
|
|
parent::__construct($url, $timeout, $redirects, $headers, $useragent, $force_fsockopen, $curl_options);
|
|
}
|
|
|
|
#[\Override]
|
|
protected function get_curl_resolve_info(string $url): array|null|false {
|
|
return FreshRSS_http_Util::getCurlResolveInfo($url);
|
|
}
|
|
|
|
#[\Override]
|
|
protected function on_http_response($response, array $curl_options = []): void {
|
|
if (!\SimplePie\Misc::is_remote_uri($this->get_final_requested_uri())) {
|
|
$this->set_status_code(0);
|
|
$this->set_body_content('');
|
|
$this->error = 'Fetching non-remote URLs is not permitted: “' . $this->get_final_requested_uri() . '“';
|
|
$this->success = false;
|
|
$response = '';
|
|
}
|
|
|
|
if (FreshRSS_Context::systemConf()->simplepie_syslog_enabled) {
|
|
syslog(LOG_INFO, 'FreshRSS SimplePie GET ' . $this->get_status_code() . ' ' . \SimplePie\Misc::url_remove_credentials($this->get_final_requested_uri()));
|
|
}
|
|
|
|
if (in_array($this->get_status_code(), [429, 503], true)) {
|
|
$parser = new \SimplePie\HTTP\Parser(is_string($response) ? $response : '');
|
|
if ($parser->parse()) {
|
|
$headers = $parser->headers;
|
|
} else {
|
|
$headers = [];
|
|
}
|
|
|
|
$proxy = is_string($curl_options[CURLOPT_PROXY] ?? null) ? $curl_options[CURLOPT_PROXY] : '';
|
|
$retryAfter = FreshRSS_http_Util::setRetryAfter($this->get_final_requested_uri(), $proxy, $headers['retry-after'] ?? '');
|
|
if ($retryAfter > 0) {
|
|
$domain = parse_url($this->get_final_requested_uri(), PHP_URL_HOST);
|
|
if (is_string($domain) && $domain !== '') {
|
|
if (is_int($port = parse_url($this->get_final_requested_uri(), PHP_URL_PORT))) {
|
|
$domain .= ':' . $port;
|
|
}
|
|
$errorMessage = 'Will retry after ' . date('c', $retryAfter) . ' for domain `' . $domain . '`';
|
|
Minz_Log::notice($errorMessage);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|