diff --git a/CHANGELOG b/CHANGELOG index a69cfc015..cbbbee76d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Version 2021.09 (unreleased) Friendica Core Simplified the proxy mechanism. The proxy cache directory (/proxy) can now be removed [annando] + DFRN is now always handled with the Diaspora transport layer. The legacy DFRN transport layer is removed [annando] Version 2021.07 (2021-07-04) Friendica Core diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php deleted file mode 100644 index f5a1d97bf..000000000 --- a/mod/dfrn_notify.php +++ /dev/null @@ -1,122 +0,0 @@ -. - * - * The dfrn notify endpoint - * - * @see PDF with dfrn specs: https://github.com/friendica/friendica/blob/stable/spec/dfrn2.pdf - */ - -use Friendica\App; -use Friendica\Core\Logger; -use Friendica\Core\System; -use Friendica\Database\DBA; -use Friendica\Model\Contact; -use Friendica\Model\Conversation; -use Friendica\Network\HTTPException; -use Friendica\Protocol\DFRN; -use Friendica\Protocol\Diaspora; -use Friendica\Util\Network; - -function dfrn_notify_post(App $a) { - $postdata = Network::postdata(); - - if (empty($_POST) || !empty($postdata)) { - $data = json_decode($postdata); - if (is_object($data)) { - $nick = $a->argv[1] ?? ''; - - $user = DBA::selectFirst('user', [], ['nickname' => $nick, 'account_expired' => false, 'account_removed' => false]); - if (!DBA::isResult($user)) { - throw new \Friendica\Network\HTTPException\InternalServerErrorException(); - } - dfrn_dispatch_private($user, $postdata); - } elseif (!dfrn_dispatch_public($postdata)) { - require_once 'mod/salmon.php'; - salmon_post($a, $postdata); - } - } - throw new HTTPException\BadRequestException(); -} - -function dfrn_dispatch_public($postdata) -{ - $msg = Diaspora::decodeRaw($postdata, '', true); - if (!$msg) { - // We have to fail silently to be able to hand it over to the salmon parser - return false; - } - - // Fetch the corresponding public contact - $contact_id = Contact::getIdForURL($msg['author']); - if (empty($contact_id)) { - Logger::log('Contact not found for address ' . $msg['author']); - System::xmlExit(3, 'Contact ' . $msg['author'] . ' not found'); - } - - $importer = DFRN::getImporter($contact_id); - - // This should never fail - if (empty($importer)) { - Logger::log('Contact not found for address ' . $msg['author']); - System::xmlExit(3, 'Contact ' . $msg['author'] . ' not found'); - } - - Logger::log('Importing post from ' . $msg['author'] . ' with the public envelope.', Logger::DEBUG); - - // Now we should be able to import it - $ret = DFRN::import($msg['message'], $importer, Conversation::PARCEL_DIASPORA_DFRN, Conversation::RELAY); - System::xmlExit($ret, 'Done'); -} - -function dfrn_dispatch_private($user, $postdata) -{ - $msg = Diaspora::decodeRaw($postdata, $user['prvkey'] ?? ''); - if (!$msg) { - System::xmlExit(4, 'Unable to parse message'); - } - - // Check if the user has got this contact - $cid = Contact::getIdForURL($msg['author'], $user['uid']); - if (!$cid) { - // Otherwise there should be a public contact - $cid = Contact::getIdForURL($msg['author']); - if (!$cid) { - Logger::log('Contact not found for address ' . $msg['author']); - System::xmlExit(3, 'Contact ' . $msg['author'] . ' not found'); - } - } - - $importer = DFRN::getImporter($cid, $user['uid']); - - // This should never fail - if (empty($importer)) { - Logger::log('Contact not found for address ' . $msg['author']); - System::xmlExit(3, 'Contact ' . $msg['author'] . ' not found'); - } - - Logger::log('Importing post from ' . $msg['author'] . ' to ' . $user['nickname'] . ' with the private envelope.', Logger::DEBUG); - - // Now we should be able to import it - $ret = DFRN::import($msg['message'], $importer, Conversation::PARCEL_DIASPORA_DFRN, Conversation::PUSH); - System::xmlExit($ret, 'Done'); -} - -function dfrn_notify_content(App $a) { - throw new HTTPException\NotFoundException(); -} diff --git a/src/Module/DFRN/Notify.php b/src/Module/DFRN/Notify.php new file mode 100644 index 000000000..eb0434897 --- /dev/null +++ b/src/Module/DFRN/Notify.php @@ -0,0 +1,122 @@ +. + * + */ + +namespace Friendica\Module\DFRN; + +use Friendica\BaseModule; +use Friendica\Core\Logger; +use Friendica\Core\System; +use Friendica\Model\Contact; +use Friendica\Model\Conversation; +use Friendica\Model\User; +use Friendica\Protocol\DFRN; +use Friendica\Protocol\Diaspora; +use Friendica\Util\Network; +use Friendica\Network\HTTPException; + +/** + * DFRN Notify + */ +class Notify extends BaseModule +{ + public static function post(array $parameters = []) + { + $postdata = Network::postdata(); + + if (empty($postdata)) { + throw new HTTPException\BadRequestException(); + } + + $data = json_decode($postdata); + if (is_object($data) && !empty($parameters['nickname'])) { + $user = User::getByNickname($parameters['nickname']); + if (empty($user)) { + throw new \Friendica\Network\HTTPException\InternalServerErrorException(); + } + self::dispatchPrivate($user, $postdata); + } elseif (!self::dispatchPublic($postdata)) { + require_once 'mod/salmon.php'; + salmon_post($a, $postdata); + } + } + + private static function dispatchPublic($postdata) + { + $msg = Diaspora::decodeRaw($postdata, '', true); + if (!$msg) { + // We have to fail silently to be able to hand it over to the salmon parser + return false; + } + + // Fetch the corresponding public contact + $contact_id = Contact::getIdForURL($msg['author']); + if (empty($contact_id)) { + Logger::notice('Contact not found', ['address' => $msg['author']]); + System::xmlExit(3, 'Contact ' . $msg['author'] . ' not found'); + } + + // Fetch the importer (Mixture of sender and receiver) + $importer = DFRN::getImporter($contact_id); + if (empty($importer)) { + Logger::notice('Importer contact not found', ['address' => $msg['author']]); + System::xmlExit(3, 'Contact ' . $msg['author'] . ' not found'); + } + + Logger::info('Importing post with the public envelope.', ['transmitter' => $msg['author']]); + + // Now we should be able to import it + $ret = DFRN::import($msg['message'], $importer, Conversation::PARCEL_DIASPORA_DFRN, Conversation::RELAY); + System::xmlExit($ret, 'Done'); + } + + private static function dispatchPrivate($user, $postdata) + { + $msg = Diaspora::decodeRaw($postdata, $user['prvkey'] ?? ''); + if (!$msg) { + System::xmlExit(4, 'Unable to parse message'); + } + + // Fetch the contact + $contact = Contact::getByURLForUser($msg['author'], $user['uid'], null, ['id', 'blocked', 'pending']); + if (empty($contact['id'])) { + Logger::notice('Contact not found', ['address' => $msg['author']]); + System::xmlExit(3, 'Contact ' . $msg['author'] . ' not found'); + } + + if ($contact['pending'] || $contact['blocked']) { + Logger::notice('Contact is blocked or pending', ['address' => $msg['author'], 'contact' => $contact]); + System::xmlExit(3, 'Contact ' . $msg['author'] . ' not found'); + } + + // Fetch the importer (Mixture of sender and receiver) + $importer = DFRN::getImporter($contact['id'], $user['uid']); + if (empty($importer)) { + Logger::notice('Importer contact not found for user', ['uid' => $user['uid'], 'cid' => $contact['id'], 'address' => $msg['author']]); + System::xmlExit(3, 'Contact ' . $msg['author'] . ' not found'); + } + + Logger::info('Importing post with the private envelope.', ['transmitter' => $msg['author'], 'receiver' => $user['nickname']]); + + // Now we should be able to import it + $ret = DFRN::import($msg['message'], $importer, Conversation::PARCEL_DIASPORA_DFRN, Conversation::PUSH); + System::xmlExit($ret, 'Done'); + } +} diff --git a/mod/dfrn_poll.php b/src/Module/DFRN/Poll.php similarity index 79% rename from mod/dfrn_poll.php rename to src/Module/DFRN/Poll.php index 7fd3abbd9..d9c7884ec 100644 --- a/mod/dfrn_poll.php +++ b/src/Module/DFRN/Poll.php @@ -19,18 +19,21 @@ * */ -use Friendica\App; -use Friendica\Protocol\OStatus; -use Friendica\Network\HTTPException; +namespace Friendica\Module\DFRN; -function dfrn_poll_init(App $a) +use Friendica\BaseModule; +use Friendica\Protocol\OStatus; + +/** + * DFRN Poll + */ +class Poll extends BaseModule { - if ($a->argc > 1) { - $nickname = $a->argv[1]; + public static function rawContent(array $parameters = []) + { header("Content-type: application/atom+xml"); $last_update = $_GET['last_update'] ?? ''; - echo OStatus::feed($nickname, $last_update, 10); + echo OStatus::feed($parameters['nickname'], $last_update, 10); exit(); } - throw new HTTPException\BadRequestException(); } diff --git a/static/routes.config.php b/static/routes.config.php index 6bc17c414..dfa7dad18 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -245,11 +245,12 @@ return [ '/hovercard' => [Module\Contact\Hovercard::class, [R::GET]], ], - '/credits' => [Module\Credits::class, [R::GET]], - - '/delegation'=> [Module\Delegation::class, [R::GET, R::POST]], - '/dirfind' => [Module\Search\Directory::class, [R::GET]], - '/directory' => [Module\Directory::class, [R::GET]], + '/credits' => [Module\Credits::class, [R::GET]], + '/delegation' => [Module\Delegation::class, [R::GET, R::POST]], + '/dfrn_notify[/{nickname}]' => [Module\DFRN\Notify::class, [R::POST]], + '/dfrn_poll/{nickname}' => [Module\DFRN\Poll::class, [R::GET]], + '/dirfind' => [Module\Search\Directory::class, [R::GET]], + '/directory' => [Module\Directory::class, [R::GET]], '/feed' => [ '/{nickname}' => [Module\Feed::class, [R::GET]],