+ * Check for Zot contact
+ *
+ * @param array $webfinger Webfinger data
+ * @param array $data previously probed data
+ *
+ * @return array Zot data
+ * @throws HTTPException\InternalServerErrorException
+ */
+ private static function zot($webfinger, $data)
+ {
+ if (!empty($webfinger["aliases"]) && is_array($webfinger["aliases"])) {
+ foreach ($webfinger["aliases"] as $alias) {
+ if (substr($alias, 0, 5) == 'acct:') {
+ $data["addr"] = substr($alias, 5);
+ }
+ }
+ }
+
+ if (!empty($webfinger["subject"]) && (substr($webfinger["subject"], 0, 5) == "acct:")) {
+ $data["addr"] = substr($webfinger["subject"], 5);
+ }
+
+ $zot_url = '';
+ foreach ($webfinger['links'] as $link) {
+ if (($link['rel'] == 'http://purl.org/zot/protocol') && !empty($link['href'])) {
+ $zot_url = $link['href'];
+ }
+ }
+
+ if (empty($zot_url) && !empty($data['addr']) && !empty(self::$baseurl)) {
+ $condition = ['nurl' => Strings::normaliseLink(self::$baseurl), 'platform' => ['hubzilla']];
+ if (!DBA::exists('gserver', $condition)) {
+ return $data;
+ }
+ $zot_url = self::$baseurl . '/.well-known/zot-info?address=' . $data['addr'];
+ }
+
+ if (empty($zot_url)) {
+ return $data;
+ }
+
+ $data = self::pollZot($zot_url, $data);
+
+ if (!empty($data['url']) && !empty($webfinger['aliases']) && is_array($webfinger['aliases'])) {
+ foreach ($webfinger['aliases'] as $alias) {
+ if (!strstr($alias, '@') && Strings::normaliseLink($alias) != Strings::normaliseLink($data['url'])) {
+ $data['alias'] = $alias;
+ }
+ }
+ }
+
+ return $data;
+ }
+
+ public static function pollZot($url, $data)
+ {
+ $curlResult = Network::curl($url);
+ if ($curlResult->isTimeout()) {
+ return $data;
+ }
+ $content = $curlResult->getBody();
+ if (!$content) {
+ return $data;
+ }
+
+ $json = json_decode($content, true);
+ if (!is_array($json)) {
+ return $data;
+ }
+
+ if (empty($data['network'])) {
+ if (!empty($json['protocols']) && in_array('zot', $json['protocols'])) {
+ $data['network'] = Protocol::ZOT;
+ } elseif (!isset($json['protocols'])) {
+ $data['network'] = Protocol::ZOT;
+ }
+ }
+
+ if (!empty($json['guid']) && empty($data['guid'])) {
+ $data['guid'] = $json['guid'];
+ }
+ if (!empty($json['key']) && empty($data['pubkey'])) {
+ $data['pubkey'] = $json['key'];
+ }
+ if (!empty($json['name'])) {
+ $data['name'] = $json['name'];
+ }
+ if (!empty($json['photo'])) {
+ $data['photo'] = $json['photo'];
+ if (!empty($json['photo_updated'])) {
+ $data['photo'] .= '?rev=' . urlencode($json['photo_updated']);
+ }
+ }
+ if (!empty($json['address'])) {
+ $data['addr'] = $json['address'];
+ }
+ if (!empty($json['url'])) {
+ $data['url'] = $json['url'];
+ }
+ if (!empty($json['connections_url'])) {
+ $data['poco'] = $json['connections_url'];
+ }
+ if (isset($json['searchable'])) {
+ $data['hide'] = !$json['searchable'];
+ }
+ if (!empty($json['public_forum'])) {
+ $data['community'] = $json['public_forum'];
+ $data['account-type'] = Contact::PAGE_COMMUNITY;
+ }
+
+ if (!empty($json['profile'])) {
+ $profile = $json['profile'];
+ if (!empty($profile['description'])) {
+ $data['about'] = $profile['description'];
+ }
+ if (!empty($profile['keywords'])) {
+ $keywords = implode(', ', $profile['keywords']);
+ if (!empty($keywords)) {
+ $data['keywords'] = $keywords;
+ }
+ }
+
+ $loc = [];
+ if (!empty($profile['region'])) {
+ $loc['region'] = $profile['region'];
+ }
+ if (!empty($profile['country'])) {
+ $loc['country-name'] = $profile['country'];
+ }
+ $location = Profile::formatLocation($loc);
+ if (!empty($location)) {
+ $data['location'] = $location;
+ }
+ }
+
+ return $data;
+ }
+
+ /**
+ * Perform a webfinger request.