From 4aa5a86a2b52e5d11eec0591da014a99c876921d Mon Sep 17 00:00:00 2001
From: Julian Prieber <60265788+JulianPrieber@users.noreply.github.com>
Date: Mon, 10 Jul 2023 18:35:20 +0200
Subject: [PATCH] Fixed favicons not loading
---
resources/views/components/favicon.blade.php | 200 +++++++++++++------
1 file changed, 136 insertions(+), 64 deletions(-)
diff --git a/resources/views/components/favicon.blade.php b/resources/views/components/favicon.blade.php
index c2c1d15..934161e 100644
--- a/resources/views/components/favicon.blade.php
+++ b/resources/views/components/favicon.blade.php
@@ -1,87 +1,159 @@
-
-
link;
+use App\Models\Link;
- $html = false;
- $context = stream_context_create();
+function getFaviconURL($url)
+{
+ $ch = curl_init($url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_HEADER, true);
+ curl_setopt($ch, CURLOPT_NOBODY, true);
+ curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36');
+ curl_setopt($ch, CURLOPT_TIMEOUT, 3);
+ $response = curl_exec($ch);
- // Set timeout to 3 seconds
- stream_context_set_option($context, 'http', 'timeout', 3);
-
- // Set custom User-Agent header
- $userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36';
- stream_context_set_option($context, 'http', 'header', "User-Agent: $userAgent\r\n");
-
- // Attempt to fetch HTML content with timeout
- if (function_exists('curl_version')) {
- $curlHandle = curl_init($url);
- curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($curlHandle, CURLOPT_TIMEOUT, 3);
- curl_setopt($curlHandle, CURLOPT_USERAGENT, $userAgent);
- $html = curl_exec($curlHandle);
- curl_close($curlHandle);
- } else {
- $html = @file_get_contents($url, false, $context);
+ // Check if cURL request was successful
+ if ($response === false) {
+ return null;
}
-
-$dom = new DOMDocument();
-if ($html !== false) {
+ $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+ curl_close($ch);
+
+ // Check if the URL is redirected
+ if ($httpCode == 301 || $httpCode == 302) {
+ $redirectUrl = getRedirectUrlFromHeaders($response);
+ if ($redirectUrl) {
+ return getFaviconURL($redirectUrl); // Recursively call getFavicon with the redirected URL
+ }
+ }
+
+ // Try extracting favicon using DOMDocument
try {
- @$dom->loadHTML($html);
- } catch (Throwable $e) {}
+ $dom = new DOMDocument();
+ $dom->strictErrorChecking = false;
+ @$dom->loadHTMLFile($url);
+ if ($dom) {
+ $domxml = simplexml_import_dom($dom);
+ // Check for the historical rel="shortcut icon"
+ if ($domxml->xpath('//link[@rel="shortcut icon"]')) {
+ $path = $domxml->xpath('//link[@rel="shortcut icon"]');
+ $faviconURL = getAbsoluteUrl($url, $path[0]['href']);
+ return $faviconURL;
+ }
+ // Check for the HTML5 rel="icon"
+ elseif ($domxml->xpath('//link[@rel="icon"]')) {
+ $path = $domxml->xpath('//link[@rel="icon"]');
+ $faviconURL = getAbsoluteUrl($url, $path[0]['href']);
+ return $faviconURL;
+ }
+ }
+ } catch (Exception $e) {
+ // Silently fail and continue to the next method
+ }
+
+ // Check directly for favicon.ico or favicon.png
+ $parse = parse_url($url);
+ $favicon_headers = @get_headers("http://" . $parse['host'] . "/favicon.ico");
+ if ($favicon_headers && $favicon_headers[0] != 'HTTP/1.1 404 Not Found') {
+ $faviconURL = "http://" . $parse['host'] . "/favicon.ico";
+ return $faviconURL;
+ }
+
+ $favicon_headers = @get_headers("http://" . $parse['host'] . "/favicon.png");
+ if ($favicon_headers && $favicon_headers[0] != 'HTTP/1.1 404 Not Found') {
+ $faviconURL = "http://" . $parse['host'] . "/favicon.png";
+ return $faviconURL;
+ }
+
+ // Fallback to regex extraction
+ $faviconURL = extractFaviconUrlWithRegex($response);
+ if ($faviconURL) {
+ $faviconURL = getAbsoluteUrl($url, $faviconURL);
+ }
+ return $faviconURL;
}
+function getRedirectUrlFromHeaders($headers)
+{
+ if (preg_match('/^Location:\s+(.*)$/mi', $headers, $matches)) {
+ return trim($matches[1]);
+ }
+ return null;
+}
- $xpath = new DOMXPath($dom);
-
- $faviconUrl = '';
-
- // Search for tags with rel="icon" or rel="shortcut icon"
- $linkTags = $xpath->query("//link[contains(@rel, 'icon') or contains(@rel, 'shortcut icon')]");
- foreach ($linkTags as $tag) {
- $faviconUrl = $tag->getAttribute('href');
- if (strpos($faviconUrl, 'http') !== 0) {
- $faviconUrl = $url . '/' . ltrim($faviconUrl, '/');
- }
- break; // Stop after the first matching tag
+function extractFaviconUrlWithRegex($html)
+{
+ // Check for the historical rel="shortcut icon"
+ if (preg_match('/]+rel=["\']shortcut icon["\'][^>]+href=["\']([^"\']+)["\']/', $html, $matches)) {
+ $faviconURL = $matches[1];
+ return $faviconURL;
}
- $fallbackFavicon = 'assets/linkstack/icons/website.svg';
-
- if (empty($faviconUrl)) {
- $faviconUrl = $fallbackFavicon;
+ // Check for the HTML5 rel="icon"
+ if (preg_match('/]+rel=["\']icon["\'][^>]+href=["\']([^"\']+)["\']/', $html, $matches)) {
+ $faviconURL = $matches[1];
+ return $faviconURL;
}
- $extension = pathinfo($faviconUrl, PATHINFO_EXTENSION);
- $filename = $id . "." . $extension;
- $filepath = base_path("assets/favicon/icons") . "/" . $filename;
+ return null;
+}
+
+function getAbsoluteUrl($baseUrl, $relativeUrl)
+{
+ $parsedUrl = parse_url($baseUrl);
+ $scheme = isset($parsedUrl['scheme']) ? $parsedUrl['scheme'] : 'http';
+ $host = isset($parsedUrl['host']) ? $parsedUrl['host'] : '';
+ $path = isset($parsedUrl['path']) ? $parsedUrl['path'] : '';
+ $basePath = "$scheme://$host$path";
+
+ if (strpos($relativeUrl, 'http') === 0) {
+ return $relativeUrl; // Already an absolute URL
+ } elseif (strpos($relativeUrl, '/') === 0) {
+ return "$scheme://$host$relativeUrl"; // Root-relative URL
+ } else {
+ return "$basePath/$relativeUrl"; // Path-relative URL
+ }
+}
+
+function getFavIcon($id)
+{
+ try{
+
+ $link = Link::find($id);
+ $page = $link->link;
+
+ $url = getFaviconURL($page);
+
+ $fileExtension = pathinfo($url, PATHINFO_EXTENSION);
+ $filename = $id . '.' . $fileExtension;
+ $filepath = base_path('assets/favicon/icons') . '/' . $filename;
if (!file_exists($filepath)) {
- if ($faviconUrl !== $fallbackFavicon) {
- if (function_exists('curl_version')) {
- $curlHandle = curl_init($faviconUrl);
- curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($curlHandle, CURLOPT_TIMEOUT, 3);
- curl_setopt($curlHandle, CURLOPT_USERAGENT, $userAgent);
- $faviconData = curl_exec($curlHandle);
- curl_close($curlHandle);
+ if (function_exists('curl_version')) {
+ $curlHandle = curl_init($url);
+ curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curlHandle, CURLOPT_TIMEOUT, 3);
+ $faviconData = curl_exec($curlHandle);
+ curl_close($curlHandle);
- if ($faviconData !== false) {
- file_put_contents($filepath, $faviconData);
- }
- } else {
- file_put_contents($filepath, file_get_contents($faviconUrl, false, $context));
+ if ($faviconData !== false) {
+ file_put_contents($filepath, $faviconData);
}
} else {
- copy($fallbackFavicon, $filepath);
+ file_put_contents($filepath, file_get_contents($url));
}
}
- return $filename;
+ return url('assets/favicon/icons/' . $id . '.' . $fileExtension);
+
+ }catch(Exception $e){
+ // Handle the exception by copying the default SVG favicon
+ $defaultIcon = base_path('assets/linkstack/icons/website.svg');
+ $filename = $id . '.svg';
+ $filepath = base_path('assets/favicon/icons') . '/' . $filename;
+ copy($defaultIcon, $filepath);
+
+ return url('assets/favicon/icons/' . $filename);
+ }
}
?>
-