$v) $hdr[] = "$k: $v"; curl_setopt_array($ch, [ CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_MAXREDIRS => 8, CURLOPT_TIMEOUT => $this->timeout, CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_ENCODING => '', CURLOPT_USERAGENT => $headers['user-agent'] ?? $this->user_agent, CURLOPT_HTTPHEADER => $hdr, ]); $body = curl_exec($ch); $err = curl_error($ch); $status = (int) curl_getinfo($ch, CURLINFO_RESPONSE_CODE); $effective = (string) curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); $content_type = (string) curl_getinfo($ch, CURLINFO_CONTENT_TYPE); curl_close($ch); if ($err !== '' || !is_string($body)) return new FetchResult(error: $err !== '' ? $err : 'empty response', status: $status, effective_url: $effective ?: $url); if ($status >= 400) return new FetchResult(error: "HTTP $status", status: $status, effective_url: $effective ?: $url); return new FetchResult( html: self::to_utf8($body, $content_type), effective_url: $effective ?: $url, status: $status, ); } /** * Normalise to UTF-8. Several of these feeds are Polish, and a page served as * ISO-8859-2 that is treated as UTF-8 loses every accented character. */ public static function to_utf8(string $body, string $content_type): string { $charset = ''; if (preg_match('/charset=["\']?([\w-]+)/i', $content_type, $m)) $charset = $m[1]; if ($charset === '' && preg_match('/]+charset=["\']?([\w-]+)/i', substr($body, 0, 4096), $m)) $charset = $m[1]; if ($charset === '' || preg_match('/^utf-?8$/i', $charset)) return $body; $converted = @mb_convert_encoding($body, 'UTF-8', $charset); return is_string($converted) && $converted !== '' ? $converted : $body; } }