diff --git a/mod/_well_known.php b/mod/_well_known.php index c5bee3fdad..782dc7a1b1 100644 --- a/mod/_well_known.php +++ b/mod/_well_known.php @@ -70,9 +70,11 @@ function wk_social_relay() } $relay = [ - "subscribe" => $subscribe, - "scope" => $scope, - "tags" => $taglist + 'subscribe' => $subscribe, + 'scope' => $scope, + 'tags' => $taglist, + 'protocols' => ['diaspora' => System::baseUrl() . '/receive/public', + 'dfrn' => System::baseUrl() . '/dfrn_notify'] ]; header('Content-type: application/json; charset=utf-8'); diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php index e2f0336db6..10a0a792a7 100644 --- a/mod/dfrn_notify.php +++ b/mod/dfrn_notify.php @@ -208,7 +208,7 @@ function dfrn_dispatch_public($postdata) $contact = Contact::getDetailsByAddr($msg['author'], 0); if (!$contact) { logger('Contact not found for address ' . $msg['author']); - System::xmlExit(3, 'Contact not found'); + System::xmlExit(3, 'Contact ' . $msg['author'] . ' not found'); } // We now have some contact, so we fetch it @@ -222,7 +222,7 @@ function dfrn_dispatch_public($postdata) // This should never fail if (!DBM::is_result($importer)) { logger('Contact not found for address ' . $msg['author']); - System::xmlExit(3, 'Contact not found'); + System::xmlExit(3, 'Contact ' . $msg['author'] . ' not found'); } logger('Importing post from ' . $msg['author'] . ' with the public envelope.', LOGGER_DEBUG); @@ -246,7 +246,7 @@ function dfrn_dispatch_private($user, $postdata) $cid = Contact::getIdForURL($msg['author']); if (!$cid) { logger('Contact not found for address ' . $msg['author']); - System::xmlExit(3, 'Contact not found'); + System::xmlExit(3, 'Contact ' . $msg['author'] . ' not found'); } } @@ -259,7 +259,7 @@ function dfrn_dispatch_private($user, $postdata) // This should never fail if (!DBM::is_result($importer)) { logger('Contact not found for address ' . $msg['author']); - System::xmlExit(3, 'Contact not found'); + System::xmlExit(3, 'Contact ' . $msg['author'] . ' not found'); } // Set the user id. This is important if this is a public contact diff --git a/src/Network/Probe.php b/src/Network/Probe.php index d14c623e86..6e7e21d1e9 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -444,6 +444,11 @@ class Probe $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; + } + dba::update('contact', $fields, $condition, $old_fields); } } diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index ad7658a764..63bd2f83bc 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -1426,9 +1426,12 @@ class DFRN Contact::markForArchival($contact); return -22; } + $pubkey = $fcontact['pubkey']; + } else { + $pubkey = ''; } - $envelope = Diaspora::buildMessage($atom, $owner, $contact, $owner['uprvkey'], $fcontact['pubkey'], $public_batch); + $envelope = Diaspora::buildMessage($atom, $owner, $contact, $owner['uprvkey'], $pubkey, $public_batch); // Create the endpoint for public posts. This is some WIP and should later be added to the probing if ($public_batch && empty($contact["batch"])) { diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index f4a649b51c..b25809a0e5 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -134,55 +134,58 @@ class Diaspora */ private static function getRelayContact($server_url) { - $batch = $server_url . '/receive/public'; - $fields = ['batch', 'id', 'name', 'network', 'archive', 'blocked']; // Fetch the relay contact - $condition = ['uid' => 0, 'network' => NETWORK_DIASPORA, 'batch' => $batch, + $condition = ['uid' => 0, 'nurl' => normalise_link($server_url), 'contact-type' => ACCOUNT_TYPE_RELAY]; $contact = dba::selectFirst('contact', $fields, $condition); - // If there is nothing found, we check if there is some unmarked relay - // This code segment can be removed before the release 2018-05 - if (!DBM::is_result($contact)) { - $condition = ['uid' => 0, 'network' => NETWORK_DIASPORA, 'batch' => $batch, - 'name' => 'relay', 'nick' => 'relay', 'url' => $server_url]; - $contact = dba::selectFirst('contact', $fields, $condition); - - if (DBM::is_result($contact)) { - // Mark the relay account as a relay account - $fields = ['contact-type' => ACCOUNT_TYPE_RELAY]; - dba::update('contact', $fields, ['id' => $contact['id']]); - } - } if (DBM::is_result($contact)) { if ($contact['archive'] || $contact['blocked']) { return false; } return $contact; } else { - $fields = ['uid' => 0, 'created' => DateTimeFormat::utcNow(), - 'name' => 'relay', 'nick' => 'relay', - 'url' => $server_url, 'nurl' => normalise_link($server_url), - 'batch' => $batch, 'network' => NETWORK_DIASPORA, - 'rel' => CONTACT_IS_FOLLOWER, 'blocked' => false, - 'contact-type' => ACCOUNT_TYPE_RELAY, - 'pending' => false, 'writable' => true]; - dba::insert('contact', $fields); + self::setRelayContact($server_url); - $fields = ['batch', 'id', 'name', 'network']; $contact = dba::selectFirst('contact', $fields, $condition); if (DBM::is_result($contact)) { return $contact; } - } // It should never happen that we arrive here return []; } + /** + * @brief Update or insert a relay contact + * + * @param string $server_url The url of the server + * @param array $network_fields Optional network specific fields + */ + public static function setRelayContact($server_url, $network_fields = []) + { + $fields = ['created' => DateTimeFormat::utcNow(), + 'name' => 'relay', 'nick' => 'relay', + 'url' => $server_url, 'network' => NETWORK_DIASPORA, + 'batch' => $server_url . '/receive/public', + 'rel' => CONTACT_IS_FOLLOWER, 'blocked' => false, + 'pending' => false, 'writable' => true]; + + $fields = array_merge($fields, $network_fields); + + $condition = ['uid' => 0, 'nurl' => normalise_link($server_url), + 'contact-type' => ACCOUNT_TYPE_RELAY]; + + if (dba::exists('contact', $condition)) { + unset($fields['created']); + } + + dba::update('contact', $fields, $condition, true); + } + /** * @brief Return a list of participating contacts for a thread * diff --git a/src/Protocol/PortableContact.php b/src/Protocol/PortableContact.php index 06c2636aca..672956ffb9 100644 --- a/src/Protocol/PortableContact.php +++ b/src/Protocol/PortableContact.php @@ -18,6 +18,7 @@ use Friendica\Model\Profile; use Friendica\Network\Probe; use Friendica\Util\DateTimeFormat; use Friendica\Util\Network; +use Friendica\Protocol\Diaspora; use dba; use DOMDocument; use DOMXPath; @@ -1429,6 +1430,20 @@ class PortableContact dba::insert('gserver-tag', ['gserver-id' => $gserver['id'], 'tag' => $tag]); } } + + // Create or update the relay contact + $fields = []; + if (isset($data->protocols)) { + if (isset($data->protocols->diaspora)) { + $fields['network'] = NETWORK_DIASPORA; + $fields['batch'] = $data->protocols->diaspora; + } + if (isset($data->protocols->dfrn)) { + $fields['network'] = NETWORK_DFRN; + $fields['batch'] = $data->protocols->dfrn; + } + } + Diaspora::setRelayContact($server_url, $fields); } /** diff --git a/src/Worker/Delivery.php b/src/Worker/Delivery.php index f874e5f230..04e08edf52 100644 --- a/src/Worker/Delivery.php +++ b/src/Worker/Delivery.php @@ -199,7 +199,7 @@ class Delivery extends BaseObject */ private static function deliverDFRN($cmd, $contact, $owner, $items, $target_item, $public_message, $top_level, $followup) { - logger('Deliver ' . $target_item["guid"] . ' via DFRN to ' . $contact['addr']); + logger('Deliver ' . $target_item["guid"] . ' via DFRN to ' . (empty($contact['addr']) ? $contact['url'] : $contact['addr'])); if ($cmd == self::MAIL) { $item = $target_item; @@ -270,11 +270,18 @@ class Delivery extends BaseObject // We don't have a relationship with contacts on a public post. // Se we transmit with the new method and via Diaspora as a fallback - if ($items[0]['uid'] == 0) { + if (($items[0]['uid'] == 0) || ($contact['uid'] == 0)) { // Transmit in public if it's a relay post $public_dfrn = ($contact['contact-type'] == ACCOUNT_TYPE_RELAY); $deliver_status = DFRN::transmit($owner, $contact, $atom, $public_dfrn); + + // We never spool failed relay deliveries + if ($public_dfrn) { + logger('Relay delivery to ' . $contact["url"] . ' with guid ' . $target_item["guid"] . ' returns ' . $deliver_status); + return; + } + if (($deliver_status < 200) || ($deliver_status > 299)) { // Transmit via Diaspora if not possible via Friendica self::deliverDiaspora($cmd, $contact, $owner, $items, $target_item, $public_message, $top_level, $followup);