From ab06d1964c02fb8a74cfe4410c82cf2a04420bc3 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 13 Jun 2024 06:16:52 +0000 Subject: [PATCH] Reduce probing / handle exception for invalid url / always check for https --- src/Content/Text/BBCode.php | 7 ++++++- src/Model/Contact.php | 10 +++++++++- src/Network/Probe.php | 31 +++++++++++++++---------------- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index c9296179ce..82a020e245 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -2124,7 +2124,12 @@ class BBCode } $parts['host'] = idn_to_ascii(urldecode($parts['host'])); - return (string)Uri::fromParts($parts); + try { + return (string)Uri::fromParts($parts); + } catch (\Throwable $th) { + Logger::notice('Exception on unparsing url', ['url' => $url, 'parts' => $parts, 'code' => $th->getCode(), 'message' => $th->getMessage()]); + return $url; + } } private static function unifyLinks(string $text): string diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 5cd77048c9..490c61cf57 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -2653,6 +2653,14 @@ class Contact $data = Probe::uri($contact['url'], $network, $contact['uid']); + if (in_array($data['network'], Protocol::FEDERATED) && (parse_url($data['url'], PHP_URL_SCHEME) == 'http')) { + $ssl_url = str_replace('http://', 'https://', $contact['url']); + $ssl_data = Probe::uri($ssl_url, $network, $contact['uid']); + if (($ssl_data['network'] == $data['network']) && (parse_url($ssl_data['url'], PHP_URL_SCHEME) != 'http')) { + $data = $ssl_data; + } + } + if ($data['network'] == Protocol::DIASPORA) { try { DI::dsprContact()->updateFromProbeArray($data); @@ -2811,7 +2819,7 @@ class Contact // We must not try to update relay contacts via probe. They are no real contacts. // See Relay::updateContact() for more details. // We check after the probing to be able to correct falsely detected contact types. - if (($contact['contact-type'] == self::TYPE_RELAY) && Strings::compareLink($contact['url'], $contact['baseurl']) && + if (($contact['contact-type'] == self::TYPE_RELAY) && Strings::compareLink($contact['url'], $contact['baseurl'] ?? '') && (!Strings::compareLink($ret['url'], $contact['url']) || in_array($ret['network'], [Protocol::FEED, Protocol::PHANTOM])) ) { if (GServer::reachable($contact)) { diff --git a/src/Network/Probe.php b/src/Network/Probe.php index ec06680316..7c589745aa 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -244,7 +244,7 @@ class Probe return []; } - if (!is_object($xrd) && !empty($url)) { + if ($ssl_connection_error && !is_object($xrd) && !empty($url)) { $curlResult = DI::httpClient()->get($url, HttpClientAccept::XRD_XML, [HttpClientOptions::TIMEOUT => $xrd_timeout, HttpClientOptions::REQUEST => HttpClientRequest::CONTACTINFO]); $connection_error = ($curlResult->getErrorNumber() == CURLE_COULDNT_CONNECT) || ($curlResult->getReturnCode() == 0); if ($curlResult->isTimeout()) { @@ -568,7 +568,7 @@ class Probe } $webfinger = self::getWebfinger($parts['scheme'] . '://' . $host . self::WEBFINGER, HttpClientAccept::JRD_JSON, $uri, $addr); - if (empty($webfinger)) { + if (empty($webfinger) && !is_null($webfinger)) { $lrdd = self::hostMeta($host); } @@ -582,7 +582,7 @@ class Probe } $webfinger = self::getWebfinger($parts['scheme'] . '://' . $host . self::WEBFINGER, HttpClientAccept::JRD_JSON, $uri, $addr); - if (empty($webfinger)) { + if (empty($webfinger) && !is_null($webfinger)) { $lrdd = self::hostMeta($host); } } @@ -604,11 +604,12 @@ class Probe return []; } - if (empty($webfinger)) { + if (is_null($webfinger)) { $webfinger = self::getWebfinger('http://' . $host . self::WEBFINGER, HttpClientAccept::JRD_JSON, $uri, $addr); - if (self::$isTimeout) { + if (self::$isTimeout || is_null($webfinger)) { return []; } + $baseurl = 'http://' . $host; } else { $baseurl = 'https://' . $host; } @@ -619,8 +620,6 @@ class Probe return []; } $baseurl = self::$baseurl; - } else { - $baseurl = 'http://' . $host; } } else { Logger::info('URI was not detectable', ['uri' => $uri]); @@ -661,11 +660,11 @@ class Probe * * @return array webfinger results */ - private static function getWebfinger(string $template, string $type, string $uri, string $addr): array + private static function getWebfinger(string $template, string $type, string $uri, string $addr): ?array { if (Network::isUrlBlocked($template)) { Logger::info('Domain is blocked', ['url' => $template]); - return []; + return null; } // First try the address because this is the primary purpose of webfinger @@ -673,8 +672,8 @@ class Probe $detected = $addr; $path = str_replace('{uri}', urlencode('acct:' . $addr), $template); $webfinger = self::webfinger($path, $type); - if (self::$isTimeout) { - return []; + if (is_null($webfinger)) { + return null; } } @@ -683,8 +682,8 @@ class Probe $detected = $uri; $path = str_replace('{uri}', urlencode($uri), $template); $webfinger = self::webfinger($path, $type); - if (self::$isTimeout) { - return []; + if (is_null($webfinger)) { + return null; } } @@ -1001,7 +1000,7 @@ class Probe * @return array webfinger data * @throws HTTPException\InternalServerErrorException */ - private static function webfinger(string $url, string $type): array + private static function webfinger(string $url, string $type): ?array { try { $curlResult = DI::httpClient()->get( @@ -1011,12 +1010,12 @@ class Probe ); } catch (\Throwable $e) { Logger::notice($e->getMessage(), ['url' => $url, 'type' => $type, 'class' => get_class($e)]); - return []; + return null; } if ($curlResult->isTimeout()) { self::$isTimeout = true; - return []; + return null; } $data = $curlResult->getBodyString();