X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FNetwork%2FProbe.php;h=48530ffeae1377f8f233eb1bfe44ff99d0fbe2f6;hb=af6dbc654f82225cfc647fe2072662acae388e47;hp=569e57381e5e9bb96af186b4ab7fc8fc4c3e1848;hpb=f28301e18fb4524708dc0ecc2c468aaa343dc9af;p=friendica.git diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 569e57381e..48530ffeae 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -9,21 +9,20 @@ namespace Friendica\Network; * @brief Functions for probing URL */ -use Friendica\App; -use Friendica\Core\System; +use DOMDocument; use Friendica\Core\Cache; use Friendica\Core\Config; +use Friendica\Core\System; +use Friendica\Database\DBA; use Friendica\Database\DBM; use Friendica\Model\Profile; use Friendica\Protocol\Email; use Friendica\Protocol\Feed; use Friendica\Util\Crypto; +use Friendica\Util\DateTimeFormat; use Friendica\Util\Network; use Friendica\Util\XML; - -use dba; -use DOMXPath; -use DOMDocument; +use DomXPath; require_once 'include/dba.php'; @@ -109,6 +108,7 @@ class Probe $redirects = 0; logger("Probing for ".$host, LOGGER_DEBUG); + $xrd = null; $ret = Network::curl($ssl_url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']); if ($ret['success']) { @@ -119,7 +119,7 @@ class Probe if (!is_object($xrd)) { $ret = Network::curl($url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']); - if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { + if (!$ret["success"] && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) { logger("Probing timeout for ".$url, LOGGER_DEBUG); return false; } @@ -334,7 +334,7 @@ class Probe } if (x($data, "photo")) { - $data["baseurl"] = Network::getUrlMatch(normalise_link($data["baseurl"]), normalise_link($data["photo"])); + $data["baseurl"] = Network::getUrlMatch(normalise_link(defaults($data, "baseurl", "")), normalise_link($data["photo"])); } else { $data["photo"] = System::baseUrl().'/images/person-175.jpg'; } @@ -357,11 +357,11 @@ class Probe } } - if (self::$baseurl != "") { + if (!empty(self::$baseurl)) { $data["baseurl"] = self::$baseurl; } - if (!isset($data["network"])) { + if (empty($data["network"])) { $data["network"] = NETWORK_PHANTOM; } @@ -395,6 +395,12 @@ class Probe 'network' => $data['network'], 'server_url' => $data['baseurl']]; + // This doesn't cover the case when a community isn't a community anymore + if (!empty($data['community']) && $data['community']) { + $fields['community'] = $data['community']; + $fields['contact-type'] = ACCOUNT_TYPE_COMMUNITY; + } + $fieldnames = []; foreach ($fields as $key => $val) { @@ -409,9 +415,20 @@ class Probe $condition = ['nurl' => normalise_link($data["url"])]; - $old_fields = dba::selectFirst('gcontact', $fieldnames, $condition); + $old_fields = DBA::selectFirst('gcontact', $fieldnames, $condition); + + // When the gcontact doesn't exist, the value "true" will trigger an insert. + // In difference to the public contacts we want to have every contact + // in the world in our global contacts. + if (!$old_fields) { + $old_fields = true; + + // These values have to be set only on insert + $fields['photo'] = $data['photo']; + $fields['created'] = DateTimeFormat::utcNow(); + } - dba::update('gcontact', $fields, $condition, $old_fields); + DBA::update('gcontact', $fields, $condition, $old_fields); $fields = ['name' => $data['name'], 'nick' => $data['nick'], @@ -428,7 +445,10 @@ class Probe 'confirm' => $data['confirm'], 'poco' => $data['poco'], 'network' => $data['network'], - 'success_update' => DBM::date()]; + 'pubkey' => $data['pubkey'], + 'priority' => $data['priority'], + 'writable' => true, + 'rel' => CONTACT_IS_SHARING]; $fieldnames = []; @@ -442,15 +462,17 @@ class Probe $condition = ['nurl' => normalise_link($data["url"]), 'self' => false, 'uid' => 0]; - $old_fields = dba::selectFirst('contact', $fieldnames, $condition); + // "$old_fields" will return a "false" when the contact doesn't exist. + // This won't trigger an insert. This is intended, since we only need + // public contacts for everyone we store items from. + // We don't need to store every contact on the planet. + $old_fields = DBA::selectFirst('contact', $fieldnames, $condition); - // When the contact doesn't exist, the value "true" will trigger an insert - if (!$old_fields) { - $old_fields = true; - $fields['blocked'] = false; - } + $fields['name-date'] = DateTimeFormat::utcNow(); + $fields['uri-date'] = DateTimeFormat::utcNow(); + $fields['success_update'] = DateTimeFormat::utcNow(); - dba::update('contact', $fields, $condition, $old_fields); + DBA::update('contact', $fields, $condition, $old_fields); } } @@ -674,6 +696,14 @@ class Probe } } + if (empty($result["network"])) { + $result["network"] = NETWORK_PHANTOM; + } + + if (empty($result["url"])) { + $result["url"] = $uri; + } + logger($uri." is ".$result["network"], LOGGER_DEBUG); if (empty($result["baseurl"])) { @@ -701,7 +731,7 @@ class Probe $redirects = 0; $ret = Network::curl($url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => $type]); - if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { + if (!$ret["success"] && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) { return false; } $data = $ret['body']; @@ -768,7 +798,7 @@ class Probe private static function pollNoscrape($noscrape_url, $data) { $ret = Network::curl($noscrape_url); - if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { + if (!$ret["success"] && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) { return false; } $content = $ret['body']; @@ -957,7 +987,7 @@ class Probe } } - if (is_array($webfinger["aliases"])) { + if (!empty($webfinger["aliases"]) && is_array($webfinger["aliases"])) { foreach ($webfinger["aliases"] as $alias) { if (normalise_link($alias) != normalise_link($data["url"]) && ! strstr($alias, "@")) { $data["alias"] = $alias; @@ -967,7 +997,7 @@ class Probe } } - if (substr($webfinger["subject"], 0, 5) == "acct:") { + if (!empty($webfinger["subject"]) && (substr($webfinger["subject"], 0, 5) == "acct:")) { $data["addr"] = substr($webfinger["subject"], 5); } @@ -1006,7 +1036,7 @@ class Probe private static function pollHcard($hcard_url, $data, $dfrn = false) { $ret = Network::curl($hcard_url); - if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { + if (!$ret["success"] && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) { return false; } $content = $ret['body']; @@ -1026,13 +1056,17 @@ class Probe return false; } + if (!isset($data["baseurl"])) { + $data["baseurl"] = ""; + } + if ($vcards->length > 0) { $vcard = $vcards->item(0); // We have to discard the guid from the hcard in favour of the guid from lrdd // Reason: Hubzilla doesn't use the value "uid" in the hcard like Diaspora does. $search = $xpath->query("//*[contains(concat(' ', @class, ' '), ' uid ')]", $vcard); // */ - if (($search->length > 0) && ($data["guid"] == "")) { + if (($search->length > 0) && empty($data["guid"])) { $data["guid"] = $search->item(0)->nodeValue; } @@ -1066,21 +1100,23 @@ class Probe } $avatar = []; - $photos = $xpath->query("//*[contains(concat(' ', @class, ' '), ' photo ') or contains(concat(' ', @class, ' '), ' avatar ')]", $vcard); // */ - foreach ($photos as $photo) { - $attr = []; - foreach ($photo->attributes as $attribute) { - $attr[$attribute->name] = trim($attribute->value); - } + if (!empty($vcard)) { + $photos = $xpath->query("//*[contains(concat(' ', @class, ' '), ' photo ') or contains(concat(' ', @class, ' '), ' avatar ')]", $vcard); // */ + foreach ($photos as $photo) { + $attr = []; + foreach ($photo->attributes as $attribute) { + $attr[$attribute->name] = trim($attribute->value); + } - if (isset($attr["src"]) && isset($attr["width"])) { - $avatar[$attr["width"]] = $attr["src"]; - } + if (isset($attr["src"]) && isset($attr["width"])) { + $avatar[$attr["width"]] = $attr["src"]; + } - // We don't have a width. So we just take everything that we got. - // This is a Hubzilla workaround which doesn't send a width. - if ((sizeof($avatar) == 0) && !empty($attr["src"])) { - $avatar[] = $attr["src"]; + // We don't have a width. So we just take everything that we got. + // This is a Hubzilla workaround which doesn't send a width. + if ((sizeof($avatar) == 0) && !empty($attr["src"])) { + $avatar[] = $attr["src"]; + } } } @@ -1105,7 +1141,7 @@ class Probe } // Older Friendica versions had used the "uid" field differently than newer versions - if ($data["nick"] == $data["guid"]) { + if (!empty($data["nick"]) && !empty($data["guid"]) && ($data["nick"] == $data["guid"])) { unset($data["guid"]); } } @@ -1154,7 +1190,7 @@ class Probe return false; } - if (is_array($webfinger["aliases"])) { + if (!empty($webfinger["aliases"]) && is_array($webfinger["aliases"])) { foreach ($webfinger["aliases"] as $alias) { if (normalise_link($alias) != normalise_link($data["url"]) && ! strstr($alias, "@")) { $data["alias"] = $alias; @@ -1184,7 +1220,9 @@ class Probe $data["network"] = NETWORK_DIASPORA; // The Diaspora handle must always be lowercase - $data["addr"] = strtolower($data["addr"]); + if (!empty($data["addr"])) { + $data["addr"] = strtolower($data["addr"]); + } // We have to overwrite the detected value for "notify" since Hubzilla doesn't send it $data["notify"] = $data["baseurl"] . "/receive/users/" . $data["guid"]; @@ -1208,7 +1246,7 @@ class Probe { $data = []; - if (is_array($webfinger["aliases"])) { + if (!empty($webfinger["aliases"]) && is_array($webfinger["aliases"])) { foreach ($webfinger["aliases"] as $alias) { if (strstr($alias, "@") && !strstr(normalise_link($alias), "http://")) { $data["addr"] = str_replace('acct:', '', $alias); @@ -1216,7 +1254,7 @@ class Probe } } - if (is_string($webfinger["subject"]) && strstr($webfinger["subject"], "@") + if (!empty($webfinger["subject"]) && strstr($webfinger["subject"], "@") && !strstr(normalise_link($webfinger["subject"]), "http://") ) { $data["addr"] = str_replace('acct:', '', $webfinger["subject"]); @@ -1245,7 +1283,7 @@ class Probe } } elseif (normalise_link($pubkey) == 'http://') { $ret = Network::curl($pubkey); - if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { + if (!$ret["success"] && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) { return false; } $pubkey = $ret['body']; @@ -1277,36 +1315,39 @@ class Probe // Fetch all additional data from the feed $ret = Network::curl($data["poll"]); - if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { + if (!$ret["success"] && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) { return false; } $feed = $ret['body']; + $dummy1 = null; + $dummy2 = null; + $dummy2 = null; $feed_data = Feed::import($feed, $dummy1, $dummy2, $dummy3, true); if (!$feed_data) { return false; } - if ($feed_data["header"]["author-name"] != "") { + if (!empty($feed_data["header"]["author-name"])) { $data["name"] = $feed_data["header"]["author-name"]; } - if ($feed_data["header"]["author-nick"] != "") { + if (!empty($feed_data["header"]["author-nick"])) { $data["nick"] = $feed_data["header"]["author-nick"]; } - if ($feed_data["header"]["author-avatar"] != "") { + if (!empty($feed_data["header"]["author-avatar"])) { $data["photo"] = self::fixAvatar($feed_data["header"]["author-avatar"], $data["url"]); } - if ($feed_data["header"]["author-id"] != "") { + if (!empty($feed_data["header"]["author-id"])) { $data["alias"] = $feed_data["header"]["author-id"]; } - if ($feed_data["header"]["author-location"] != "") { + if (!empty($feed_data["header"]["author-location"])) { $data["location"] = $feed_data["header"]["author-location"]; } - if ($feed_data["header"]["author-about"] != "") { + if (!empty($feed_data["header"]["author-about"])) { $data["about"] = $feed_data["header"]["author-about"]; } // OStatus has serious issues when the the url doesn't fit (ssl vs. non ssl) // So we take the value that we just fetched, although the other one worked as well - if ($feed_data["header"]["author-link"] != "") { + if (!empty($feed_data["header"]["author-link"])) { $data["url"] = $feed_data["header"]["author-link"]; } @@ -1348,16 +1389,16 @@ class Probe } } - $data["location"] = $xpath->query("//p[contains(@class, 'p-locality')]")->item(0)->nodeValue; + $data["location"] = XML::getFirstNodeValue($xpath, "//p[contains(@class, 'p-locality')]"); if ($data["location"] == '') { - $data["location"] = $xpath->query("//p[contains(@class, 'location')]")->item(0)->nodeValue; + $data["location"] = XML::getFirstNodeValue($xpath, "//p[contains(@class, 'location')]"); } - $data["about"] = $xpath->query("//p[contains(@class, 'p-note')]")->item(0)->nodeValue; + $data["about"] = XML::getFirstNodeValue($xpath, "//p[contains(@class, 'p-note')]"); if ($data["about"] == '') { - $data["about"] = $xpath->query("//p[contains(@class, 'summary')]")->item(0)->nodeValue; + $data["about"] = XML::getFirstNodeValue($xpath, "//p[contains(@class, 'summary')]"); } $avatar = $xpath->query("//img[contains(@class, 'u-photo')]")->item(0); @@ -1484,10 +1525,11 @@ class Probe private static function feed($url, $probe = true) { $ret = Network::curl($url); - if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { + if (!$ret["success"] && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) { return false; } $feed = $ret['body']; + $dummy1 = $dummy2 = $dummy3 = null; $feed_data = Feed::import($feed, $dummy1, $dummy2, $dummy3, true); if (!$feed_data) { @@ -1504,26 +1546,26 @@ class Probe return self::feed($feed_url, false); } - if ($feed_data["header"]["author-name"] != "") { + if (!empty($feed_data["header"]["author-name"])) { $data["name"] = $feed_data["header"]["author-name"]; } - if ($feed_data["header"]["author-nick"] != "") { + if (!empty($feed_data["header"]["author-nick"])) { $data["nick"] = $feed_data["header"]["author-nick"]; } - if ($feed_data["header"]["author-avatar"] != "") { + if (!empty($feed_data["header"]["author-avatar"])) { $data["photo"] = $feed_data["header"]["author-avatar"]; } - if ($feed_data["header"]["author-id"] != "") { + if (!empty($feed_data["header"]["author-id"])) { $data["alias"] = $feed_data["header"]["author-id"]; } $data["url"] = $url; $data["poll"] = $url; - if ($feed_data["header"]["author-link"] != "") { + if (!empty($feed_data["header"]["author-link"])) { $data["baseurl"] = $feed_data["header"]["author-link"]; } else { $data["baseurl"] = $data["url"];