diff --git a/src/File.php b/src/File.php index 13a50afdf..d0e526c3d 100644 --- a/src/File.php +++ b/src/File.php @@ -179,6 +179,55 @@ public function __construct(string $url, int $timeout = 10, int $redirects = 5, $this->success = false; return; } + + // FreshRSS: POST to GET on redirect + if (isset($curl_options[CURLOPT_POST]) && in_array($this->status_code, [301, 302, 303], true)) { // Not for 307 and 308, which must not change the HTTP method + unset($curl_options[CURLOPT_POST]); + unset($curl_options[CURLOPT_POSTFIELDS]); + if (is_array($curl_options[CURLOPT_HTTPHEADER] ?? null)) { + $curl_options[CURLOPT_HTTPHEADER] = array_filter( + $curl_options[CURLOPT_HTTPHEADER], + function ($header) { + return is_string($header) && substr(strtolower(trim($header)), 0, 13) !== 'content-type:'; + } + ); + } + } + // FreshRSS: cross-origin authentication headers removal + if (($url_parts_from = parse_url(strtolower($url))) === false) { + throw new \InvalidArgumentException('Malformed URL: ' . $url); + } + if (($url_parts_to = parse_url(strtolower($location))) === false) { + $this->error = "Invalid redirect location: malformed URL “{$location}”"; + $this->success = false; + return; + } + foreach ([&$url_parts_from, &$url_parts_to] as &$url_parts) { + if (!isset($url_parts['port']) && isset($url_parts['scheme'])) { + if ($url_parts['scheme'] === 'http') { + $url_parts['port'] = 80; + } elseif ($url_parts['scheme'] === 'https') { + $url_parts['port'] = 443; + } + } + } + unset($url_parts); + $sameOriginRedirect = + ($url_parts_from['scheme'] ?? '') === ($url_parts_to['scheme'] ?? '') && + ($url_parts_from['host'] ?? '') === ($url_parts_to['host'] ?? '') && + ($url_parts_from['port'] ?? '') === ($url_parts_to['port'] ?? ''); + if (!$sameOriginRedirect) { + unset($curl_options[CURLOPT_COOKIE]); + if (is_array($curl_options[CURLOPT_HTTPHEADER] ?? null)) { + $curl_options[CURLOPT_HTTPHEADER] = array_filter( + $curl_options[CURLOPT_HTTPHEADER], + function ($header) { + return is_string($header) && !preg_match('/^(Cookie|Authorization)\s*:/i', $header); + } + ); + } + } + $this->permanentUrlMutable = $this->permanentUrlMutable && ($this->status_code == 301 || $this->status_code == 308); $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen, $curl_options); return;