X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;ds=sidebyside;f=src%2FNetwork%2FProbe.php;h=23c115eaba2035e1e405690de128a6926f07ae36;hb=7cdd2d1336e768def2f9b2dc1d4026f8d9bb3804;hp=67db29a4f3536fe9b0e98332de9578ac55db8b8a;hpb=bfbf8816e2ce72f85c541328b5a043effe2a4e70;p=friendica.git diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 67db29a4f3..23c115eaba 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -1,6 +1,6 @@ $host, 'ssl_url' => $ssl_url, 'url' => $url, 'callstack' => System::callstack(20)]); $xrd = null; - $curlResult = DI::httpRequest()->get($ssl_url, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']); + $curlResult = DI::httpClient()->get($ssl_url, [HTTPClientOptions::TIMEOUT => $xrd_timeout, HTTPClientOptions::ACCEPT_CONTENT => ['application/xrd+xml']]); $ssl_connection_error = ($curlResult->getErrorNumber() == CURLE_COULDNT_CONNECT) || ($curlResult->getReturnCode() == 0); if ($curlResult->isSuccess()) { $xml = $curlResult->getBody(); @@ -186,7 +187,7 @@ class Probe } if (!is_object($xrd) && !empty($url)) { - $curlResult = DI::httpRequest()->get($url, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']); + $curlResult = DI::httpClient()->get($url, [HTTPClientOptions::TIMEOUT => $xrd_timeout, HTTPClientOptions::ACCEPT_CONTENT => ['application/xrd+xml']]); $connection_error = ($curlResult->getErrorNumber() == CURLE_COULDNT_CONNECT) || ($curlResult->getReturnCode() == 0); if ($curlResult->isTimeout()) { Logger::info('Probing timeout', ['url' => $url]); @@ -230,6 +231,11 @@ class Probe } } + if (Network::isUrlBlocked($host_url)) { + Logger::info('Domain is blocked', ['url' => $host]); + return []; + } + self::$baseurl = $host_url; Logger::info('Probing successful', ['host' => $host]); @@ -258,7 +264,7 @@ class Probe * @return string profile link * @throws HTTPException\InternalServerErrorException */ - public static function webfingerDfrn($webbie, &$hcard_url) + public static function webfingerDfrn(string $webbie, string &$hcard_url) { $profile_link = ''; @@ -333,7 +339,7 @@ class Probe public static function uri($uri, $network = '', $uid = -1) { // Local profiles aren't probed via network - if (empty($network) && strpos($uri, DI::baseUrl()->getHostname())) { + if (empty($network) && Contact::isLocal($uri)) { $data = self::localProbe($uri); if (!empty($data)) { return $data; @@ -423,22 +429,20 @@ class Probe */ private static function getHideStatus($url) { - $curlResult = DI::httpRequest()->get($url); + $curlResult = DI::httpClient()->get($url, [HTTPClientOptions::CONTENT_LENGTH => 1000000]); if (!$curlResult->isSuccess()) { return false; } - // If the file is too large then exit - if (($curlResult->getInfo()['download_content_length'] ?? 0) > 1000000) { - return false; - } - // If it isn't a HTML file then exit if (($curlResult->getContentType() != '') && !strstr(strtolower($curlResult->getContentType()), 'html')) { return false; } $body = $curlResult->getBody(); + if (empty($body)) { + return false; + } $doc = new DOMDocument(); @$doc->loadHTML($body); @@ -626,6 +630,11 @@ class Probe */ private static function getWebfinger(string $template, string $type, string $uri, string $addr) { + if (Network::isUrlBlocked($template)) { + Logger::info('Domain is blocked', ['url' => $template]); + return []; + } + // First try the address because this is the primary purpose of webfinger if (!empty($addr)) { $detected = $addr; @@ -844,7 +853,7 @@ class Probe public static function pollZot($url, $data) { - $curlResult = DI::httpRequest()->get($url); + $curlResult = DI::httpClient()->get($url); if ($curlResult->isTimeout()) { return $data; } @@ -941,7 +950,7 @@ class Probe { $xrd_timeout = DI::config()->get('system', 'xrd_timeout', 20); - $curlResult = DI::httpRequest()->get($url, ['timeout' => $xrd_timeout, 'accept_content' => $type]); + $curlResult = DI::httpClient()->get($url, [HTTPClientOptions::TIMEOUT => $xrd_timeout, HTTPClientOptions::ACCEPT_CONTENT => [$type]]); if ($curlResult->isTimeout()) { self::$istimeout = true; return []; @@ -1010,21 +1019,21 @@ class Probe */ private static function pollNoscrape($noscrape_url, $data) { - $curlResult = DI::httpRequest()->get($noscrape_url); + $curlResult = DI::httpClient()->get($noscrape_url); if ($curlResult->isTimeout()) { self::$istimeout = true; - return []; + return $data; } $content = $curlResult->getBody(); if (!$content) { Logger::info('Empty body', ['url' => $noscrape_url]); - return []; + return $data; } $json = json_decode($content, true); if (!is_array($json)) { Logger::info('No json data', ['url' => $noscrape_url]); - return []; + return $data; } if (!empty($json["fn"])) { @@ -1063,6 +1072,14 @@ class Probe $data["about"] = $json["about"]; } + if (!empty($json["xmpp"])) { + $data["xmpp"] = $json["xmpp"]; + } + + if (!empty($json["matrix"])) { + $data["matrix"] = $json["matrix"]; + } + if (!empty($json["key"])) { $data["pubkey"] = $json["key"]; } @@ -1268,13 +1285,13 @@ class Probe */ private static function pollHcard($hcard_url, $data, $dfrn = false) { - $curlResult = DI::httpRequest()->get($hcard_url); + $curlResult = DI::httpClient()->get($hcard_url); if ($curlResult->isTimeout()) { self::$istimeout = true; return []; } $content = $curlResult->getBody(); - if (!$content) { + if (empty($content)) { return []; } @@ -1408,6 +1425,8 @@ class Probe $data["guid"] = $link["href"]; } elseif (($link["rel"] == "http://webfinger.net/rel/profile-page") && (($link["type"] ?? "") == "text/html") && !empty($link["href"])) { $data["url"] = $link["href"]; + } elseif (($link["rel"] == "http://webfinger.net/rel/profile-page") && empty($link["type"]) && !empty($link["href"])) { + $profile_url = $link["href"]; } elseif (($link["rel"] == ActivityNamespace::FEED) && !empty($link["href"])) { $data["poll"] = $link["href"]; } elseif (($link["rel"] == ActivityNamespace::POCO) && !empty($link["href"])) { @@ -1424,6 +1443,10 @@ class Probe } } + if (empty($data["url"]) && !empty($profile_url)) { + $data["url"] = $profile_url; + } + if (empty($data["url"]) || empty($hcard_url)) { return []; } @@ -1523,7 +1546,7 @@ class Probe $pubkey = substr($pubkey, 5); } } elseif (Strings::normaliseLink($pubkey) == 'http://') { - $curlResult = DI::httpRequest()->get($pubkey); + $curlResult = DI::httpClient()->get($pubkey); if ($curlResult->isTimeout()) { self::$istimeout = true; return $short ? false : []; @@ -1557,7 +1580,7 @@ class Probe } // Fetch all additional data from the feed - $curlResult = DI::httpRequest()->get($data["poll"]); + $curlResult = DI::httpClient()->get($data["poll"]); if ($curlResult->isTimeout()) { self::$istimeout = true; return []; @@ -1609,8 +1632,8 @@ class Probe */ private static function pumpioProfileData($profile_link) { - $curlResult = DI::httpRequest()->get($profile_link); - if (!$curlResult->isSuccess()) { + $curlResult = DI::httpClient()->get($profile_link); + if (!$curlResult->isSuccess() || empty($curlResult->getBody())) { return []; } @@ -1754,6 +1777,10 @@ class Probe */ public static function getFeedLink(string $url, string $body) { + if (empty($body)) { + return ''; + } + $doc = new DOMDocument(); if (!@$doc->loadHTML($body)) { return false; @@ -1801,26 +1828,28 @@ class Probe $hrefParts = parse_url($href); - // Root path case (/path) including relative scheme case (//host/path) - if ($hrefParts['path'] && $hrefParts['path'][0] == '/') { - $path = $hrefParts['path']; - } else { - $path = $path . '/' . $hrefParts['path']; - - // Resolve arbitrary relative path - // Lifted from https://www.php.net/manual/en/function.realpath.php#84012 - $parts = array_filter(explode('/', $path), 'strlen'); - $absolutes = array(); - foreach ($parts as $part) { - if ('.' == $part) continue; - if ('..' == $part) { - array_pop($absolutes); - } else { - $absolutes[] = $part; + if (!empty($hrefParts['path'])) { + // Root path case (/path) including relative scheme case (//host/path) + if ($hrefParts['path'] && $hrefParts['path'][0] == '/') { + $path = $hrefParts['path']; + } else { + $path = $path . '/' . $hrefParts['path']; + + // Resolve arbitrary relative path + // Lifted from https://www.php.net/manual/en/function.realpath.php#84012 + $parts = array_filter(explode('/', $path), 'strlen'); + $absolutes = array(); + foreach ($parts as $part) { + if ('.' == $part) continue; + if ('..' == $part) { + array_pop($absolutes); + } else { + $absolutes[] = $part; + } } - } - $path = '/' . implode('/', $absolutes); + $path = '/' . implode('/', $absolutes); + } } // Relative scheme case (//host/path) @@ -1843,7 +1872,7 @@ class Probe */ private static function feed($url, $probe = true) { - $curlResult = DI::httpRequest()->get($url); + $curlResult = DI::httpClient()->get($url); if ($curlResult->isTimeout()) { self::$istimeout = true; return []; @@ -2067,7 +2096,7 @@ class Probe return ''; } - $curlResult = DI::httpRequest()->get($gserver['noscrape'] . '/' . $data['nick']); + $curlResult = DI::httpClient()->get($gserver['noscrape'] . '/' . $data['nick']); if ($curlResult->isSuccess() && !empty($curlResult->getBody())) { $noscrape = json_decode($curlResult->getBody(), true); @@ -2142,8 +2171,8 @@ class Probe private static function updateFromFeed(array $data) { // Search for the newest entry in the feed - $curlResult = DI::httpRequest()->get($data['poll']); - if (!$curlResult->isSuccess()) { + $curlResult = DI::httpClient()->get($data['poll']); + if (!$curlResult->isSuccess() || !$curlResult->getBody()) { return ''; } @@ -2189,41 +2218,49 @@ class Probe * * @param string $url * @return array probed data + * @throws HTTPException\InternalServerErrorException + * @throws HTTPException\NotFoundException */ - private static function localProbe(string $url) + private static function localProbe(string $url): array { - $uid = User::getIdForURL($url); - if (empty($uid)) { - return []; + try { + $uid = User::getIdForURL($url); + if (!$uid) { + throw new HTTPException\NotFoundException('User not found.'); + } + + $owner = User::getOwnerDataById($uid); + $approfile = ActivityPub\Transmitter::getProfile($uid); + + if (empty($owner['gsid'])) { + $owner['gsid'] = GServer::getID($approfile['generator']['url']); + } + + $data = [ + 'name' => $owner['name'], 'nick' => $owner['nick'], 'guid' => $approfile['diaspora:guid'] ?? '', + 'url' => $owner['url'], 'addr' => $owner['addr'], 'alias' => $owner['alias'], + 'photo' => User::getAvatarUrl($owner), + 'header' => $owner['header'] ? Contact::getHeaderUrlForId($owner['id'], $owner['updated']) : '', + 'account-type' => $owner['contact-type'], 'community' => ($owner['contact-type'] == User::ACCOUNT_TYPE_COMMUNITY), + 'keywords' => $owner['keywords'], 'location' => $owner['location'], 'about' => $owner['about'], + 'xmpp' => $owner['xmpp'], 'matrix' => $owner['matrix'], + 'hide' => !$owner['net-publish'], 'batch' => '', 'notify' => $owner['notify'], + 'poll' => $owner['poll'], 'request' => $owner['request'], 'confirm' => $owner['confirm'], + 'subscribe' => $approfile['generator']['url'] . '/follow?url={uri}', 'poco' => $owner['poco'], + 'following' => $approfile['following'], 'followers' => $approfile['followers'], + 'inbox' => $approfile['inbox'], 'outbox' => $approfile['outbox'], + 'sharedinbox' => $approfile['endpoints']['sharedInbox'], 'network' => Protocol::DFRN, + 'pubkey' => $owner['upubkey'], 'baseurl' => $approfile['generator']['url'], 'gsid' => $owner['gsid'], + 'manually-approve' => in_array($owner['page-flags'], [User::PAGE_FLAGS_NORMAL, User::PAGE_FLAGS_PRVGROUP]) + ]; + } catch (Exception $e) { + // Default values for non existing targets + $data = [ + 'name' => $url, 'nick' => $url, 'url' => $url, 'network' => Protocol::PHANTOM, + 'photo' => DI::baseUrl() . Contact::DEFAULT_AVATAR_PHOTO + ]; } - $profile = User::getOwnerDataById($uid); - if (empty($profile)) { - return []; - } - - $approfile = ActivityPub\Transmitter::getProfile($uid); - if (empty($approfile)) { - return []; - } - - if (empty($profile['gsid'])) { - $profile['gsid'] = GServer::getID($approfile['generator']['url']); - } - - $data = ['name' => $profile['name'], 'nick' => $profile['nick'], 'guid' => $approfile['diaspora:guid'] ?? '', - 'url' => $profile['url'], 'addr' => $profile['addr'], 'alias' => $profile['alias'], - 'photo' => $profile['photo'], 'account-type' => $profile['contact-type'], - 'community' => ($profile['contact-type'] == User::ACCOUNT_TYPE_COMMUNITY), - 'keywords' => $profile['keywords'], 'location' => $profile['location'], 'about' => $profile['about'], - 'hide' => !$profile['net-publish'], 'batch' => '', 'notify' => $profile['notify'], - 'poll' => $profile['poll'], 'request' => $profile['request'], 'confirm' => $profile['confirm'], - 'subscribe' => $approfile['generator']['url'] . '/follow?url={uri}', 'poco' => $profile['poco'], - 'following' => $approfile['following'], 'followers' => $approfile['followers'], - 'inbox' => $approfile['inbox'], 'outbox' => $approfile['outbox'], - 'sharedinbox' => $approfile['endpoints']['sharedInbox'], 'network' => Protocol::DFRN, - 'pubkey' => $profile['upubkey'], 'baseurl' => $approfile['generator']['url'], 'gsid' => $profile['gsid'], - 'manually-approve' => in_array($profile['page-flags'], [User::PAGE_FLAGS_NORMAL, User::PAGE_FLAGS_PRVGROUP])]; - return self::rearrangeData($data); + return self::rearrangeData($data); } }