X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;ds=sidebyside;f=src%2FProtocol%2FPortableContact.php;h=5b419e42eff3d15deb989d8cc8cac66231f71eca;hb=d8e9ed5ff8cc8bacad8d7ea8180607d002196513;hp=f884b0f283a641926f04b83da647b63f6a632990;hpb=47db624105182194b11f0039742deda6fc12c54d;p=friendica.git diff --git a/src/Protocol/PortableContact.php b/src/Protocol/PortableContact.php index f884b0f283..5b419e42ef 100644 --- a/src/Protocol/PortableContact.php +++ b/src/Protocol/PortableContact.php @@ -9,20 +9,21 @@ namespace Friendica\Protocol; -use Friendica\App; -use Friendica\Core\System; -use Friendica\Core\Cache; use Friendica\Core\Config; use Friendica\Core\Worker; use Friendica\Database\DBM; -use Friendica\Model\GlobalContact; +use Friendica\Model\GContact; +use Friendica\Model\Profile; use Friendica\Network\Probe; - -require_once 'include/datetime.php'; -require_once 'include/network.php'; +use Friendica\Util\DateTimeFormat; +use Friendica\Util\Network; +use dba; +use DOMDocument; +use DOMXPath; +use Exception; + +require_once 'include/dba.php'; require_once 'include/html2bbcode.php'; -require_once 'include/Contact.php'; -require_once 'include/Photo.php'; class PortableContact { @@ -47,7 +48,7 @@ class PortableContact public static function loadWorker($cid, $uid = 0, $zcid = 0, $url = null) { // Call the function "load" via the worker - Worker::add(PRIORITY_LOW, "discover_poco", "load", (int)$cid, (int)$uid, (int)$zcid, $url); + Worker::add(PRIORITY_LOW, "DiscoverPoCo", "load", (int)$cid, (int)$uid, (int)$zcid, $url); } /** @@ -64,22 +65,19 @@ class PortableContact $a = get_app(); if ($cid) { - if ((! $url) || (! $uid)) { - $r = q( - "select `poco`, `uid` from `contact` where `id` = %d limit 1", - intval($cid) - ); - if (DBM::is_result($r)) { - $url = $r[0]['poco']; - $uid = $r[0]['uid']; + if (!$url || !$uid) { + $contact = dba::selectFirst('contact', ['poco', 'uid'], ['id' => $cid]); + if (DBM::is_result($contact)) { + $url = $contact['poco']; + $uid = $contact['uid']; } } - if (! $uid) { + if (!$uid) { return; } } - if (! $url) { + if (!$url) { return; } @@ -87,7 +85,7 @@ class PortableContact logger('load: ' . $url, LOGGER_DEBUG); - $s = fetch_url($url); + $s = Network::fetchUrl($url); logger('load: returns ' . $s, LOGGER_DATA); @@ -145,7 +143,7 @@ class PortableContact } if (isset($entry->updated)) { - $updated = date("Y-m-d H:i:s", strtotime($entry->updated)); + $updated = date(DateTimeFormat::MYSQL, strtotime($entry->updated)); } if (isset($entry->network)) { @@ -178,7 +176,7 @@ class PortableContact $contact_type = $entry->contactType; } - $gcontact = array("url" => $profile_url, + $gcontact = ["url" => $profile_url, "name" => $name, "network" => $network, "photo" => $profile_photo, @@ -189,42 +187,38 @@ class PortableContact "connect" => $connect_url, "updated" => $updated, "contact-type" => $contact_type, - "generation" => $generation); + "generation" => $generation]; try { - $gcontact = GlobalContact::sanitize($gcontact); - $gcid = GlobalContact::update($gcontact); + $gcontact = GContact::sanitize($gcontact); + $gcid = GContact::update($gcontact); - GlobalContact::link($gcid, $uid, $cid, $zcid); + GContact::link($gcid, $uid, $cid, $zcid); } catch (Exception $e) { logger($e->getMessage(), LOGGER_DEBUG); } } logger("load: loaded $total entries", LOGGER_DEBUG); - q( - "DELETE FROM `glink` WHERE `cid` = %d AND `uid` = %d AND `zcid` = %d AND `updated` < UTC_TIMESTAMP - INTERVAL 2 DAY", - intval($cid), - intval($uid), - intval($zcid) - ); + $condition = ["`cid` = ? AND `uid` = ? AND `zcid` = ? AND `updated` < UTC_TIMESTAMP - INTERVAL 2 DAY", $cid, $uid, $zcid]; + dba::delete('glink', $condition); } - function poco_reachable($profile, $server = "", $network = "", $force = false) { - + public static function reachable($profile, $server = "", $network = "", $force = false) + { if ($server == "") { - $server = poco_detect_server($profile); + $server = self::detectServer($profile); } if ($server == "") { return true; } - return poco_check_server($server, $network, $force); + return self::checkServer($server, $network, $force); } - function poco_detect_server($profile) { - + public static function detectServer($profile) + { // Try to detect the server path based upon some known standard paths $server_url = ""; @@ -283,14 +277,17 @@ class PortableContact return ""; } - $r = q("SELECT `id` FROM `gserver` WHERE `nurl` = '%s' AND `last_contact` > `last_failure`", - dbesc(normalise_link($server_url))); + $r = q( + "SELECT `id` FROM `gserver` WHERE `nurl` = '%s' AND `last_contact` > `last_failure`", + dbesc(normalise_link($server_url)) + ); + if (DBM::is_result($r)) { return $server_url; } // Fetch the host-meta to check if this really is a server - $serverret = z_fetch_url($server_url."/.well-known/host-meta"); + $serverret = Network::curl($server_url."/.well-known/host-meta"); if (!$serverret["success"]) { return ""; } @@ -298,27 +295,31 @@ class PortableContact return $server_url; } - function poco_alternate_ostatus_url($url) { + public static function alternateOStatusUrl($url) + { return(preg_match("=https?://.+/user/\d+=ism", $url, $matches)); } - function poco_last_updated($profile, $force = false) { - - $gcontacts = q("SELECT * FROM `gcontact` WHERE `nurl` = '%s'", - dbesc(normalise_link($profile))); + public static function lastUpdated($profile, $force = false) + { + $gcontacts = q( + "SELECT * FROM `gcontact` WHERE `nurl` = '%s'", + dbesc(normalise_link($profile)) + ); if (!DBM::is_result($gcontacts)) { return false; } - $contact = array("url" => $profile); + $contact = ["url" => $profile]; if ($gcontacts[0]["created"] <= NULL_DATE) { - $contact['created'] = datetime_convert(); + $contact['created'] = DateTimeFormat::utcNow(); } + $server_url = ''; if ($force) { - $server_url = normalise_link(poco_detect_server($profile)); + $server_url = normalise_link(self::detectServer($profile)); } if (($server_url == '') && ($gcontacts[0]["server_url"] != "")) { @@ -326,19 +327,19 @@ class PortableContact } if (!$force && (($server_url == '') || ($gcontacts[0]["server_url"] == $gcontacts[0]["nurl"]))) { - $server_url = normalise_link(poco_detect_server($profile)); + $server_url = normalise_link(self::detectServer($profile)); } - if (!in_array($gcontacts[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_FEED, NETWORK_OSTATUS, ""))) { + if (!in_array($gcontacts[0]["network"], [NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_FEED, NETWORK_OSTATUS, ""])) { logger("Profile ".$profile.": Network type ".$gcontacts[0]["network"]." can't be checked", LOGGER_DEBUG); return false; } if ($server_url != "") { - if (!poco_check_server($server_url, $gcontacts[0]["network"], $force)) { + if (!self::checkServer($server_url, $gcontacts[0]["network"], $force)) { if ($force) { - q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `nurl` = '%s'", - dbesc(datetime_convert()), dbesc(normalise_link($profile))); + $fields = ['last_failure' => DateTimeFormat::utcNow()]; + dba::update('gcontact', $fields, ['nurl' => normalise_link($profile)]); } logger("Profile ".$profile.": Server ".$server_url." wasn't reachable.", LOGGER_DEBUG); @@ -347,9 +348,11 @@ class PortableContact $contact['server_url'] = $server_url; } - if (in_array($gcontacts[0]["network"], array("", NETWORK_FEED))) { - $server = q("SELECT `network` FROM `gserver` WHERE `nurl` = '%s' AND `network` != ''", - dbesc(normalise_link($server_url))); + if (in_array($gcontacts[0]["network"], ["", NETWORK_FEED])) { + $server = q( + "SELECT `network` FROM `gserver` WHERE `nurl` = '%s' AND `network` != ''", + dbesc(normalise_link($server_url)) + ); if ($server) { $contact['network'] = $server[0]["network"]; @@ -360,15 +363,13 @@ class PortableContact // noscrape is really fast so we don't cache the call. if (($server_url != "") && ($gcontacts[0]["nick"] != "")) { - // Use noscrape if possible $server = q("SELECT `noscrape`, `network` FROM `gserver` WHERE `nurl` = '%s' AND `noscrape` != ''", dbesc(normalise_link($server_url))); if ($server) { - $noscraperet = z_fetch_url($server[0]["noscrape"]."/".$gcontacts[0]["nick"]); + $noscraperet = Network::curl($server[0]["noscrape"]."/".$gcontacts[0]["nick"]); if ($noscraperet["success"] && ($noscraperet["body"] != "")) { - $noscrape = json_decode($noscraperet["body"], true); if (is_array($noscrape)) { @@ -387,7 +388,7 @@ class PortableContact } } - $location = formatted_location($noscrape); + $location = Profile::formatLocation($noscrape); if ($location) { $contact["location"] = $location; } @@ -411,15 +412,15 @@ class PortableContact // Set the date of the last contact /// @todo By now the function "update_gcontact" doesn't work with this field - //$contact["last_contact"] = datetime_convert(); + //$contact["last_contact"] = DateTimeFormat::utcNow(); $contact = array_merge($contact, $noscrape); - GlobalContact::update($contact); + GContact::update($contact); if (trim($noscrape["updated"]) != "") { - q("UPDATE `gcontact` SET `last_contact` = '%s' WHERE `nurl` = '%s'", - dbesc(datetime_convert()), dbesc(normalise_link($profile))); + $fields = ['last_contact' => DateTimeFormat::utcNow()]; + dba::update('gcontact', $fields, ['nurl' => normalise_link($profile)]); logger("Profile ".$profile." was last updated at ".$noscrape["updated"]." (noscrape)", LOGGER_DEBUG); @@ -431,10 +432,10 @@ class PortableContact } // If we only can poll the feed, then we only do this once a while - if (!$force && !poco_do_update($gcontacts[0]["created"], $gcontacts[0]["updated"], $gcontacts[0]["last_failure"], $gcontacts[0]["last_contact"])) { + if (!$force && !self::updateNeeded($gcontacts[0]["created"], $gcontacts[0]["updated"], $gcontacts[0]["last_failure"], $gcontacts[0]["last_contact"])) { logger("Profile ".$profile." was last updated at ".$gcontacts[0]["updated"]." (cached)", LOGGER_DEBUG); - GlobalContact::update($contact); + GContact::update($contact); return $gcontacts[0]["updated"]; } @@ -442,23 +443,22 @@ class PortableContact // Is the profile link the alternate OStatus link notation? (http://domain.tld/user/4711) // Then check the other link and delete this one - if (($data["network"] == NETWORK_OSTATUS) && poco_alternate_ostatus_url($profile) + if (($data["network"] == NETWORK_OSTATUS) && self::alternateOStatusUrl($profile) && (normalise_link($profile) == normalise_link($data["alias"])) && (normalise_link($profile) != normalise_link($data["url"])) ) { // Delete the old entry - q("DELETE FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($profile))); - q("DELETE FROM `glink` WHERE `gcid` = %d", intval($gcontacts[0]["id"])); + dba::delete('gcontact', ['nurl' => normalise_link($profile)]); $gcontact = array_merge($gcontacts[0], $data); $gcontact["server_url"] = $data["baseurl"]; try { - $gcontact = GlobalContact::sanitize($gcontact); - GlobalContact::update($gcontact); + $gcontact = GContact::sanitize($gcontact); + GContact::update($gcontact); - poco_last_updated($data["url"], $force); + self::lastUpdated($data["url"], $force); } catch (Exception $e) { logger($e->getMessage(), LOGGER_DEBUG); } @@ -467,9 +467,9 @@ class PortableContact return false; } - if (($data["poll"] == "") || (in_array($data["network"], array(NETWORK_FEED, NETWORK_PHANTOM)))) { - q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `nurl` = '%s'", - dbesc(datetime_convert()), dbesc(normalise_link($profile))); + if (($data["poll"] == "") || (in_array($data["network"], [NETWORK_FEED, NETWORK_PHANTOM]))) { + $fields = ['last_failure' => DateTimeFormat::utcNow()]; + dba::update('gcontact', $fields, ['nurl' => normalise_link($profile)]); logger("Profile ".$profile." wasn't reachable (profile)", LOGGER_DEBUG); return false; @@ -479,13 +479,13 @@ class PortableContact $contact["server_url"] = $data["baseurl"]; - GlobalContact::update($contact); + GContact::update($contact); - $feedret = z_fetch_url($data["poll"]); + $feedret = Network::curl($data["poll"]); if (!$feedret["success"]) { - q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `nurl` = '%s'", - dbesc(datetime_convert()), dbesc(normalise_link($profile))); + $fields = ['last_failure' => DateTimeFormat::utcNow()]; + dba::update('gcontact', $fields, ['nurl' => normalise_link($profile)]); logger("Profile ".$profile." wasn't reachable (no feed)", LOGGER_DEBUG); return false; @@ -494,7 +494,7 @@ class PortableContact $doc = new DOMDocument(); @$doc->loadXML($feedret["body"]); - $xpath = new DomXPath($doc); + $xpath = new DOMXPath($doc); $xpath->registerNamespace('atom', "http://www.w3.org/2005/Atom"); $entries = $xpath->query('/atom:feed/atom:entry'); @@ -502,14 +502,16 @@ class PortableContact $last_updated = ""; foreach ($entries as $entry) { - $published = $xpath->query('atom:published/text()', $entry)->item(0)->nodeValue; - $updated = $xpath->query('atom:updated/text()', $entry)->item(0)->nodeValue; + $published = DateTimeFormat::utc($xpath->query('atom:published/text()', $entry)->item(0)->nodeValue); + $updated = DateTimeFormat::utc($xpath->query('atom:updated/text()' , $entry)->item(0)->nodeValue); - if ($last_updated < $published) + if ($last_updated < $published) { $last_updated = $published; + } - if ($last_updated < $updated) + if ($last_updated < $updated) { $last_updated = $updated; + } } // Maybe there aren't any entries. Then check if it is a valid feed @@ -518,21 +520,23 @@ class PortableContact $last_updated = NULL_DATE; } } - q("UPDATE `gcontact` SET `updated` = '%s', `last_contact` = '%s' WHERE `nurl` = '%s'", - dbesc(DBM::date($last_updated)), dbesc(DBM::date()), dbesc(normalise_link($profile))); + + $fields = ['updated' => $last_updated, 'last_contact' => DateTimeFormat::utcNow()]; + dba::update('gcontact', $fields, ['nurl' => normalise_link($profile)]); if (($gcontacts[0]["generation"] == 0)) { - q("UPDATE `gcontact` SET `generation` = 9 WHERE `nurl` = '%s'", - dbesc(normalise_link($profile))); + $fields = ['generation' => 9]; + dba::update('gcontact', $fields, ['nurl' => normalise_link($profile)]); } logger("Profile ".$profile." was last updated at ".$last_updated, LOGGER_DEBUG); - return($last_updated); + return $last_updated; } - function poco_do_update($created, $updated, $last_failure, $last_contact) { - $now = strtotime(datetime_convert()); + public static function updateNeeded($created, $updated, $last_failure, $last_contact) + { + $now = strtotime(DateTimeFormat::utcNow()); if ($updated > $last_contact) { $contact_time = strtotime($updated); @@ -575,7 +579,8 @@ class PortableContact return true; } - function poco_to_boolean($val) { + private static function toBoolean($val) + { if (($val == "true") || ($val == 1)) { return true; } elseif (($val == "false") || ($val == 0)) { @@ -591,7 +596,8 @@ class PortableContact * @param object $data POCO data * @return array Server data */ - function poco_detect_poco_data($data) { + private static function detectPocoData($data) + { $server = false; if (!isset($data->entry)) { @@ -612,7 +618,7 @@ class PortableContact foreach ($data->entry[0]->urls as $url) { if ($url->type == 'zot') { - $server = array(); + $server = []; $server["platform"] = 'Hubzilla'; $server["network"] = NETWORK_DIASPORA; return $server; @@ -627,8 +633,9 @@ class PortableContact * @param string $server_url address of the server * @return array Server data */ - function poco_fetch_nodeinfo($server_url) { - $serverret = z_fetch_url($server_url."/.well-known/nodeinfo"); + private static function fetchNodeinfo($server_url) + { + $serverret = Network::curl($server_url."/.well-known/nodeinfo"); if (!$serverret["success"]) { return false; } @@ -643,30 +650,56 @@ class PortableContact return false; } - $nodeinfo_url = ''; + $nodeinfo1_url = ''; + $nodeinfo2_url = ''; foreach ($nodeinfo->links as $link) { if ($link->rel == 'http://nodeinfo.diaspora.software/ns/schema/1.0') { - $nodeinfo_url = $link->href; + $nodeinfo1_url = $link->href; + } + if ($link->rel == 'http://nodeinfo.diaspora.software/ns/schema/2.0') { + $nodeinfo2_url = $link->href; } } - if ($nodeinfo_url == '') { + if ($nodeinfo1_url . $nodeinfo2_url == '') { return false; } - $serverret = z_fetch_url($nodeinfo_url); + $server = []; + + // When the nodeinfo url isn't on the same host, then there is obviously something wrong + if (!empty($nodeinfo2_url) && (parse_url($server_url, PHP_URL_HOST) == parse_url($nodeinfo2_url, PHP_URL_HOST))) { + $server = self::parseNodeinfo2($nodeinfo2_url); + } + + // When the nodeinfo url isn't on the same host, then there is obviously something wrong + if (empty($server) && !empty($nodeinfo1_url) && (parse_url($server_url, PHP_URL_HOST) == parse_url($nodeinfo1_url, PHP_URL_HOST))) { + $server = self::parseNodeinfo1($nodeinfo1_url); + } + + return $server; + } + + /** + * @brief Parses Nodeinfo 1 + * + * @param string $nodeinfo_url address of the nodeinfo path + * @return array Server data + */ + private static function parseNodeinfo1($nodeinfo_url) + { + $serverret = Network::curl($nodeinfo_url); if (!$serverret["success"]) { return false; } $nodeinfo = json_decode($serverret['body']); - if (!is_object($nodeinfo)) { return false; } - $server = array(); + $server = []; $server['register_policy'] = REGISTER_CLOSED; @@ -693,6 +726,10 @@ class PortableContact } } + if (!empty($nodeinfo->usage->users->total)) { + $server['registered-users'] = $nodeinfo->usage->users->total; + } + $diaspora = false; $friendica = false; $gnusocial = false; @@ -728,23 +765,108 @@ class PortableContact return $server; } + /** + * @brief Parses Nodeinfo 2 + * + * @param string $nodeinfo_url address of the nodeinfo path + * @return array Server data + */ + private static function parseNodeinfo2($nodeinfo_url) + { + $serverret = Network::curl($nodeinfo_url); + if (!$serverret["success"]) { + return false; + } + + $nodeinfo = json_decode($serverret['body']); + if (!is_object($nodeinfo)) { + return false; + } + + $server = []; + + $server['register_policy'] = REGISTER_CLOSED; + + if (is_bool($nodeinfo->openRegistrations) && $nodeinfo->openRegistrations) { + $server['register_policy'] = REGISTER_OPEN; + } + + if (is_object($nodeinfo->software)) { + if (isset($nodeinfo->software->name)) { + $server['platform'] = $nodeinfo->software->name; + } + + if (isset($nodeinfo->software->version)) { + $server['version'] = $nodeinfo->software->version; + // Version numbers on Nodeinfo are presented with additional info, e.g.: + // 0.6.3.0-p1702cc1c, 0.6.99.0-p1b9ab160 or 3.4.3-2-1191. + $server['version'] = preg_replace("=(.+)-(.{4,})=ism", "$1", $server['version']); + } + } + + if (is_object($nodeinfo->metadata)) { + if (isset($nodeinfo->metadata->nodeName)) { + $server['site_name'] = $nodeinfo->metadata->nodeName; + } + } + + if (!empty($nodeinfo->usage->users->total)) { + $server['registered-users'] = $nodeinfo->usage->users->total; + } + + $diaspora = false; + $friendica = false; + $gnusocial = false; + + if (is_array($nodeinfo->protocols)) { + foreach ($nodeinfo->protocols as $protocol) { + if ($protocol == 'diaspora') { + $diaspora = true; + } + if ($protocol == 'friendica') { + $friendica = true; + } + if ($protocol == 'gnusocial') { + $gnusocial = true; + } + } + } + + if ($gnusocial) { + $server['network'] = NETWORK_OSTATUS; + } + if ($diaspora) { + $server['network'] = NETWORK_DIASPORA; + } + if ($friendica) { + $server['network'] = NETWORK_DFRN; + } + + if (!$server) { + return false; + } + + return $server; + } + /** * @brief Detect server type (Hubzilla or Friendica) via the front page body * * @param string $body Front page of the server * @return array Server data */ - function poco_detect_server_type($body) { + private static function detectServerType($body) + { $server = false; $doc = new DOMDocument(); @$doc->loadHTML($body); - $xpath = new DomXPath($doc); + $xpath = new DOMXPath($doc); $list = $xpath->query("//meta[@name]"); foreach ($list as $node) { - $attr = array(); + $attr = []; if ($node->attributes->length) { foreach ($node->attributes as $attribute) { $attr[$attribute->name] = $attribute->value; @@ -753,8 +875,8 @@ class PortableContact if ($attr['name'] == 'generator') { $version_part = explode(" ", $attr['content']); if (count($version_part) == 2) { - if (in_array($version_part[0], array("Friendika", "Friendica"))) { - $server = array(); + if (in_array($version_part[0], ["Friendika", "Friendica"])) { + $server = []; $server["platform"] = $version_part[0]; $server["version"] = $version_part[1]; $server["network"] = NETWORK_DFRN; @@ -767,14 +889,14 @@ class PortableContact $list = $xpath->query("//meta[@property]"); foreach ($list as $node) { - $attr = array(); + $attr = []; if ($node->attributes->length) { foreach ($node->attributes as $attribute) { $attr[$attribute->name] = $attribute->value; } } - if ($attr['property'] == 'generator' && in_array($attr['content'], array("hubzilla", "BlaBlaNet"))) { - $server = array(); + if ($attr['property'] == 'generator' && in_array($attr['content'], ["hubzilla", "BlaBlaNet"])) { + $server = []; $server["platform"] = $attr['content']; $server["version"] = ""; $server["network"] = NETWORK_DIASPORA; @@ -786,12 +908,12 @@ class PortableContact return false; } - $server["site_name"] = $xpath->evaluate($element."//head/title/text()", $context)->item(0)->nodeValue; + $server["site_name"] = $xpath->evaluate("//head/title/text()")->item(0)->nodeValue; return $server; } - function poco_check_server($server_url, $network = "", $force = false) { - + public static function checkServer($server_url, $network = "", $force = false) + { // Unify the server address $server_url = trim($server_url, "/"); $server_url = str_replace("/index.php", "", $server_url); @@ -800,29 +922,30 @@ class PortableContact return false; } - $servers = q("SELECT * FROM `gserver` WHERE `nurl` = '%s'", dbesc(normalise_link($server_url))); - if (DBM::is_result($servers)) { - - if ($servers[0]["created"] <= NULL_DATE) { - q("UPDATE `gserver` SET `created` = '%s' WHERE `nurl` = '%s'", - dbesc(datetime_convert()), dbesc(normalise_link($server_url))); + $gserver = dba::selectFirst('gserver', [], ['nurl' => normalise_link($server_url)]); + if (DBM::is_result($gserver)) { + if ($gserver["created"] <= NULL_DATE) { + $fields = ['created' => DateTimeFormat::utcNow()]; + $condition = ['nurl' => normalise_link($server_url)]; + dba::update('gserver', $fields, $condition); } - $poco = $servers[0]["poco"]; - $noscrape = $servers[0]["noscrape"]; + $poco = $gserver["poco"]; + $noscrape = $gserver["noscrape"]; if ($network == "") { - $network = $servers[0]["network"]; + $network = $gserver["network"]; } - $last_contact = $servers[0]["last_contact"]; - $last_failure = $servers[0]["last_failure"]; - $version = $servers[0]["version"]; - $platform = $servers[0]["platform"]; - $site_name = $servers[0]["site_name"]; - $info = $servers[0]["info"]; - $register_policy = $servers[0]["register_policy"]; + $last_contact = $gserver["last_contact"]; + $last_failure = $gserver["last_failure"]; + $version = $gserver["version"]; + $platform = $gserver["platform"]; + $site_name = $gserver["site_name"]; + $info = $gserver["info"]; + $register_policy = $gserver["register_policy"]; + $registered_users = $gserver["registered-users"]; - if (!$force && !poco_do_update($servers[0]["created"], "", $last_failure, $last_contact)) { + if (!$force && !self::updateNeeded($gserver["created"], "", $last_failure, $last_contact)) { logger("Use cached data for server ".$server_url, LOGGER_DEBUG); return ($last_contact >= $last_failure); } @@ -834,54 +957,62 @@ class PortableContact $site_name = ""; $info = ""; $register_policy = -1; + $registered_users = 0; $last_contact = NULL_DATE; $last_failure = NULL_DATE; } - logger("Server ".$server_url." is outdated or unknown. Start discovery. Force: ".$force." Created: ".$servers[0]["created"]." Failure: ".$last_failure." Contact: ".$last_contact, LOGGER_DEBUG); + logger("Server ".$server_url." is outdated or unknown. Start discovery. Force: ".$force." Created: ".$gserver["created"]." Failure: ".$last_failure." Contact: ".$last_contact, LOGGER_DEBUG); $failure = false; $possible_failure = false; $orig_last_failure = $last_failure; $orig_last_contact = $last_contact; + // Mastodon uses the "@" for user profiles. + // But this can be misunderstood. + if (parse_url($server_url, PHP_URL_USER) != '') { + dba::update('gserver', ['last_failure' => DateTimeFormat::utcNow()], ['nurl' => normalise_link($server_url)]); + return false; + } + // Check if the page is accessible via SSL. $orig_server_url = $server_url; $server_url = str_replace("http://", "https://", $server_url); // We set the timeout to 20 seconds since this operation should be done in no time if the server was vital - $serverret = z_fetch_url($server_url."/.well-known/host-meta", false, $redirects, array('timeout' => 20)); + $serverret = Network::curl($server_url."/.well-known/host-meta", false, $redirects, ['timeout' => 20]); // Quit if there is a timeout. // But we want to make sure to only quit if we are mostly sure that this server url fits. - if (DBM::is_result($servers) && ($orig_server_url == $server_url) && + if (DBM::is_result($gserver) && ($orig_server_url == $server_url) && ($serverret['errno'] == CURLE_OPERATION_TIMEDOUT)) { logger("Connection to server ".$server_url." timed out.", LOGGER_DEBUG); - dba::update('gserver', array('last_failure' => datetime_convert()), array('nurl' => normalise_link($server_url))); + dba::update('gserver', ['last_failure' => DateTimeFormat::utcNow()], ['nurl' => normalise_link($server_url)]); return false; } // Maybe the page is unencrypted only? - $xmlobj = @simplexml_load_string($serverret["body"],'SimpleXMLElement',0, "http://docs.oasis-open.org/ns/xri/xrd-1.0"); + $xmlobj = @simplexml_load_string($serverret["body"], 'SimpleXMLElement', 0, "http://docs.oasis-open.org/ns/xri/xrd-1.0"); if (!$serverret["success"] || ($serverret["body"] == "") || (@sizeof($xmlobj) == 0) || !is_object($xmlobj)) { $server_url = str_replace("https://", "http://", $server_url); // We set the timeout to 20 seconds since this operation should be done in no time if the server was vital - $serverret = z_fetch_url($server_url."/.well-known/host-meta", false, $redirects, array('timeout' => 20)); + $serverret = Network::curl($server_url."/.well-known/host-meta", false, $redirects, ['timeout' => 20]); // Quit if there is a timeout if ($serverret['errno'] == CURLE_OPERATION_TIMEDOUT) { logger("Connection to server ".$server_url." timed out.", LOGGER_DEBUG); - dba::update('gserver', array('last_failure' => datetime_convert()), array('nurl' => normalise_link($server_url))); + dba::update('gserver', ['last_failure' => DateTimeFormat::utcNow()], ['nurl' => normalise_link($server_url)]); return false; } - $xmlobj = @simplexml_load_string($serverret["body"],'SimpleXMLElement',0, "http://docs.oasis-open.org/ns/xri/xrd-1.0"); + $xmlobj = @simplexml_load_string($serverret["body"], 'SimpleXMLElement', 0, "http://docs.oasis-open.org/ns/xri/xrd-1.0"); } if (!$serverret["success"] || ($serverret["body"] == "") || (sizeof($xmlobj) == 0) || !is_object($xmlobj)) { // Workaround for bad configured servers (known nginx problem) - if (!in_array($serverret["debug"]["http_code"], array("403", "404"))) { + if (!in_array($serverret["debug"]["http_code"], ["403", "404"])) { $failure = true; } $possible_failure = true; @@ -896,14 +1027,20 @@ class PortableContact $register_policy = -1; } + if (!$failure) { + // This will be too low, but better than no value at all. + $registered_users = dba::count('gcontact', ['server_url' => normalise_link($server_url)]); + } + // Look for poco if (!$failure) { - $serverret = z_fetch_url($server_url."/poco"); + $serverret = Network::curl($server_url."/poco"); if ($serverret["success"]) { $data = json_decode($serverret["body"]); if (isset($data->totalResults)) { + $registered_users = $data->totalResults; $poco = $server_url."/poco"; - $server = poco_detect_poco_data($data); + $server = self::detectPocoData($data); if ($server) { $platform = $server['platform']; $network = $server['network']; @@ -911,17 +1048,24 @@ class PortableContact $site_name = ''; } } + // There are servers out there who don't return 404 on a failure + // We have to be sure that don't misunderstand this + if (is_null($data)) { + $poco = ""; + $noscrape = ""; + $network = ""; + } } } if (!$failure) { // Test for Diaspora, Hubzilla, Mastodon or older Friendica servers - $serverret = z_fetch_url($server_url); + $serverret = Network::curl($server_url); if (!$serverret["success"] || ($serverret["body"] == "")) { $failure = true; } else { - $server = poco_detect_server_type($serverret["body"]); + $server = self::detectServerType($serverret["body"]); if ($server) { $platform = $server['platform']; $network = $server['network']; @@ -929,11 +1073,11 @@ class PortableContact $site_name = $server['site_name']; } - $lines = explode("\n",$serverret["header"]); + $lines = explode("\n", $serverret["header"]); if (count($lines)) { - foreach($lines as $line) { + foreach ($lines as $line) { $line = trim($line); - if (stristr($line,'X-Diaspora-Version:')) { + if (stristr($line, 'X-Diaspora-Version:')) { $platform = "Diaspora"; $version = trim(str_replace("X-Diaspora-Version:", "", $line)); $version = trim(str_replace("x-diaspora-version:", "", $version)); @@ -942,7 +1086,7 @@ class PortableContact $version = $versionparts[0]; } - if (stristr($line,'Server: Mastodon')) { + if (stristr($line, 'Server: Mastodon')) { $platform = "Mastodon"; $network = NETWORK_OSTATUS; } @@ -955,7 +1099,7 @@ class PortableContact // Test for Statusnet // Will also return data for Friendica and GNU Social - but it will be overwritten later // The "not implemented" is a special treatment for really, really old Friendica versions - $serverret = z_fetch_url($server_url."/api/statusnet/version.json"); + $serverret = Network::curl($server_url."/api/statusnet/version.json"); if ($serverret["success"] && ($serverret["body"] != '{"error":"not implemented"}') && ($serverret["body"] != '') && (strlen($serverret["body"]) < 30)) { $platform = "StatusNet"; @@ -966,7 +1110,7 @@ class PortableContact } // Test for GNU Social - $serverret = z_fetch_url($server_url."/api/gnusocial/version.json"); + $serverret = Network::curl($server_url."/api/gnusocial/version.json"); if ($serverret["success"] && ($serverret["body"] != '{"error":"not implemented"}') && ($serverret["body"] != '') && (strlen($serverret["body"]) < 30)) { $platform = "GNU Social"; @@ -978,9 +1122,10 @@ class PortableContact // Test for Mastodon $orig_version = $version; - $serverret = z_fetch_url($server_url."/api/v1/instance"); + $serverret = Network::curl($server_url."/api/v1/instance"); if ($serverret["success"] && ($serverret["body"] != '')) { $data = json_decode($serverret["body"]); + if (isset($data->version)) { $platform = "Mastodon"; $version = $data->version; @@ -988,6 +1133,9 @@ class PortableContact $info = $data->description; $network = NETWORK_OSTATUS; } + if (!empty($data->stats->user_count)) { + $registered_users = $data->stats->user_count; + } } if (strstr($orig_version.$version, 'Pleroma')) { $platform = 'Pleroma'; @@ -997,7 +1145,7 @@ class PortableContact if (!$failure) { // Test for Hubzilla and Red - $serverret = z_fetch_url($server_url."/siteinfo.json"); + $serverret = Network::curl($server_url."/siteinfo.json"); if ($serverret["success"]) { $data = json_decode($serverret["body"]); if (isset($data->url)) { @@ -1008,6 +1156,9 @@ class PortableContact if (!empty($data->site_name)) { $site_name = $data->site_name; } + if (!empty($data->channels_total)) { + $registered_users = $data->channels_total; + } switch ($data->register_policy) { case "REGISTER_OPEN": $register_policy = REGISTER_OPEN; @@ -1022,7 +1173,7 @@ class PortableContact } } else { // Test for Hubzilla, Redmatrix or Friendica - $serverret = z_fetch_url($server_url."/api/statusnet/config.json"); + $serverret = Network::curl($server_url."/api/statusnet/config.json"); if ($serverret["success"]) { $data = json_decode($serverret["body"]); if (isset($data->site->server)) { @@ -1059,9 +1210,9 @@ class PortableContact $site_name = $data->site->name; - $data->site->closed = poco_to_boolean($data->site->closed); - $data->site->private = poco_to_boolean($data->site->private); - $data->site->inviteonly = poco_to_boolean($data->site->inviteonly); + $data->site->closed = self::toBoolean($data->site->closed); + $data->site->private = self::toBoolean($data->site->private); + $data->site->inviteonly = self::toBoolean($data->site->inviteonly); if (!$data->site->closed && !$data->site->private and $data->site->inviteonly) { $register_policy = REGISTER_APPROVE; @@ -1077,9 +1228,10 @@ class PortableContact // Query statistics.json. Optional package for Diaspora, Friendica and Redmatrix if (!$failure) { - $serverret = z_fetch_url($server_url."/statistics.json"); + $serverret = Network::curl($server_url."/statistics.json"); if ($serverret["success"]) { $data = json_decode($serverret["body"]); + if (isset($data->version)) { $version = $data->version; // Version numbers on statistics.json are presented with additional info, e.g.: @@ -1109,7 +1261,7 @@ class PortableContact // Query nodeinfo. Working for (at least) Diaspora and Friendica. if (!$failure) { - $server = poco_fetch_nodeinfo($server_url); + $server = self::fetchNodeinfo($server_url); if ($server) { $register_policy = $server['register_policy']; @@ -1128,16 +1280,20 @@ class PortableContact if (isset($server['site_name'])) { $site_name = $server['site_name']; } + + if (isset($server['registered-users'])) { + $registered_users = $server['registered-users']; + } } } // Check for noscrape // Friendica servers could be detected as OStatus servers - if (!$failure && in_array($network, array(NETWORK_DFRN, NETWORK_OSTATUS))) { - $serverret = z_fetch_url($server_url."/friendica/json"); + if (!$failure && in_array($network, [NETWORK_DFRN, NETWORK_OSTATUS])) { + $serverret = Network::curl($server_url."/friendica/json"); if (!$serverret["success"]) { - $serverret = z_fetch_url($server_url."/friendika/json"); + $serverret = Network::curl($server_url."/friendika/json"); } if ($serverret["success"]) { @@ -1168,15 +1324,20 @@ class PortableContact } } + // Every server has got at least an admin account + if (!$failure && ($registered_users == 0)) { + $registered_users = 1; + } + if ($possible_failure && !$failure) { $failure = true; } if ($failure) { $last_contact = $orig_last_contact; - $last_failure = datetime_convert(); + $last_failure = DateTimeFormat::utcNow(); } else { - $last_contact = datetime_convert(); + $last_contact = DateTimeFormat::utcNow(); $last_failure = $orig_last_failure; } @@ -1187,47 +1348,25 @@ class PortableContact } // Check again if the server exists - $servers = q("SELECT `nurl` FROM `gserver` WHERE `nurl` = '%s'", dbesc(normalise_link($server_url))); + $found = dba::exists('gserver', ['nurl' => normalise_link($server_url)]); $version = strip_tags($version); $site_name = strip_tags($site_name); $info = strip_tags($info); $platform = strip_tags($platform); - if ($servers) { - q("UPDATE `gserver` SET `url` = '%s', `version` = '%s', `site_name` = '%s', `info` = '%s', `register_policy` = %d, `poco` = '%s', `noscrape` = '%s', - `network` = '%s', `platform` = '%s', `last_contact` = '%s', `last_failure` = '%s' WHERE `nurl` = '%s'", - dbesc($server_url), - dbesc($version), - dbesc($site_name), - dbesc($info), - intval($register_policy), - dbesc($poco), - dbesc($noscrape), - dbesc($network), - dbesc($platform), - dbesc($last_contact), - dbesc($last_failure), - dbesc(normalise_link($server_url)) - ); + $fields = ['url' => $server_url, 'version' => $version, + 'site_name' => $site_name, 'info' => $info, 'register_policy' => $register_policy, + 'poco' => $poco, 'noscrape' => $noscrape, 'network' => $network, + 'platform' => $platform, 'registered-users' => $registered_users, + 'last_contact' => $last_contact, 'last_failure' => $last_failure]; + + if ($found) { + dba::update('gserver', $fields, ['nurl' => normalise_link($server_url)]); } elseif (!$failure) { - q("INSERT INTO `gserver` (`url`, `nurl`, `version`, `site_name`, `info`, `register_policy`, `poco`, `noscrape`, `network`, `platform`, `created`, `last_contact`, `last_failure`) - VALUES ('%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s')", - dbesc($server_url), - dbesc(normalise_link($server_url)), - dbesc($version), - dbesc($site_name), - dbesc($info), - intval($register_policy), - dbesc($poco), - dbesc($noscrape), - dbesc($network), - dbesc($platform), - dbesc(datetime_convert()), - dbesc($last_contact), - dbesc($last_failure), - dbesc(datetime_convert()) - ); + $fields['nurl'] = normalise_link($server_url); + $fields['created'] = DateTimeFormat::utcNow(); + dba::insert('gserver', $fields); } logger("End discovery for server " . $server_url, LOGGER_DEBUG); @@ -1238,12 +1377,18 @@ class PortableContact * @brief Returns a list of all known servers * @return array List of server urls */ - function poco_serverlist() { - $r = q("SELECT `url`, `site_name` AS `displayName`, `network`, `platform`, `version` FROM `gserver` + public static function serverlist() + { + $r = q( + "SELECT `url`, `site_name` AS `displayName`, `network`, `platform`, `version` FROM `gserver` WHERE `network` IN ('%s', '%s', '%s') AND `last_contact` > `last_failure` ORDER BY `last_contact` LIMIT 1000", - dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS)); + dbesc(NETWORK_DFRN), + dbesc(NETWORK_DIASPORA), + dbesc(NETWORK_OSTATUS) + ); + if (!DBM::is_result($r)) { return false; } @@ -1256,8 +1401,9 @@ class PortableContact * * @param string $poco URL to the POCO endpoint */ - function poco_fetch_serverlist($poco) { - $serverret = z_fetch_url($poco."/@server"); + private static function fetchServerlist($poco) + { + $serverret = Network::curl($poco."/@server"); if (!$serverret["success"]) { return; } @@ -1273,13 +1419,14 @@ class PortableContact $r = q("SELECT `nurl` FROM `gserver` WHERE `nurl` = '%s'", dbesc(normalise_link($server_url))); if (!DBM::is_result($r)) { logger("Call server check for server ".$server_url, LOGGER_DEBUG); - Worker::add(PRIORITY_LOW, "discover_poco", "server", $server_url); + Worker::add(PRIORITY_LOW, "DiscoverPoCo", "server", $server_url); } } } - function poco_discover_federation() { - $last = Config::get('poco','last_federation_discovery'); + private static function discoverFederation() + { + $last = Config::get('poco', 'last_federation_discovery'); if ($last) { $next = $last + (24 * 60 * 60); @@ -1289,26 +1436,29 @@ class PortableContact } // Discover Friendica, Hubzilla and Diaspora servers - $serverdata = fetch_url("http://the-federation.info/pods.json"); + $serverdata = Network::fetchUrl("http://the-federation.info/pods.json"); if ($serverdata) { $servers = json_decode($serverdata); foreach ($servers->pods as $server) { - Worker::add(PRIORITY_LOW, "discover_poco", "server", "https://".$server->host); + Worker::add(PRIORITY_LOW, "DiscoverPoCo", "server", "https://".$server->host); } } // Disvover Mastodon servers - if (!Config::get('system','ostatus_disabled')) { - $serverdata = fetch_url("https://instances.mastodon.xyz/instances.json"); - - if ($serverdata) { - $servers = json_decode($serverdata); - - foreach ($servers as $server) { - $url = (is_null($server->https_score) ? 'http' : 'https').'://'.$server->name; - Worker::add(PRIORITY_LOW, "discover_poco", "server", $url); + if (!Config::get('system', 'ostatus_disabled')) { + $accesstoken = Config::get('system', 'instances_social_key'); + if (!empty($accesstoken)) { + $api = 'https://instances.social/api/1.0/instances/list?count=0'; + $header = ['Authorization: Bearer '.$accesstoken]; + $serverdata = Network::curl($api, false, $redirects, ['headers' => $header]); + if ($serverdata['success']) { + $servers = json_decode($serverdata['body']); + foreach ($servers->instances as $server) { + $url = (is_null($server->https_score) ? 'http' : 'https').'://'.$server->name; + Worker::add(PRIORITY_LOW, "DiscoverPoCo", "server", $url); + } } } } @@ -1319,19 +1469,20 @@ class PortableContact //if (!Config::get('system','ostatus_disabled')) { // $serverdata = "http://gstools.org/api/get_open_instances/"; - // $result = z_fetch_url($serverdata); + // $result = Network::curl($serverdata); // if ($result["success"]) { // $servers = json_decode($result["body"]); // foreach($servers->data as $server) - // poco_check_server($server->instance_address); + // self::checkServer($server->instance_address); // } //} - Config::set('poco','last_federation_discovery', time()); + Config::set('poco', 'last_federation_discovery', time()); } - function poco_discover_single_server($id) { + public static function discoverSingleServer($id) + { $r = q("SELECT `poco`, `nurl`, `url`, `network` FROM `gserver` WHERE `id` = %d", intval($id)); if (!DBM::is_result($r)) { return false; @@ -1340,63 +1491,64 @@ class PortableContact $server = $r[0]; // Discover new servers out there (Works from Friendica version 3.5.2) - poco_fetch_serverlist($server["poco"]); + self::fetchServerlist($server["poco"]); // Fetch all users from the other server $url = $server["poco"]."/?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,contactType,generation"; logger("Fetch all users from the server ".$server["url"], LOGGER_DEBUG); - $retdata = z_fetch_url($url); + $retdata = Network::curl($url); if ($retdata["success"]) { $data = json_decode($retdata["body"]); - poco_discover_server($data, 2); - - if (Config::get('system','poco_discovery') > 1) { + self::discoverServer($data, 2); - $timeframe = Config::get('system','poco_discovery_since'); + if (Config::get('system', 'poco_discovery') > 1) { + $timeframe = Config::get('system', 'poco_discovery_since'); if ($timeframe == 0) { $timeframe = 30; } - $updatedSince = date("Y-m-d H:i:s", time() - $timeframe * 86400); + $updatedSince = date(DateTimeFormat::MYSQL, time() - $timeframe * 86400); // Fetch all global contacts from the other server (Not working with Redmatrix and Friendica versions before 3.3) $url = $server["poco"]."/@global?updatedSince=".$updatedSince."&fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,contactType,generation"; $success = false; - $retdata = z_fetch_url($url); + $retdata = Network::curl($url); if ($retdata["success"]) { logger("Fetch all global contacts from the server ".$server["nurl"], LOGGER_DEBUG); - $success = poco_discover_server(json_decode($retdata["body"])); + $success = self::discoverServer(json_decode($retdata["body"])); } - if (!$success && (Config::get('system','poco_discovery') > 2)) { + if (!$success && (Config::get('system', 'poco_discovery') > 2)) { logger("Fetch contacts from users of the server ".$server["nurl"], LOGGER_DEBUG); - poco_discover_server_users($data, $server); + self::discoverServerUsers($data, $server); } } - q("UPDATE `gserver` SET `last_poco_query` = '%s' WHERE `nurl` = '%s'", dbesc(datetime_convert()), dbesc($server["nurl"])); + $fields = ['last_poco_query' => DateTimeFormat::utcNow()]; + dba::update('gserver', $fields, ['nurl' => $server["nurl"]]); return true; } else { // If the server hadn't replied correctly, then force a sanity check - poco_check_server($server["url"], $server["network"], true); + self::checkServer($server["url"], $server["network"], true); // If we couldn't reach the server, we will try it some time later - q("UPDATE `gserver` SET `last_poco_query` = '%s' WHERE `nurl` = '%s'", dbesc(datetime_convert()), dbesc($server["nurl"])); + $fields = ['last_poco_query' => DateTimeFormat::utcNow()]; + dba::update('gserver', $fields, ['nurl' => $server["nurl"]]); return false; } } - function poco_discover($complete = false) { - + public static function discover($complete = false) + { // Update the server list - poco_discover_federation(); + self::discoverFederation(); $no_of_queries = 5; @@ -1410,15 +1562,15 @@ class PortableContact $r = q("SELECT `id`, `url`, `network` FROM `gserver` WHERE `last_contact` >= `last_failure` AND `poco` != '' AND `last_poco_query` < '%s' ORDER BY RAND()", dbesc($last_update)); if (DBM::is_result($r)) { foreach ($r as $server) { - - if (!poco_check_server($server["url"], $server["network"])) { + if (!self::checkServer($server["url"], $server["network"])) { // The server is not reachable? Okay, then we will try it later - q("UPDATE `gserver` SET `last_poco_query` = '%s' WHERE `nurl` = '%s'", dbesc(datetime_convert()), dbesc($server["nurl"])); + $fields = ['last_poco_query' => DateTimeFormat::utcNow()]; + dba::update('gserver', $fields, ['nurl' => $server["nurl"]]); continue; } logger('Update directory from server '.$server['url'].' with ID '.$server['id'], LOGGER_DEBUG); - Worker::add(PRIORITY_LOW, "discover_poco", "update_server_directory", (int)$server['id']); + Worker::add(PRIORITY_LOW, "DiscoverPoCo", "update_server_directory", (int)$server['id']); if (!$complete && (--$no_of_queries == 0)) { break; @@ -1427,8 +1579,8 @@ class PortableContact } } - function poco_discover_server_users($data, $server) { - + private static function discoverServerUsers($data, $server) + { if (!isset($data->entry)) { return; } @@ -1450,16 +1602,16 @@ class PortableContact // Fetch all contacts from a given user from the other server $url = $server["poco"]."/".$username."/?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,contactType,generation"; - $retdata = z_fetch_url($url); + $retdata = Network::curl($url); if ($retdata["success"]) { - poco_discover_server(json_decode($retdata["body"]), 3); + self::discoverServer(json_decode($retdata["body"]), 3); } } } } - function poco_discover_server($data, $default_generation = 0) { - + private static function discoverServer($data, $default_generation = 0) + { if (!isset($data->entry) || !count($data->entry)) { return false; } @@ -1505,7 +1657,7 @@ class PortableContact } if (isset($entry->updated)) { - $updated = date("Y-m-d H:i:s", strtotime($entry->updated)); + $updated = date(DateTimeFormat::MYSQL, strtotime($entry->updated)); } if (isset($entry->network)) { @@ -1524,11 +1676,11 @@ class PortableContact $gender = $entry->gender; } - if(isset($entry->generation) && ($entry->generation > 0)) { + if (isset($entry->generation) && ($entry->generation > 0)) { $generation = ++$entry->generation; } - if(isset($entry->contactType) && ($entry->contactType >= 0)) { + if (isset($entry->contactType) && ($entry->contactType >= 0)) { $contact_type = $entry->contactType; } @@ -1543,7 +1695,7 @@ class PortableContact logger("Store profile ".$profile_url, LOGGER_DEBUG); - $gcontact = array("url" => $profile_url, + $gcontact = ["url" => $profile_url, "name" => $name, "network" => $network, "photo" => $profile_photo, @@ -1554,11 +1706,11 @@ class PortableContact "connect" => $connect_url, "updated" => $updated, "contact-type" => $contact_type, - "generation" => $generation); + "generation" => $generation]; try { - $gcontact = GlobalContact::sanitize($gcontact); - update_gcontact($gcontact); + $gcontact = GContact::sanitize($gcontact); + GContact::update($gcontact); } catch (Exception $e) { logger($e->getMessage(), LOGGER_DEBUG); }