X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FNetwork%2FProbe.php;h=920dac47e6771911002a8fefc4f9546855cdc388;hb=a98957eeb29cfb142dfc4cd3e03c5bdfbc373466;hp=ff364d12a17935de455c1253c35251008ee6b19a;hpb=5cb3a5ff746a02ac6e864c120b734505985da983;p=friendica.git diff --git a/src/Network/Probe.php b/src/Network/Probe.php index ff364d12a1..920dac47e6 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -30,9 +30,9 @@ use Friendica\Core\Protocol; use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; -use Friendica\Model\Contact; use Friendica\Model\GServer; use Friendica\Model\Profile; +use Friendica\Model\User; use Friendica\Protocol\ActivityNamespace; use Friendica\Protocol\ActivityPub; use Friendica\Protocol\Email; @@ -47,6 +47,8 @@ use Friendica\Util\XML; */ class Probe { + const WEBFINGER = '/.well-known/webfinger?resource={uri}'; + private static $baseurl; private static $istimeout; @@ -175,7 +177,7 @@ class Probe $host_url = $host; } } elseif ($curlResult->isTimeout()) { - Logger::info('Probing timeout', ['url' => $ssl_url], Logger::DEBUG); + Logger::info('Probing timeout', ['url' => $ssl_url]); self::$istimeout = true; return []; } @@ -184,7 +186,7 @@ class Probe $curlResult = Network::curl($url, false, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']); $connection_error = ($curlResult->getErrorNumber() == CURLE_COULDNT_CONNECT) || ($curlResult->getReturnCode() == 0); if ($curlResult->isTimeout()) { - Logger::info('Probing timeout', ['url' => $url], Logger::DEBUG); + Logger::info('Probing timeout', ['url' => $url]); self::$istimeout = true; return []; } elseif ($connection_error && $ssl_connection_error) { @@ -197,17 +199,17 @@ class Probe $host_url = 'http://'.$host; } if (!is_object($xrd)) { - Logger::log("No xrd object found for ".$host, Logger::DEBUG); + Logger::info('No xrd object found', ['host' => $host]); return []; } $links = XML::elementToArray($xrd); if (!isset($links["xrd"]["link"])) { - Logger::log("No xrd data found for ".$host, Logger::DEBUG); + Logger::info('No xrd data found', ['host' => $host]); return []; } - $lrdd = ['application/jrd+json' => $host_url . '/.well-known/webfinger?resource={uri}']; + $lrdd = []; foreach ($links["xrd"]["link"] as $value => $link) { if (!empty($link["@attributes"])) { @@ -227,7 +229,7 @@ class Probe self::$baseurl = $host_url; - Logger::log("Probing successful for ".$host, Logger::DEBUG); + Logger::info('Probing successful', ['host' => $host]); return $lrdd; } @@ -258,7 +260,7 @@ class Probe $profile_link = ''; $links = self::lrdd($webbie); - Logger::log('webfingerDfrn: '.$webbie.':'.print_r($links, true), Logger::DATA); + Logger::debug('Result', ['url' => $webbie, 'links' => $links]); if (!empty($links) && is_array($links)) { foreach ($links as $link) { if ($link['@attributes']['rel'] === ActivityNamespace::DFRN) { @@ -285,68 +287,14 @@ class Probe */ public static function lrdd(string $uri) { - $lrdd = self::hostMeta($uri); - $webfinger = null; - - if (is_bool($lrdd)) { - return []; - } - - if (!$lrdd) { - $parts = @parse_url($uri); - if (!$parts || empty($parts["host"]) || empty($parts["path"])) { - return []; - } - - $host = $parts['scheme'] . '://' . $parts["host"]; - if (!empty($parts["port"])) { - $host .= ':'.$parts["port"]; - } - - $path_parts = explode("/", trim($parts["path"], "/")); - - $nick = array_pop($path_parts); - - do { - $lrdd = self::hostMeta($host); - $host .= "/".array_shift($path_parts); - } while (!$lrdd && (sizeof($path_parts) > 0)); - } - - if (!$lrdd) { - Logger::log("No lrdd data found for ".$uri, Logger::DEBUG); + $data = self::getWebfingerArray($uri); + if (empty($data)) { return []; } - - foreach ($lrdd as $type => $template) { - if ($webfinger) { - continue; - } - - $path = str_replace('{uri}', urlencode($uri), $template); - $webfinger = self::webfinger($path, $type); - - if (!$webfinger && (strstr($uri, "@"))) { - $path = str_replace('{uri}', urlencode("acct:".$uri), $template); - $webfinger = self::webfinger($path, $type); - } - - // Special treatment for Mastodon - // Problem is that Mastodon uses an URL format like http://domain.tld/@nick - // But the webfinger for this format fails. - if (!$webfinger && !empty($nick)) { - // Mastodon uses a "@" as prefix for usernames in their url format - $nick = ltrim($nick, '@'); - - $addr = $nick."@".$host; - - $path = str_replace('{uri}', urlencode("acct:".$addr), $template); - $webfinger = self::webfinger($path, $type); - } - } + $webfinger = $data['webfinger']; if (empty($webfinger["links"])) { - Logger::log("No webfinger links found for ".$uri, Logger::DEBUG); + Logger::info('No webfinger links found', ['uri' => $uri]); return []; } @@ -381,8 +329,9 @@ class Probe */ public static function uri($uri, $network = '', $uid = -1, $cache = true) { + $cachekey = 'Probe::uri:' . $network . ':' . $uri; if ($cache) { - $result = DI::cache()->get('Probe::uri:' . $network . ':' . $uri); + $result = DI::cache()->get($cachekey); if (!is_null($result)) { return $result; } @@ -392,19 +341,19 @@ class Probe $uid = local_user(); } - self::$istimeout = false; - - if ($network != Protocol::ACTIVITYPUB) { - $data = self::detect($uri, $network, $uid); + if (empty($network) || ($network == Protocol::ACTIVITYPUB)) { + $ap_profile = ActivityPub::probeProfile($uri); } else { - $data = null; + $ap_profile = []; } - // When the previous detection process had got a time out - // we could falsely detect a Friendica profile as AP profile. - if (!self::$istimeout) { - $ap_profile = ActivityPub::probeProfile($uri, !$cache); + self::$istimeout = false; + if ($network != Protocol::ACTIVITYPUB) { + $data = self::detect($uri, $network, $uid, $ap_profile); + if (!is_array($data)) { + $data = []; + } if (empty($data) || (!empty($ap_profile) && empty($network) && (($data['network'] ?? '') != Protocol::DFRN))) { $data = $ap_profile; } elseif (!empty($ap_profile)) { @@ -412,7 +361,7 @@ class Probe $data = array_merge($ap_profile, $data); } } else { - Logger::notice('Time out detected. AP will not be probed.', ['uri' => $uri]); + $data = $ap_profile; } if (!isset($data['url'])) { @@ -441,10 +390,6 @@ class Probe } } - if (!empty(self::$baseurl)) { - $data['baseurl'] = self::$baseurl; - } - if (!empty($data['baseurl']) && empty($data['gsid'])) { $data['gsid'] = GServer::getID($data['baseurl']); } @@ -466,7 +411,7 @@ class Probe // Only store into the cache if the value seems to be valid if (!in_array($data['network'], [Protocol::PHANTOM, Protocol::MAIL])) { - DI::cache()->set('Probe::uri:' . $network . ':' . $uri, $data, Duration::DAY); + DI::cache()->set($cachekey, $data, Duration::DAY); } return $data; @@ -537,69 +482,179 @@ class Probe } /** - * Checks if a profile url should be OStatus but only provides partial information - * - * @param array $webfinger Webfinger data - * @param string $lrdd Path template for webfinger request - * @param string $type type + * Fetch the "subscribe" and add it to the result * - * @return array fixed webfinger data - * @throws HTTPException\InternalServerErrorException + * @param array $result + * @param array $webfinger + * @return array result */ - private static function fixOStatus($webfinger, $lrdd, $type) + private static function getSubscribeLink(array $result, array $webfinger) { - if (empty($webfinger['links']) || empty($webfinger['subject'])) { - return $webfinger; + if (empty($webfinger['links'])) { + return $result; } - $is_ostatus = false; - $has_key = false; - foreach ($webfinger['links'] as $link) { - if ($link['rel'] == ActivityNamespace::OSTATUSSUB) { - $is_ostatus = true; + if (!empty($link['template']) && ($link['rel'] === ActivityNamespace::OSTATUSSUB)) { + $result['subscribe'] = $link['template']; + } + } + + return $result; + } + + /** + * Get webfinger data from a given URI + * + * @param string $uri + * @return array Webfinger array + */ + private static function getWebfingerArray(string $uri) + { + $parts = parse_url($uri); + + if (!empty($parts['scheme']) && !empty($parts['host'])) { + $host = $parts['host']; + if (!empty($parts['port'])) { + $host .= ':'.$parts['port']; + } + + $baseurl = $parts['scheme'] . '://' . $host; + + $nick = ''; + $addr = ''; + + $path_parts = explode("/", trim($parts['path'] ?? '', "/")); + if (!empty($path_parts)) { + $nick = ltrim(end($path_parts), '@'); + // When the last part of the URI is numeric then it is most likely an ID and not a nick name + if (!is_numeric($nick)) { + $addr = $nick."@".$host; + } else { + $nick = ''; + } + } + + $webfinger = self::getWebfinger($parts['scheme'] . '://' . $host . self::WEBFINGER, 'application/jrd+json', $uri, $addr); + if (empty($webfinger)) { + $lrdd = self::hostMeta($host); } - if ($link['rel'] == 'magic-public-key') { - $has_key = true; + + if (empty($webfinger) && empty($lrdd)) { + while (empty($lrdd) && empty($webfinger) && (sizeof($path_parts) > 1)) { + $host .= "/".array_shift($path_parts); + $baseurl = $parts['scheme'] . '://' . $host; + + if (!empty($nick)) { + $addr = $nick."@".$host; + } + + $webfinger = self::getWebfinger($parts['scheme'] . '://' . $host . self::WEBFINGER, 'application/jrd+json', $uri, $addr); + if (empty($webfinger)) { + $lrdd = self::hostMeta($host); + } + } + + if (empty($lrdd) && empty($webfinger)) { + return []; + } + } + } elseif (strstr($uri, '@')) { + // Remove "acct:" from the URI + $uri = str_replace('acct:', '', $uri); + + $host = substr($uri, strpos($uri, '@') + 1); + $nick = substr($uri, 0, strpos($uri, '@')); + $addr = $uri; + + $webfinger = self::getWebfinger('https://' . $host . self::WEBFINGER, 'application/jrd+json', $uri, $addr); + if (self::$istimeout) { + return []; + } + + if (empty($webfinger)) { + $webfinger = self::getWebfinger('http://' . $host . self::WEBFINGER, 'application/jrd+json', $uri, $addr); + if (self::$istimeout) { + return []; + } + } else { + $baseurl = 'https://' . $host; + } + + if (empty($webfinger)) { + $lrdd = self::hostMeta($host); + if (self::$istimeout) { + return []; + } + $baseurl = self::$baseurl; + } else { + $baseurl = 'http://' . $host; } + } else { + Logger::info('URI was not detectable', ['uri' => $uri]); + return []; } - if (!$is_ostatus || $has_key) { - return $webfinger; + if (empty($webfinger)) { + foreach ($lrdd as $type => $template) { + if ($webfinger) { + continue; + } + + $webfinger = self::getWebfinger($template, $type, $uri, $addr); + } } - $url = Network::switchScheme($webfinger['subject']); - $path = str_replace('{uri}', urlencode($url), $lrdd); - $webfinger2 = self::webfinger($path, $type); + if (empty($webfinger)) { + return []; + } - // Is the new webfinger detectable as OStatus? - if (self::ostatus($webfinger2, true)) { - $webfinger = $webfinger2; + if ($webfinger['detected'] == $addr) { + $webfinger['nick'] = $nick; + $webfinger['addr'] = $addr; } + $webfinger['baseurl'] = $baseurl; + return $webfinger; } /** - * Fetch the "subscribe" and add it to the result + * Perform network request for webfinger data * - * @param array $result - * @param array $webfinger - * @return array result + * @param string $template + * @param string $type + * @param string $uri + * @param string $addr + * @return array webfinger results */ - private static function getSubscribeLink(array $result, array $webfinger) + private static function getWebfinger(string $template, string $type, string $uri, string $addr) { - if (empty($webfinger['links'])) { - return $result; + // First try the address because this is the primary purpose of webfinger + if (!empty($addr)) { + $detected = $addr; + $path = str_replace('{uri}', urlencode("acct:" . $addr), $template); + $webfinger = self::webfinger($path, $type); + if (self::$istimeout) { + return []; + } } - foreach ($webfinger['links'] as $link) { - if ($link['rel'] === ActivityNamespace::OSTATUSSUB) { - $result['subscribe'] = $link['template']; + // Then try the URI + if (empty($webfinger) && $uri != $addr) { + $detected = $uri; + $path = str_replace('{uri}', urlencode($uri), $template); + $webfinger = self::webfinger($path, $type); + if (self::$istimeout) { + return []; } } - return $result; + if (empty($webfinger)) { + return []; + } + + return ['webfinger' => $webfinger, 'detected' => $detected]; } /** @@ -607,17 +662,16 @@ class Probe * * This function is only called by the "uri" function that adds caching and rearranging of data. * - * @param string $uri Address that should be probed - * @param string $network Test for this specific network - * @param integer $uid User ID for the probe (only used for mails) + * @param string $uri Address that should be probed + * @param string $network Test for this specific network + * @param integer $uid User ID for the probe (only used for mails) + * @param array $ap_profile Previously probed AP profile * * @return array uri data * @throws HTTPException\InternalServerErrorException */ - private static function detect($uri, $network, $uid) + private static function detect(string $uri, string $network, int $uid, array $ap_profile) { - $parts = parse_url($uri); - $hookData = [ 'uri' => $uri, 'network' => $network, @@ -628,40 +682,19 @@ class Probe Hook::callAll('probe_detect', $hookData); if ($hookData['result']) { - return $hookData['result']; - } - - if (!empty($parts["scheme"]) && !empty($parts["host"])) { - $host = $parts["host"]; - if (!empty($parts["port"])) { - $host .= ':'.$parts["port"]; - } - - if ($host == 'twitter.com') { - return self::twitter($uri); - } - $lrdd = self::hostMeta($host); - - if (is_bool($lrdd)) { + if (!is_array($hookData['result'])) { return []; + } else { + return $hookData['result']; } + } - $path_parts = explode("/", trim($parts['path'] ?? '', "/")); + $parts = parse_url($uri); - while (!$lrdd && (sizeof($path_parts) > 1)) { - $host .= "/".array_shift($path_parts); - $lrdd = self::hostMeta($host); - } - if (!$lrdd) { - Logger::log('No XRD data was found for '.$uri, Logger::DEBUG); - return self::feed($uri); + if (!empty($parts['scheme']) && !empty($parts['host'])) { + if (in_array($parts['host'], ['twitter.com', 'mobile.twitter.com'])) { + return self::twitter($uri); } - $nick = array_pop($path_parts); - - // Mastodon uses a "@" as prefix for usernames in their url format - $nick = ltrim($nick, '@'); - - $addr = $nick."@".$host; } elseif (strstr($uri, '@')) { // If the URI starts with "mailto:" then jump directly to the mail detection if (strpos($uri, 'mailto:') !== false) { @@ -672,74 +705,37 @@ class Probe if ($network == Protocol::MAIL) { return self::mail($uri, $uid); } - // Remove "acct:" from the URI - $uri = str_replace('acct:', '', $uri); - - $host = substr($uri, strpos($uri, '@') + 1); - $nick = substr($uri, 0, strpos($uri, '@')); - if (strpos($uri, '@twitter.com')) { + if (Strings::endsWith($uri, '@twitter.com') + || Strings::endsWith($uri, '@mobile.twitter.com') + ) { return self::twitter($uri); } - $lrdd = self::hostMeta($host); - - if (is_bool($lrdd)) { - return []; - } - - if (!$lrdd) { - Logger::log('No XRD data was found for '.$uri, Logger::DEBUG); - return self::mail($uri, $uid); - } - $addr = $uri; } else { - Logger::log("Uri ".$uri." was not detectable", Logger::DEBUG); + Logger::info('URI was not detectable', ['uri' => $uri]); return []; } - $webfinger = false; - - /// @todo Do we need the prefix "acct:" or "acct://"? - - foreach ($lrdd as $type => $template) { - if ($webfinger) { - continue; - } - - // At first try it with the given uri - $path = str_replace('{uri}', urlencode($uri), $template); - $webfinger = self::webfinger($path, $type); - - // Fix possible problems with GNU Social probing to wrong scheme - $webfinger = self::fixOStatus($webfinger, $template, $type); - - // We cannot be sure that the detected address was correct, so we don't use the values - if ($webfinger && ($uri != $addr)) { - $nick = ""; - $addr = ""; - } - - // Try webfinger with the address (user@domain.tld) - if (!$webfinger) { - $path = str_replace('{uri}', urlencode($addr), $template); - $webfinger = self::webfinger($path, $type); - } + Logger::info('Probing start', ['uri' => $uri]); - // Mastodon needs to have it with "acct:" - if (!$webfinger) { - $path = str_replace('{uri}', urlencode("acct:".$addr), $template); - $webfinger = self::webfinger($path, $type); + $data = self::getWebfingerArray($uri); + if (empty($data)) { + if (!empty($parts['scheme'])) { + return self::feed($uri); + } elseif (!empty($uid)) { + return self::mail($uri, $uid); + } else { + return []; } } - if (!$webfinger) { - return self::feed($uri); - } + $webfinger = $data['webfinger']; + $nick = $data['nick'] ?? ''; + $addr = $data['addr'] ?? ''; + $baseurl = $data['baseurl'] ?? ''; $result = []; - Logger::info("Probing", ['uri' => $uri]); - if (in_array($network, ["", Protocol::DFRN])) { $result = self::dfrn($webfinger); } @@ -750,12 +746,12 @@ class Probe $result = self::ostatus($webfinger); } if (in_array($network, ['', Protocol::ZOT])) { - $result = self::zot($webfinger, $result); + $result = self::zot($webfinger, $result, $baseurl); } if ((!$result && ($network == "")) || ($network == Protocol::PUMPIO)) { $result = self::pumpio($webfinger, $addr); } - if ((!$result && ($network == "")) || ($network == Protocol::FEED)) { + if (empty($result['network']) && empty($ap_profile['network']) || ($network == Protocol::FEED)) { $result = self::feed($uri); } else { // We overwrite the detected nick with our try if the previois routines hadn't detected it. @@ -775,18 +771,15 @@ class Probe $result["network"] = Protocol::PHANTOM; } + if (empty($result['baseurl']) && !empty($baseurl)) { + $result['baseurl'] = $baseurl; + } + if (empty($result["url"])) { $result["url"] = $uri; } - Logger::log($uri." is ".$result["network"], Logger::DEBUG); - - if (empty($result["baseurl"]) && ($result["network"] != Protocol::PHANTOM)) { - $pos = strpos($result["url"], $host); - if ($pos) { - $result["baseurl"] = substr($result["url"], 0, $pos).$host; - } - } + Logger::info('Probing done', ['uri' => $uri, 'network' => $result["network"]]); return $result; } @@ -800,7 +793,7 @@ class Probe * @return array Zot data * @throws HTTPException\InternalServerErrorException */ - private static function zot($webfinger, $data) + private static function zot($webfinger, $data, $baseurl) { if (!empty($webfinger["aliases"]) && is_array($webfinger["aliases"])) { foreach ($webfinger["aliases"] as $alias) { @@ -821,12 +814,12 @@ class Probe } } - if (empty($zot_url) && !empty($data['addr']) && !empty(self::$baseurl)) { - $condition = ['nurl' => Strings::normaliseLink(self::$baseurl), 'platform' => ['hubzilla']]; + if (empty($zot_url) && !empty($data['addr']) && !empty($baseurl)) { + $condition = ['nurl' => Strings::normaliseLink($baseurl), 'platform' => ['hubzilla']]; if (!DBA::exists('gserver', $condition)) { return $data; } - $zot_url = self::$baseurl . '/.well-known/zot-info?address=' . $data['addr']; + $zot_url = $baseurl . '/.well-known/zot-info?address=' . $data['addr']; } if (empty($zot_url)) { @@ -899,7 +892,7 @@ class Probe } if (!empty($json['public_forum'])) { $data['community'] = $json['public_forum']; - $data['account-type'] = Contact::PAGE_COMMUNITY; + $data['account-type'] = User::PAGE_FLAGS_COMMUNITY; } if (!empty($json['profile'])) { @@ -955,7 +948,7 @@ class Probe $webfinger = json_decode($data, true); if (!empty($webfinger)) { if (!isset($webfinger["links"])) { - Logger::log("No json webfinger links for ".$url, Logger::DEBUG); + Logger::info('No json webfinger links', ['url' => $url]); return []; } return $webfinger; @@ -964,13 +957,13 @@ class Probe // If it is not JSON, maybe it is XML $xrd = XML::parseString($data, true); if (!is_object($xrd)) { - Logger::log("No webfinger data retrievable for ".$url, Logger::DEBUG); + Logger::info('No webfinger data retrievable', ['url' => $url]); return []; } $xrd_arr = XML::elementToArray($xrd); if (!isset($xrd_arr["xrd"]["link"])) { - Logger::log("No XML webfinger links for ".$url, Logger::DEBUG); + Logger::info('No XML webfinger links', ['url' => $url]); return []; } @@ -1021,13 +1014,13 @@ class Probe } $content = $curlResult->getBody(); if (!$content) { - Logger::log("Empty body for ".$noscrape_url, Logger::DEBUG); + Logger::info('Empty body', ['url' => $noscrape_url]); return []; } $json = json_decode($content, true); if (!is_array($json)) { - Logger::log("No json data for ".$noscrape_url, Logger::DEBUG); + Logger::info('No json data', ['url' => $noscrape_url]); return []; } @@ -1141,7 +1134,7 @@ class Probe { $data = []; - Logger::log("Check profile ".$profile_link, Logger::DEBUG); + Logger::info('Check profile', ['link' => $profile_link]); // Fetch data via noscrape - this is faster $noscrape_url = str_replace(["/hcard/", "/profile/"], "/noscrape/", $profile_link); @@ -1175,7 +1168,7 @@ class Probe $prof_data["fn"] = $data['name'] ?? null; $prof_data["key"] = $data['pubkey'] ?? null; - Logger::log("Result for profile ".$profile_link.": ".print_r($prof_data, true), Logger::DEBUG); + Logger::debug('Result', ['link' => $profile_link, 'data' => $prof_data]); return $prof_data; } @@ -1511,7 +1504,7 @@ class Probe && (($link["type"] ?? "") == "text/html") && ($link["href"] != "") ) { - $data["url"] = $link["href"]; + $data["url"] = $data["alias"] = $link["href"]; } elseif (($link["rel"] == "salmon") && !empty($link["href"])) { $data["notify"] = $link["href"]; } elseif (($link["rel"] == ActivityNamespace::FEED) && !empty($link["href"])) { @@ -1594,8 +1587,7 @@ class Probe $data["url"] = $feed_data["header"]["author-link"]; } - if (($data['poll'] == $data['url']) && ($data["alias"] != '')) { - $data['url'] = $data["alias"]; + if ($data["url"] == $data["alias"]) { $data["alias"] = ''; } @@ -1730,9 +1722,9 @@ class Probe */ private static function twitter($uri) { - if (preg_match('=(.*)@twitter.com=i', $uri, $matches)) { + if (preg_match('=([^@]+)@(?:mobile\.)?twitter\.com$=i', $uri, $matches)) { $nick = $matches[1]; - } elseif (preg_match('=https?://twitter.com/(.*)=i', $uri, $matches)) { + } elseif (preg_match('=^https?://(?:mobile\.)?twitter\.com/(.+)=i', $uri, $matches)) { $nick = $matches[1]; } else { return []; @@ -1884,12 +1876,6 @@ class Probe $data["url"] = $url; $data["poll"] = $url; - if (!empty($feed_data["header"]["author-link"])) { - $data["baseurl"] = $feed_data["header"]["author-link"]; - } else { - $data["baseurl"] = $data["url"]; - } - $data["network"] = Protocol::FEED; return $data; @@ -1933,7 +1919,7 @@ class Probe } $msgs = Email::poll($mbox, $uri); - Logger::log('searching '.$uri.', '.count($msgs).' messages found.', Logger::DEBUG); + Logger::info('Messages found', ['uri' => $uri, 'count' => count($msgs)]); if (!count($msgs)) { return []; @@ -2016,7 +2002,7 @@ class Probe $fixed = $scheme.$host.$port.$path.$query.$fragment; - Logger::log('Base: '.$base.' - Avatar: '.$avatar.' - Fixed: '.$fixed, Logger::DATA); + Logger::debug('Avatar fixed', ['base' => $base, 'avatar' => $avatar, 'fixed' => $fixed]); return $fixed; }