mirror of
https://github.com/friendica/friendica
synced 2025-04-22 08:30:10 +00:00
OStatus support removed
This commit is contained in:
parent
eb066b258d
commit
e8a3be6820
87 changed files with 773 additions and 4383 deletions
|
@ -111,7 +111,6 @@ class Site extends BaseAdmin
|
|||
$poco_local_search = !empty($_POST['poco_local_search']);
|
||||
$nodeinfo = !empty($_POST['nodeinfo']);
|
||||
$mail_enabled = !empty($_POST['mail_enabled']);
|
||||
$ostatus_enabled = !empty($_POST['ostatus_enabled']);
|
||||
$diaspora_enabled = !empty($_POST['diaspora_enabled']);
|
||||
$force_ssl = !empty($_POST['force_ssl']);
|
||||
$show_help = !empty($_POST['show_help']);
|
||||
|
@ -280,7 +279,6 @@ class Site extends BaseAdmin
|
|||
$transactionConfig->set('system', 'proxy' , $proxy);
|
||||
$transactionConfig->set('system', 'curl_timeout' , $timeout);
|
||||
$transactionConfig->set('system', 'imap_disabled' , !$mail_enabled && function_exists('imap_open'));
|
||||
$transactionConfig->set('system', 'ostatus_disabled' , !$ostatus_enabled);
|
||||
$transactionConfig->set('system', 'diaspora_enabled' , $diaspora_enabled);
|
||||
|
||||
$transactionConfig->set('config', 'private_addons' , $private_addons);
|
||||
|
@ -531,7 +529,6 @@ class Site extends BaseAdmin
|
|||
'$mail_able' => function_exists('imap_open'),
|
||||
'$mail_enabled' => ['mail_enabled', DI::l10n()->t('Enable Mail support'), !DI::config()->get('system', 'imap_disabled', !function_exists('imap_open')), DI::l10n()->t('Enable built-in mail support to poll IMAP folders and to reply via mail.')],
|
||||
'$mail_not_able' => DI::l10n()->t('Mail support can\'t be enabled because the PHP IMAP module is not installed.'),
|
||||
'$ostatus_enabled' => ['ostatus_enabled', DI::l10n()->t('Enable OStatus support'), !DI::config()->get('system', 'ostatus_disabled'), DI::l10n()->t('Enable built-in OStatus (StatusNet, GNU Social etc.) compatibility. All communications in OStatus are public.')],
|
||||
'$diaspora_able' => $diaspora_able,
|
||||
'$diaspora_not_able' => DI::l10n()->t('Diaspora support can\'t be enabled because Friendica was installed into a sub directory.'),
|
||||
'$diaspora_enabled' => ['diaspora_enabled', DI::l10n()->t('Enable Diaspora support'), DI::config()->get('system', 'diaspora_enabled', $diaspora_able), DI::l10n()->t('Enable built-in Diaspora network compatibility for communicating with diaspora servers.')],
|
||||
|
@ -562,7 +559,7 @@ class Site extends BaseAdmin
|
|||
'$dbclean' => ['dbclean', DI::l10n()->t('Clean database'), DI::config()->get('system', 'dbclean'), DI::l10n()->t('Remove old remote items, orphaned database records and old content from some other helper tables.')],
|
||||
'$dbclean_expire_days' => ['dbclean_expire_days', DI::l10n()->t('Lifespan of remote items'), DI::config()->get('system', 'dbclean-expire-days'), DI::l10n()->t('When the database cleanup is enabled, this defines the days after which remote items will be deleted. Own items, and marked or filed items are always kept. 0 disables this behaviour.')],
|
||||
'$dbclean_unclaimed' => ['dbclean_unclaimed', DI::l10n()->t('Lifespan of unclaimed items'), DI::config()->get('system', 'dbclean-expire-unclaimed'), DI::l10n()->t('When the database cleanup is enabled, this defines the days after which unclaimed remote items (mostly content from the relay) will be deleted. Default value is 90 days. Defaults to the general lifespan value of remote items if set to 0.')],
|
||||
'$dbclean_expire_conv' => ['dbclean_expire_conv', DI::l10n()->t('Lifespan of raw conversation data'), DI::config()->get('system', 'dbclean_expire_conversation'), DI::l10n()->t('The conversation data is used for ActivityPub and OStatus, as well as for debug purposes. It should be safe to remove it after 14 days, default is 90 days.')],
|
||||
'$dbclean_expire_conv' => ['dbclean_expire_conv', DI::l10n()->t('Lifespan of raw conversation data'), DI::config()->get('system', 'dbclean_expire_conversation'), DI::l10n()->t('The conversation data is used for ActivityPub, as well as for debug purposes. It should be safe to remove it after 14 days, default is 90 days.')],
|
||||
'$max_comments' => ['max_comments', DI::l10n()->t('Maximum numbers of comments per post'), DI::config()->get('system', 'max_comments'), DI::l10n()->t('How much comments should be shown for each post? Default value is 100.')],
|
||||
'$max_display_comments' => ['max_display_comments', DI::l10n()->t('Maximum numbers of comments per post on the display page'), DI::config()->get('system', 'max_display_comments'), DI::l10n()->t('How many comments should be shown on the single view for each post? Default value is 1000.')],
|
||||
'$itemspage_network' => ['itemspage_network', DI::l10n()->t('Items per page'), DI::config()->get('system', 'itemspage_network'), DI::l10n()->t('Number of items per page in stream pages (network, community, profile/contact statuses, search).')],
|
||||
|
|
|
@ -140,8 +140,8 @@ class Search extends BaseApi
|
|||
|
||||
if (substr($q, 0, 1) == '#') {
|
||||
$condition = ["`name` = ? AND (`uid` = ? OR (`uid` = ? AND NOT `global`))
|
||||
AND (`network` IN (?, ?, ?, ?) OR (`uid` = ? AND `uid` != ?))",
|
||||
substr($q, 1), 0, $uid, Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS, $uid, 0];
|
||||
AND (`network` IN (?, ?, ?) OR (`uid` = ? AND `uid` != ?))",
|
||||
substr($q, 1), 0, $uid, Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, $uid, 0];
|
||||
$table = 'tag-search-view';
|
||||
} else {
|
||||
$q = Post\Engagement::escapeKeywords($q);
|
||||
|
|
|
@ -56,8 +56,8 @@ class Tag extends BaseApi
|
|||
$params = ['order' => ['uri-id' => true], 'limit' => $request['limit']];
|
||||
|
||||
$condition = ["`name` = ? AND (`uid` = ? OR (`uid` = ? AND NOT `global`))
|
||||
AND (`network` IN (?, ?, ?, ?) OR (`uid` = ? AND `uid` != ?))",
|
||||
$this->parameters['hashtag'], 0, $uid, Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS, $uid, 0];
|
||||
AND (`network` IN (?, ?, ?) OR (`uid` = ? AND `uid` != ?))",
|
||||
$this->parameters['hashtag'], 0, $uid, Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, $uid, 0];
|
||||
|
||||
if ($request['local']) {
|
||||
$condition = DBA::mergeConditions($condition, ["`uri-id` IN (SELECT `uri-id` FROM `post-user` WHERE `origin`)"]);
|
||||
|
|
|
@ -118,21 +118,10 @@ class Contact extends BaseModule
|
|||
return;
|
||||
}
|
||||
|
||||
if ($contact['network'] == Protocol::OSTATUS) {
|
||||
$result = Model\Contact::createFromProbeForUser($contact['uid'], $contact['url'], $contact['network']);
|
||||
|
||||
if ($result['success']) {
|
||||
Model\Contact::update(['subhub' => 1], ['id' => $contact_id]);
|
||||
}
|
||||
|
||||
// pull feed and consume it, which should subscribe to the hub.
|
||||
Worker::add(Worker::PRIORITY_HIGH, 'OnePoll', $contact_id, 'force');
|
||||
} else {
|
||||
try {
|
||||
UpdateContact::add(Worker::PRIORITY_HIGH, $contact_id);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
Logger::notice($e->getMessage(), ['contact' => $contact]);
|
||||
}
|
||||
try {
|
||||
UpdateContact::add(Worker::PRIORITY_HIGH, $contact_id);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
Logger::notice($e->getMessage(), ['contact' => $contact]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -125,11 +125,6 @@ class Follow extends BaseModule
|
|||
$submit = '';
|
||||
}
|
||||
|
||||
if (($protocol == Protocol::OSTATUS) && $this->config->get('system', 'ostatus_disabled')) {
|
||||
$this->sysMessages->addNotice($this->t("OStatus support is disabled. Contact can't be added."));
|
||||
$submit = '';
|
||||
}
|
||||
|
||||
if ($protocol == Protocol::MAIL) {
|
||||
$contact['url'] = $contact['addr'];
|
||||
}
|
||||
|
|
|
@ -294,7 +294,7 @@ class Profile extends BaseModule
|
|||
}
|
||||
$lblsuggest = (($contact['network'] === Protocol::DFRN) ? $this->t('Suggest friends') : '');
|
||||
|
||||
$poll_enabled = in_array($contact['network'], [Protocol::DFRN, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL]);
|
||||
$poll_enabled = in_array($contact['network'], [Protocol::DFRN, Protocol::FEED, Protocol::MAIL]);
|
||||
|
||||
$nettype = $this->t('Network type: %s', ContactSelector::networkToName($contact['network'], $contact['url'], $contact['protocol'], $contact['gsid']));
|
||||
|
||||
|
@ -460,7 +460,7 @@ class Profile extends BaseModule
|
|||
*/
|
||||
private function getContactActions(array $contact, LocalRelationship\Entity\LocalRelationship $localRelationship): array
|
||||
{
|
||||
$poll_enabled = in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL]);
|
||||
$poll_enabled = in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::FEED, Protocol::MAIL]);
|
||||
$contact_actions = [];
|
||||
|
||||
$formSecurityToken = self::getFormSecurityToken('contact_action');
|
||||
|
|
|
@ -51,7 +51,6 @@ class Notify extends BaseModule
|
|||
{
|
||||
$msg = Diaspora::decodeRaw($postdata, '', true);
|
||||
if (!is_array($msg)) {
|
||||
// We have to fail silently to be able to hand it over to the salmon parser
|
||||
$this->logger->warning('Diaspora::decodeRaw() has failed for some reason.', ['post-data' => $postdata]);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024, the Friendica project
|
||||
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
namespace Friendica\Module\DFRN;
|
||||
|
||||
use Friendica\BaseModule;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Module\Response;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Protocol\OStatus;
|
||||
|
||||
/**
|
||||
* DFRN Poll
|
||||
*/
|
||||
class Poll extends BaseModule
|
||||
{
|
||||
protected function rawContent(array $request = [])
|
||||
{
|
||||
$owner = User::getByNickname(
|
||||
$this->parameters['nickname'] ?? '',
|
||||
['nickname', 'blocked', 'account_expired', 'account_removed']
|
||||
);
|
||||
if (!$owner || $owner['account_expired'] || $owner['account_removed']) {
|
||||
throw new HTTPException\NotFoundException($this->t('User not found.'));
|
||||
}
|
||||
|
||||
if ($owner['blocked']) {
|
||||
throw new HTTPException\UnauthorizedException($this->t('Access to this profile has been restricted.'));
|
||||
}
|
||||
|
||||
$last_update = $request['last_update'] ?? '';
|
||||
$this->httpExit(OStatus::feed($owner['nickname'], $last_update, 10) ?? '', Response::TYPE_ATOM);
|
||||
}
|
||||
}
|
|
@ -55,11 +55,11 @@ class HCard extends BaseModule
|
|||
$uri = urlencode('acct:' . $profile['nickname'] . '@' . DI::baseUrl()->getHost() . (DI::baseUrl()->getPath() ? '/' . DI::baseUrl()->getPath() : ''));
|
||||
|
||||
$page['htmlhead'] .= '<meta name="dfrn-global-visibility" content="' . ($profile['net-publish'] ? 'true' : 'false') . '" />' . "\r\n";
|
||||
$page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $baseUrl . '/dfrn_poll/' . $nickname . '" />' . "\r\n";
|
||||
$page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $profile['poll'] . '" />' . "\r\n";
|
||||
$page['htmlhead'] .= '<link rel="lrdd" type="application/xrd+xml" href="' . $baseUrl . '/xrd/?uri=' . $uri . '" />' . "\r\n";
|
||||
header('Link: <' . $baseUrl . '/xrd/?uri=' . $uri . '>; rel="lrdd"; type="application/xrd+xml"', false);
|
||||
|
||||
foreach (['request', 'confirm', 'notify', 'poll'] as $dfrn) {
|
||||
foreach (['notify', 'poll'] as $dfrn) {
|
||||
$page['htmlhead'] .= "<link rel=\"dfrn-{$dfrn}\" href=\"" . $baseUrl . "/dfrn_{$dfrn}/{$nickname}\" />\r\n";
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ class NoScrape extends BaseModule
|
|||
'account-type' => $owner['account-type'],
|
||||
];
|
||||
|
||||
$dfrn_pages = ['request', 'confirm', 'notify', 'poll'];
|
||||
$dfrn_pages = ['notify', 'poll'];
|
||||
foreach ($dfrn_pages as $dfrn) {
|
||||
$json_info["dfrn-{$dfrn}"] = DI::baseUrl() . "/dfrn_{$dfrn}/{$which}";
|
||||
}
|
||||
|
|
|
@ -61,11 +61,6 @@ class NodeInfo110 extends BaseModule
|
|||
$nodeinfo['protocols']['outbound'][] = 'diaspora';
|
||||
}
|
||||
|
||||
if (empty($this->config->get('system', 'ostatus_disabled'))) {
|
||||
$nodeinfo['protocols']['inbound'][] = 'gnusocial';
|
||||
$nodeinfo['protocols']['outbound'][] = 'gnusocial';
|
||||
}
|
||||
|
||||
$nodeinfo['metadata']['protocols'] = $nodeinfo['protocols'];
|
||||
$nodeinfo['metadata']['protocols']['outbound'][] = 'atom1.0';
|
||||
$nodeinfo['metadata']['protocols']['inbound'][] = 'atom1.0';
|
||||
|
|
|
@ -54,10 +54,6 @@ class NodeInfo120 extends BaseModule
|
|||
$nodeinfo['protocols'][] = 'diaspora';
|
||||
}
|
||||
|
||||
if (empty($this->config->get('system', 'ostatus_disabled'))) {
|
||||
$nodeinfo['protocols'][] = 'ostatus';
|
||||
}
|
||||
|
||||
$nodeinfo['services']['inbound'][] = 'atom1.0';
|
||||
$nodeinfo['services']['inbound'][] = 'rss2.0';
|
||||
$nodeinfo['services']['outbound'][] = 'atom1.0';
|
||||
|
|
|
@ -56,10 +56,6 @@ class NodeInfo121 extends BaseModule
|
|||
$nodeinfo['protocols'][] = 'diaspora';
|
||||
}
|
||||
|
||||
if (empty($this->config->get('system', 'ostatus_disabled'))) {
|
||||
$nodeinfo['protocols'][] = 'ostatus';
|
||||
}
|
||||
|
||||
$nodeinfo['services']['inbound'][] = 'atom1.0';
|
||||
$nodeinfo['services']['inbound'][] = 'rss2.0';
|
||||
$nodeinfo['services']['outbound'][] = 'atom1.0';
|
||||
|
|
|
@ -57,10 +57,6 @@ class NodeInfo122 extends BaseModule
|
|||
$nodeinfo['protocols'][] = 'diaspora';
|
||||
}
|
||||
|
||||
if (empty($this->config->get('system', 'ostatus_disabled'))) {
|
||||
$nodeinfo['protocols'][] = 'ostatus';
|
||||
}
|
||||
|
||||
$nodeinfo['services']['inbound'][] = 'atom1.0';
|
||||
$nodeinfo['services']['inbound'][] = 'rss2.0';
|
||||
$nodeinfo['services']['outbound'][] = 'atom1.0';
|
||||
|
|
|
@ -52,10 +52,6 @@ class NodeInfo210 extends BaseModule
|
|||
$nodeinfo['protocols'][] = 'diaspora';
|
||||
}
|
||||
|
||||
if (empty($this->config->get('system', 'ostatus_disabled'))) {
|
||||
$nodeinfo['protocols'][] = 'ostatus';
|
||||
}
|
||||
|
||||
$nodeinfo['services']['inbound'][] = 'atom1.0';
|
||||
$nodeinfo['services']['inbound'][] = 'rss2.0';
|
||||
$nodeinfo['services']['outbound'][] = 'atom1.0';
|
||||
|
|
|
@ -1,148 +0,0 @@
|
|||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024, the Friendica project
|
||||
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
namespace Friendica\Module\OStatus;
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\GServer;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\Post;
|
||||
use Friendica\Module\Response;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Protocol\OStatus;
|
||||
use Friendica\Util\Network;
|
||||
use Friendica\Util\Profiler;
|
||||
use Friendica\Util\Strings;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class PubSub extends \Friendica\BaseModule
|
||||
{
|
||||
/** @var Database */
|
||||
private $database;
|
||||
/** @var App\Request */
|
||||
private $request;
|
||||
|
||||
public function __construct(App\Request $request, Database $database, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = [])
|
||||
{
|
||||
parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
|
||||
|
||||
$this->database = $database;
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
$xml = Network::postdata();
|
||||
|
||||
$this->logger->info('Feed arrived.', ['from' => $this->request->getRemoteAddress(), 'for' => $this->args->getCommand(), 'user-agent' => $this->server['HTTP_USER_AGENT']]);
|
||||
$this->logger->debug('Data stream.', ['xml' => $xml]);
|
||||
$this->logger->debug('Got request data.', ['request' => $request]);
|
||||
|
||||
$nickname = $this->parameters['nickname'] ?? '';
|
||||
$contact_id = $this->parameters['cid'] ?? 0;
|
||||
|
||||
$importer = $this->database->selectFirst('user', [], ['nickname' => $nickname, 'verified' => true, 'blocked' => false, 'account_removed' => false, 'account_expired' => false]);
|
||||
if (!$importer) {
|
||||
throw new HTTPException\OKException();
|
||||
}
|
||||
|
||||
$condition = ['id' => $contact_id, 'uid' => $importer['uid'], 'subhub' => true, 'blocked' => false];
|
||||
$contact = $this->database->selectFirst('contact', [], $condition);
|
||||
if (!$contact) {
|
||||
$author = OStatus::salmonAuthor($xml, $importer);
|
||||
if (!empty($author['contact-id'])) {
|
||||
$condition = ['id' => $author['contact-id'], 'uid' => $importer['uid'], 'subhub' => true, 'blocked' => false];
|
||||
$contact = $this->database->selectFirst('contact', [], $condition);
|
||||
$this->logger->notice('No record found for nickname, using author entry instead.', ['nickname' => $nickname, 'contact-id' => $contact_id, 'author-contact-id' => $author['contact-id']]);
|
||||
}
|
||||
|
||||
if (!$contact) {
|
||||
$this->logger->notice("Contact wasn't found - ignored.", ['author-link' => $author['author-link'], 'contact-id' => $contact_id, 'nickname' => $nickname, 'xml' => $xml]);
|
||||
throw new HTTPException\OKException();
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($contact['gsid'])) {
|
||||
GServer::setProtocol($contact['gsid'], Post\DeliveryData::OSTATUS);
|
||||
}
|
||||
|
||||
if (!in_array($contact['rel'], [Contact::SHARING, Contact::FRIEND]) && ($contact['network'] != Protocol::FEED)) {
|
||||
$this->logger->notice('Contact is not expected to share with us - ignored.', ['contact-id' => $contact['id']]);
|
||||
throw new HTTPException\OKException();
|
||||
}
|
||||
|
||||
// We only import feeds from OStatus here
|
||||
if (!in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::OSTATUS])) {
|
||||
$this->logger->warning('Unexpected network', ['contact' => $contact, 'network' => $contact['network']]);
|
||||
throw new HTTPException\OKException();
|
||||
}
|
||||
|
||||
$this->logger->info('Import item from Contact.', ['nickname' => $nickname, 'contact-nickname' => $contact['nick'], 'contact-id' => $contact['id']]);
|
||||
$feedhub = '';
|
||||
Item::incrementOutbound(Protocol::OSTATUS);
|
||||
OStatus::import($xml, $importer, $contact, $feedhub);
|
||||
|
||||
throw new HTTPException\OKException();
|
||||
}
|
||||
|
||||
protected function rawContent(array $request = [])
|
||||
{
|
||||
$nickname = $this->parameters['nickname'] ?? '';
|
||||
$contact_id = $this->parameters['cid'] ?? 0;
|
||||
|
||||
$hub_mode = trim($request['hub_mode'] ?? '');
|
||||
$hub_topic = trim($request['hub_topic'] ?? '');
|
||||
$hub_challenge = trim($request['hub_challenge'] ?? '');
|
||||
$hub_verify = trim($request['hub_verify_token'] ?? '');
|
||||
|
||||
$this->logger->notice('Subscription start.', ['from' => $this->request->getRemoteAddress(), 'mode' => $hub_mode, 'nickname' => $nickname]);
|
||||
$this->logger->debug('Data: ', ['get' => $request]);
|
||||
|
||||
$owner = $this->database->selectFirst('user', ['uid'], ['nickname' => $nickname, 'verified' => true, 'blocked' => false, 'account_removed' => false, 'account_expired' => false]);
|
||||
if (!$owner) {
|
||||
$this->logger->notice('Local account not found.', ['nickname' => $nickname]);
|
||||
throw new HTTPException\NotFoundException();
|
||||
}
|
||||
|
||||
$condition = ['uid' => $owner['uid'], 'id' => $contact_id, 'blocked' => false, 'pending' => false];
|
||||
|
||||
if (!empty($hub_verify)) {
|
||||
$condition['hub-verify'] = $hub_verify;
|
||||
}
|
||||
|
||||
$contact = $this->database->selectFirst('contact', ['id', 'poll'], $condition);
|
||||
if (!$contact) {
|
||||
$this->logger->notice('Contact not found.', ['contact' => $contact_id]);
|
||||
throw new HTTPException\NotFoundException();
|
||||
}
|
||||
|
||||
if (!empty($hub_topic) && !Strings::compareLink($hub_topic, $contact['poll'])) {
|
||||
$this->logger->notice("Hub topic isn't valid for Contact.", ['hub_topic' => $hub_topic, 'contact_poll' => $contact['poll']]);
|
||||
throw new HTTPException\NotFoundException();
|
||||
}
|
||||
|
||||
// We must initiate an unsubscribe request with a verify_token.
|
||||
// Don't allow outsiders to unsubscribe us.
|
||||
|
||||
if (($hub_mode === 'unsubscribe') && empty($hub_verify)) {
|
||||
$this->logger->notice('Bogus unsubscribe');
|
||||
throw new HTTPException\NotFoundException();
|
||||
}
|
||||
|
||||
if (!empty($hub_mode)) {
|
||||
Contact::update(['subhub' => $hub_mode === 'subscribe'], ['id' => $contact['id']]);
|
||||
$this->logger->notice('Success for contact.', ['mode' => $hub_mode, 'contact' => $contact_id]);
|
||||
}
|
||||
|
||||
$this->httpExit($hub_challenge);
|
||||
}
|
||||
}
|
|
@ -1,165 +0,0 @@
|
|||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024, the Friendica project
|
||||
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
namespace Friendica\Module\OStatus;
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Model\PushSubscriber;
|
||||
use Friendica\Module\Response;
|
||||
use Friendica\Network\HTTPClient\Capability\ICanSendHttpRequests;
|
||||
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
||||
use Friendica\Network\HTTPClient\Client\HttpClientOptions;
|
||||
use Friendica\Network\HTTPClient\Client\HttpClientRequest;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Util\Profiler;
|
||||
use Friendica\Util\Strings;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* An open, simple, web-scale and decentralized pubsub protocol.
|
||||
*
|
||||
* Part of the OStatus stack.
|
||||
*
|
||||
* See https://pubsubhubbub.github.io/PubSubHubbub/pubsubhubbub-core-0.4.html
|
||||
*
|
||||
* @version 0.4
|
||||
*/
|
||||
class PubSubHubBub extends \Friendica\BaseModule
|
||||
{
|
||||
/** @var IManageConfigValues */
|
||||
private $config;
|
||||
/** @var Database */
|
||||
private $database;
|
||||
/** @var ICanSendHttpRequests */
|
||||
private $httpClient;
|
||||
/** @var App\Request */
|
||||
private $request;
|
||||
|
||||
public function __construct(App\Request $request, ICanSendHttpRequests $httpClient, Database $database, IManageConfigValues $config, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = [])
|
||||
{
|
||||
parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
|
||||
|
||||
$this->config = $config;
|
||||
$this->database = $database;
|
||||
$this->httpClient = $httpClient;
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
// PuSH subscription must be considered "public" so just block it
|
||||
// if public access isn't enabled.
|
||||
if ($this->config->get('system', 'block_public')) {
|
||||
throw new HTTPException\ForbiddenException();
|
||||
}
|
||||
|
||||
$this->logger->debug('Got request data.', ['request' => $request]);
|
||||
|
||||
// Subscription request from subscriber
|
||||
// https://pubsubhubbub.github.io/PubSubHubbub/pubsubhubbub-core-0.4.html#rfc.section.5.1
|
||||
// Example from GNU Social:
|
||||
// [hub_mode] => subscribe
|
||||
// [hub_callback] => http://status.local/main/push/callback/1
|
||||
// [hub_verify] => sync
|
||||
// [hub_verify_token] => af11...
|
||||
// [hub_secret] => af11...
|
||||
// [hub_topic] => http://friendica.local/dfrn_poll/sazius
|
||||
|
||||
$hub_mode = $request['hub_mode'] ?? '';
|
||||
$hub_callback = $request['hub_callback'] ?? '';
|
||||
$hub_verify_token = $request['hub_verify_token'] ?? '';
|
||||
$hub_secret = $request['hub_secret'] ?? '';
|
||||
$hub_topic = $request['hub_topic'] ?? '';
|
||||
|
||||
// check for valid hub_mode
|
||||
if ($hub_mode === 'subscribe') {
|
||||
$subscribe = 1;
|
||||
} elseif ($hub_mode === 'unsubscribe') {
|
||||
$subscribe = 0;
|
||||
} else {
|
||||
$this->logger->notice('Invalid hub_mod - ignored.', ['mode' => $hub_mode]);
|
||||
throw new HTTPException\NotFoundException();
|
||||
}
|
||||
|
||||
$this->logger->info('hub_mode request details.', ['from' => $this->request->getRemoteAddress(), 'mode' => $hub_mode]);
|
||||
|
||||
$nickname = $this->parameters['nickname'] ?? $hub_topic;
|
||||
|
||||
// Extract nickname and strip any .atom extension
|
||||
$nickname = basename($nickname, '.atom');
|
||||
if (!$nickname) {
|
||||
$this->logger->notice('Empty nick, ignoring.');
|
||||
throw new HTTPException\NotFoundException();
|
||||
}
|
||||
|
||||
// fetch user from database given the nickname
|
||||
$condition = ['nickname' => $nickname, 'verified' => true, 'blocked' => false, 'account_removed' => false, 'account_expired' => false];
|
||||
$owner = $this->database->selectFirst('user', ['uid', 'nickname'], $condition);
|
||||
if (!$owner) {
|
||||
$this->logger->notice('Local account not found', ['nickname' => $nickname, 'topic' => $hub_topic, 'callback' => $hub_callback]);
|
||||
throw new HTTPException\NotFoundException();
|
||||
}
|
||||
|
||||
// get corresponding row from contact table
|
||||
$condition = ['uid' => $owner['uid'], 'blocked' => false, 'pending' => false, 'self' => true];
|
||||
$contact = $this->database->selectFirst('contact', ['poll'], $condition);
|
||||
if (!$contact) {
|
||||
$this->logger->notice('Self contact for user not found.', ['uid' => $owner['uid']]);
|
||||
throw new HTTPException\NotFoundException();
|
||||
}
|
||||
|
||||
// sanity check that topic URLs are the same
|
||||
$hub_topic2 = str_replace('/feed/', '/dfrn_poll/', $hub_topic);
|
||||
$self = $this->baseUrl . '/api/statuses/user_timeline/' . $owner['nickname'] . '.atom';
|
||||
|
||||
if (!Strings::compareLink($hub_topic, $contact['poll']) && !Strings::compareLink($hub_topic2, $contact['poll']) && !Strings::compareLink($hub_topic, $self)) {
|
||||
$this->logger->notice('Hub topic invalid', ['hub_topic' => $hub_topic, 'poll' => $contact['poll']]);
|
||||
throw new HTTPException\NotFoundException();
|
||||
}
|
||||
|
||||
// do subscriber verification according to the PuSH protocol
|
||||
$hub_challenge = Strings::getRandomHex(40);
|
||||
|
||||
$params = http_build_query([
|
||||
'hub.mode' => $subscribe == 1 ? 'subscribe' : 'unsubscribe',
|
||||
'hub.topic' => $hub_topic,
|
||||
'hub.challenge' => $hub_challenge,
|
||||
'hub.verify_token' => $hub_verify_token,
|
||||
|
||||
// lease time is hard coded to one week (in seconds)
|
||||
// we don't actually enforce the lease time because GNU
|
||||
// Social/StatusNet doesn't honour it (yet)
|
||||
'hub.lease_seconds' => 604800,
|
||||
]);
|
||||
|
||||
$hub_callback = rtrim($hub_callback, ' ?&#');
|
||||
$separator = parse_url($hub_callback, PHP_URL_QUERY) === null ? '?' : '&';
|
||||
|
||||
$fetchResult = $this->httpClient->get($hub_callback . $separator . $params, HttpClientAccept::DEFAULT, [HttpClientOptions::REQUEST => HttpClientRequest::PUBSUB]);
|
||||
$body = $fetchResult->getBodyString();
|
||||
$returnCode = $fetchResult->getReturnCode();
|
||||
|
||||
// give up if the HTTP return code wasn't a success (2xx)
|
||||
if ($returnCode < 200 || $returnCode > 299) {
|
||||
$this->logger->notice('Subscriber verification ignored', ['hub_topic' => $hub_topic, 'callback' => $hub_callback, 'returnCode' => $returnCode]);
|
||||
throw new HTTPException\NotFoundException();
|
||||
}
|
||||
|
||||
// check that the correct hub_challenge code was echoed back
|
||||
if (trim($body) !== $hub_challenge) {
|
||||
$this->logger->notice('Subscriber did not echo back hub.challenge, ignoring.', ['hub_challenge' => $hub_challenge, 'body' => trim($body)]);
|
||||
throw new HTTPException\NotFoundException();
|
||||
}
|
||||
|
||||
PushSubscriber::renew($owner['uid'], $nickname, $subscribe, $hub_callback, $hub_topic, $hub_secret);
|
||||
|
||||
throw new HTTPException\AcceptedException();
|
||||
}
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024, the Friendica project
|
||||
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
namespace Friendica\Module\OStatus;
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Core\Renderer;
|
||||
use Friendica\Core\Session\Capability\IHandleUserSessions;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Module\Response;
|
||||
use Friendica\Navigation\SystemMessages;
|
||||
use Friendica\Util\Profiler;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class Repair extends \Friendica\BaseModule
|
||||
{
|
||||
/** @var IHandleUserSessions */
|
||||
private $session;
|
||||
/** @var SystemMessages */
|
||||
private $systemMessages;
|
||||
/** @var Database */
|
||||
private $database;
|
||||
/** @var App\Page */
|
||||
private $page;
|
||||
|
||||
public function __construct(App\Page $page, Database $database, SystemMessages $systemMessages, IHandleUserSessions $session, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = [])
|
||||
{
|
||||
parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
|
||||
|
||||
$this->session = $session;
|
||||
$this->systemMessages = $systemMessages;
|
||||
$this->database = $database;
|
||||
$this->page = $page;
|
||||
}
|
||||
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
if (!$this->session->getLocalUserId()) {
|
||||
$this->systemMessages->addNotice($this->t('Permission denied.'));
|
||||
$this->baseUrl->redirect('login');
|
||||
}
|
||||
|
||||
$uid = $this->session->getLocalUserId();
|
||||
|
||||
$counter = intval($request['counter'] ?? 0);
|
||||
|
||||
$condition = ['uid' => $uid, 'network' => Protocol::OSTATUS, 'rel' => [Contact::FRIEND, Contact::SHARING]];
|
||||
$total = $this->database->count('contact', $condition);
|
||||
if ($total) {
|
||||
$contacts = Contact::selectToArray(['url'], $condition, ['order' => ['url'], 'limit' => [$counter++, 1]]);
|
||||
if ($contacts) {
|
||||
Contact::createFromProbeForUser($this->session->getLocalUserId(), $contacts[0]['url']);
|
||||
|
||||
$this->page['htmlhead'] .= '<meta http-equiv="refresh" content="5; url=ostatus/repair?counter=' . $counter . '">';
|
||||
}
|
||||
}
|
||||
|
||||
$tpl = Renderer::getMarkupTemplate('ostatus/repair.tpl');
|
||||
|
||||
return Renderer::replaceMacros($tpl, [
|
||||
'$l10n' => [
|
||||
'title' => $this->t('Resubscribing to OStatus contacts'),
|
||||
'keep' => $this->t('Keep this window open until done.'),
|
||||
'done' => $this->t('✔ Done'),
|
||||
'nocontacts' => $this->t('No OStatus contacts to resubscribe to.'),
|
||||
],
|
||||
'$total' => $total,
|
||||
'$counter' => $counter,
|
||||
'$contact' => $contacts[0] ?? null,
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -1,205 +0,0 @@
|
|||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024, the Friendica project
|
||||
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
namespace Friendica\Module\OStatus;
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Model\GServer;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\Post;
|
||||
use Friendica\Module\Response;
|
||||
use Friendica\Protocol\ActivityNamespace;
|
||||
use Friendica\Protocol\OStatus;
|
||||
use Friendica\Util\Crypto;
|
||||
use Friendica\Util\Network;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Protocol\Salmon as SalmonProtocol;
|
||||
use Friendica\Util\Profiler;
|
||||
use Friendica\Util\Strings;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Technical endpoint for the Salmon protocol
|
||||
*/
|
||||
class Salmon extends \Friendica\BaseModule
|
||||
{
|
||||
/** @var Database */
|
||||
private $database;
|
||||
|
||||
public function __construct(Database $database, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = [])
|
||||
{
|
||||
parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
|
||||
|
||||
$this->database = $database;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $request
|
||||
* @return void
|
||||
* @throws HTTPException\AcceptedException
|
||||
* @throws HTTPException\BadRequestException
|
||||
* @throws HTTPException\InternalServerErrorException
|
||||
* @throws HTTPException\OKException
|
||||
* @throws \ImagickException
|
||||
*/
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
$xml = Network::postdata();
|
||||
$this->logger->debug('Got request data.', ['request' => $request]);
|
||||
|
||||
$nickname = $this->parameters['nickname'] ?? '';
|
||||
if (empty($nickname)) {
|
||||
throw new HTTPException\BadRequestException('nickname parameter is mandatory');
|
||||
}
|
||||
|
||||
$this->logger->debug('New Salmon', ['nickname' => $nickname, 'xml' => $xml]);
|
||||
|
||||
$importer = $this->database->selectFirst('user', [], ['nickname' => $nickname, 'verified' => true, 'blocked' => false, 'account_removed' => false, 'account_expired' => false]);
|
||||
if (!$this->database->isResult($importer)) {
|
||||
throw new HTTPException\InternalServerErrorException();
|
||||
}
|
||||
|
||||
// parse the xml
|
||||
$dom = simplexml_load_string($xml, 'SimpleXMLElement', 0, ActivityNamespace::SALMON_ME);
|
||||
|
||||
$base = null;
|
||||
|
||||
// figure out where in the DOM tree our data is hiding
|
||||
if (!empty($dom->provenance->data)) {
|
||||
$base = $dom->provenance;
|
||||
} elseif (!empty($dom->env->data)) {
|
||||
$base = $dom->env;
|
||||
} elseif (!empty($dom->data)) {
|
||||
$base = $dom;
|
||||
}
|
||||
|
||||
if (empty($base)) {
|
||||
$this->logger->notice('unable to locate salmon data in xml');
|
||||
throw new HTTPException\BadRequestException();
|
||||
}
|
||||
|
||||
// Stash the signature away for now. We have to find their key or it won't be good for anything.
|
||||
$signature = Strings::base64UrlDecode($base->sig);
|
||||
|
||||
// unpack the data
|
||||
|
||||
// strip whitespace so our data element will return to one big base64 blob
|
||||
$data = str_replace([" ", "\t", "\r", "\n"], ["", "", "", ""], $base->data);
|
||||
|
||||
// stash away some other stuff for later
|
||||
|
||||
$type = $base->data[0]->attributes()->type[0];
|
||||
$keyhash = $base->sig[0]->attributes()->keyhash[0] ?? '';
|
||||
$encoding = $base->encoding;
|
||||
$alg = $base->alg;
|
||||
|
||||
// Salmon magic signatures have evolved and there is no way of knowing ahead of time which
|
||||
// flavour we have. We'll try and verify it regardless.
|
||||
|
||||
$stnet_signed_data = $data;
|
||||
|
||||
$signed_data = $data . '.' . Strings::base64UrlEncode($type) . '.' . Strings::base64UrlEncode($encoding) . '.' . Strings::base64UrlEncode($alg);
|
||||
|
||||
$compliant_format = str_replace('=', '', $signed_data);
|
||||
|
||||
|
||||
// decode the data
|
||||
$data = Strings::base64UrlDecode($data);
|
||||
|
||||
$author = OStatus::salmonAuthor($data, $importer);
|
||||
$author_link = $author["author-link"];
|
||||
if (!$author_link) {
|
||||
$this->logger->notice('Could not retrieve author URI.');
|
||||
throw new HTTPException\BadRequestException();
|
||||
}
|
||||
|
||||
// Once we have the author URI, go to the web and try to find their public key
|
||||
|
||||
$this->logger->notice('Fetching key for ' . $author_link);
|
||||
|
||||
$key = SalmonProtocol::getKey($author_link, $keyhash);
|
||||
|
||||
if (!$key) {
|
||||
$this->logger->notice('Could not retrieve author key.');
|
||||
throw new HTTPException\BadRequestException();
|
||||
}
|
||||
|
||||
$this->logger->info('Key details', ['info' => $key]);
|
||||
|
||||
$pubkey = SalmonProtocol::magicKeyToPem($key);
|
||||
|
||||
// We should have everything we need now. Let's see if it verifies.
|
||||
|
||||
// Try GNU Social format
|
||||
$verify = Crypto::rsaVerify($signed_data, $signature, $pubkey);
|
||||
$mode = 1;
|
||||
|
||||
if (!$verify) {
|
||||
$this->logger->notice('Message did not verify using protocol. Trying compliant format.');
|
||||
$verify = Crypto::rsaVerify($compliant_format, $signature, $pubkey);
|
||||
$mode = 2;
|
||||
}
|
||||
|
||||
if (!$verify) {
|
||||
$this->logger->notice('Message did not verify using padding. Trying old statusnet format.');
|
||||
$verify = Crypto::rsaVerify($stnet_signed_data, $signature, $pubkey);
|
||||
$mode = 3;
|
||||
}
|
||||
|
||||
if (!$verify) {
|
||||
$this->logger->notice('Message did not verify. Discarding.');
|
||||
throw new HTTPException\BadRequestException();
|
||||
}
|
||||
|
||||
$this->logger->notice('Message verified with mode ' . $mode);
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* If we reached this point, the message is good. Now let's figure out if the author is allowed to send us stuff.
|
||||
*
|
||||
*/
|
||||
|
||||
$contact = $this->database->selectFirst(
|
||||
'contact',
|
||||
[],
|
||||
[
|
||||
"`network` IN (?, ?)
|
||||
AND (`nurl` = ? OR `alias` = ? OR `alias` = ?)
|
||||
AND `uid` = ?",
|
||||
Protocol::OSTATUS, Protocol::DFRN,
|
||||
Strings::normaliseLink($author_link), $author_link, Strings::normaliseLink($author_link),
|
||||
$importer['uid']
|
||||
]
|
||||
);
|
||||
|
||||
if (!empty($contact['gsid'])) {
|
||||
GServer::setProtocol($contact['gsid'], Post\DeliveryData::OSTATUS);
|
||||
}
|
||||
|
||||
// Have we ignored the person?
|
||||
// If so we can not accept this post.
|
||||
|
||||
if (!empty($contact['blocked'])) {
|
||||
$this->logger->notice('Ignoring this author.');
|
||||
throw new HTTPException\AcceptedException();
|
||||
}
|
||||
|
||||
// Placeholder for hub discovery.
|
||||
$hub = '';
|
||||
|
||||
$contact = $contact ?: [];
|
||||
|
||||
Item::incrementOutbound(Protocol::OSTATUS);
|
||||
OStatus::import($data, $importer, $contact, $hub);
|
||||
|
||||
throw new HTTPException\OKException();
|
||||
}
|
||||
}
|
|
@ -77,7 +77,7 @@ class Common extends BaseProfile
|
|||
$condition = [
|
||||
'blocked' => false,
|
||||
'deleted' => false,
|
||||
'network' => [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS, Protocol::FEED],
|
||||
'network' => [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::FEED],
|
||||
];
|
||||
|
||||
$total = Contact\Relation::countCommon($sourceId, $targetId, $condition);
|
||||
|
|
|
@ -78,7 +78,7 @@ class Contacts extends Module\BaseProfile
|
|||
'archive' => false,
|
||||
'failed' => false,
|
||||
'self' => false,
|
||||
'network' => [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS]
|
||||
'network' => [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA]
|
||||
];
|
||||
|
||||
switch ($type) {
|
||||
|
|
|
@ -89,7 +89,6 @@ class Conversations extends BaseProfile
|
|||
$this->page['htmlhead'] .= '<meta content="noindex, noarchive" name="robots" />' . "\n";
|
||||
}
|
||||
|
||||
$this->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $this->baseUrl . '/dfrn_poll/' . $this->parameters['nickname'] . '" title="DFRN: ' . $this->t('%s\'s timeline', Strings::escapeHtml($profile['name'])) . '"/>' . "\n";
|
||||
$this->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $this->baseUrl . '/feed/' . $this->parameters['nickname'] . '/" title="' . $this->t('%s\'s posts', Strings::escapeHtml($profile['name'])) . '"/>' . "\n";
|
||||
$this->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $this->baseUrl . '/feed/' . $this->parameters['nickname'] . '/comments" title="' . $this->t('%s\'s comments', Strings::escapeHtml($profile['name'])) . '"/>' . "\n";
|
||||
$this->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $this->baseUrl . '/feed/' . $this->parameters['nickname'] . '/activity" title="' . $this->t('%s\'s timeline', Strings::escapeHtml($profile['name'])) . '"/>' . "\n";
|
||||
|
|
|
@ -336,7 +336,6 @@ class Profile extends BaseProfile
|
|||
$htmlhead .= '<meta content="noindex, noarchive" name="robots" />' . "\n";
|
||||
}
|
||||
|
||||
$htmlhead .= '<link rel="alternate" type="application/atom+xml" href="' . $this->baseUrl . '/dfrn_poll/' . $nickname . '" title="DFRN: ' . $this->t('%s\'s timeline', htmlspecialchars($profile['name'], ENT_COMPAT, 'UTF-8', true)) . '"/>' . "\n";
|
||||
$htmlhead .= '<link rel="alternate" type="application/atom+xml" href="' . $this->baseUrl . '/feed/' . $nickname . '/" title="' . $this->t('%s\'s posts', htmlspecialchars($profile['name'], ENT_COMPAT, 'UTF-8', true)) . '"/>' . "\n";
|
||||
$htmlhead .= '<link rel="alternate" type="application/atom+xml" href="' . $this->baseUrl . '/feed/' . $nickname . '/comments" title="' . $this->t('%s\'s comments', htmlspecialchars($profile['name'], ENT_COMPAT, 'UTF-8', true)) . '"/>' . "\n";
|
||||
$htmlhead .= '<link rel="alternate" type="application/atom+xml" href="' . $this->baseUrl . '/feed/' . $nickname . '/activity" title="' . $this->t('%s\'s timeline', htmlspecialchars($profile['name'], ENT_COMPAT, 'UTF-8', true)) . '"/>' . "\n";
|
||||
|
@ -344,7 +343,7 @@ class Profile extends BaseProfile
|
|||
$htmlhead .= '<link rel="lrdd" type="application/xrd+xml" href="' . $this->baseUrl . '/xrd/?uri=' . $uri . '" />' . "\n";
|
||||
header('Link: <' . $this->baseUrl . '/xrd/?uri=' . $uri . '>; rel="lrdd"; type="application/xrd+xml"', false);
|
||||
|
||||
$dfrn_pages = ['request', 'confirm', 'notify', 'poll'];
|
||||
$dfrn_pages = ['notify', 'poll'];
|
||||
foreach ($dfrn_pages as $dfrn) {
|
||||
$htmlhead .= '<link rel="dfrn-' . $dfrn . '" href="' . $this->baseUrl . '/dfrn_' . $dfrn . '/' . $nickname . '" />' . "\n";
|
||||
}
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024, the Friendica project
|
||||
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
namespace Friendica\Module;
|
||||
|
||||
use Friendica\BaseModule;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Network\HTTPException\BadRequestException;
|
||||
use Friendica\Protocol\Salmon;
|
||||
|
||||
/**
|
||||
* prints the public RSA key of a user
|
||||
*/
|
||||
class PublicRSAKey extends BaseModule
|
||||
{
|
||||
protected function rawContent(array $request = [])
|
||||
{
|
||||
if (empty($this->parameters['nick'])) {
|
||||
throw new BadRequestException();
|
||||
}
|
||||
|
||||
$nick = $this->parameters['nick'];
|
||||
|
||||
$user = User::getByNickname($nick, ['spubkey']);
|
||||
if (empty($user) || empty($user['spubkey'])) {
|
||||
throw new BadRequestException();
|
||||
}
|
||||
|
||||
$this->httpExit(
|
||||
Salmon::salmonKey($user['spubkey']),
|
||||
Response::TYPE_BLANK,
|
||||
'application/magic-public-key'
|
||||
);
|
||||
}
|
||||
}
|
|
@ -141,11 +141,6 @@ class Acl extends BaseModule
|
|||
|
||||
switch ($type) {
|
||||
case self::TYPE_MENTION_CONTACT_CIRCLE:
|
||||
$condition = DBA::mergeConditions($condition,
|
||||
["NOT `self` AND NOT `blocked` AND `network` != ?", Protocol::OSTATUS
|
||||
]);
|
||||
break;
|
||||
|
||||
case self::TYPE_MENTION_CONTACT:
|
||||
$condition = DBA::mergeConditions($condition,
|
||||
["NOT `self` AND NOT `blocked`",
|
||||
|
|
|
@ -154,12 +154,8 @@ class Connectors extends BaseSettings
|
|||
$diasp_enabled = $this->config->get('system', 'diaspora_enabled') ?
|
||||
$this->t('Built-in support for %s connectivity is enabled', $this->t('Diaspora (Socialhome, Hubzilla)')) :
|
||||
$this->t('Built-in support for %s connectivity is disabled', $this->t('Diaspora (Socialhome, Hubzilla)'));
|
||||
$ostat_enabled = $this->config->get('system', 'ostatus_disabled') ?
|
||||
$this->t('Built-in support for %s connectivity is disabled', $this->t('OStatus (GNU Social)')) :
|
||||
$this->t('Built-in support for %s connectivity is enabled', $this->t('OStatus (GNU Social)'));
|
||||
} else {
|
||||
$diasp_enabled = '';
|
||||
$ostat_enabled = '';
|
||||
}
|
||||
|
||||
$mail_enabled = function_exists('imap_open') && !$this->config->get('system', 'imap_disabled');
|
||||
|
@ -199,7 +195,6 @@ class Connectors extends BaseSettings
|
|||
'$title' => $this->t('Social Networks'),
|
||||
|
||||
'$diasp_enabled' => $diasp_enabled,
|
||||
'$ostat_enabled' => $ostat_enabled,
|
||||
|
||||
'$general_settings' => $this->t('General Social Media Settings'),
|
||||
'$accept_only_sharer' => [
|
||||
|
@ -221,8 +216,6 @@ class Connectors extends BaseSettings
|
|||
'$api_auto_attach' => ['api_auto_attach', $this->t('API: Automatically links at the end of the post as attached posts'), $api_auto_attach, $this->t('When activated, added links at the end of the post react the same way as added links in the web interface.')],
|
||||
'$article_mode' => ['article_mode', $this->t('Article Mode'), $article_mode, $this->t("Controls how posts with titles are transmitted. Mastodon and its forks don't display the content of these posts if the post is created in the correct (default) way."), $article_modes],
|
||||
'$legacy_contact' => ['legacy_contact', $this->t('Your legacy ActivityPub/GNU Social account'), $legacy_contact, $this->t('If you enter your old account name from an ActivityPub based system or your GNU Social/Statusnet account name here (in the format user@domain.tld), your contacts will be added automatically. The field will be emptied when done.')],
|
||||
'$repair_ostatus_url' => 'ostatus/repair',
|
||||
'$repair_ostatus_text' => $this->t('Repair OStatus subscriptions'),
|
||||
|
||||
'$connector_settings_forms' => $connector_settings_forms,
|
||||
|
||||
|
|
|
@ -8,10 +8,8 @@
|
|||
namespace Friendica\Module\WellKnown;
|
||||
|
||||
use Friendica\BaseModule;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\DI;
|
||||
use Friendica\Module\Response;
|
||||
use Friendica\Protocol\Salmon;
|
||||
use Friendica\Util\Crypto;
|
||||
use Friendica\Util\XML;
|
||||
|
||||
|
@ -66,15 +64,8 @@ class HostMeta extends BaseModule
|
|||
'href' => $domain . '/amcd'
|
||||
]
|
||||
],
|
||||
'Property' => [
|
||||
'@attributes' => [
|
||||
'type' => 'http://salmon-protocol.org/ns/magic-key',
|
||||
'mk:key_id' => '1'
|
||||
],
|
||||
Salmon::salmonKey($config->get('system', 'site_pubkey'))
|
||||
]
|
||||
],
|
||||
], $xml, false, ['hm' => 'http://host-meta.net/xrd/1.0', 'mk' => 'http://salmon-protocol.org/ns/magic-key']);
|
||||
], $xml, false, ['hm' => 'http://host-meta.net/xrd/1.0']);
|
||||
|
||||
$this->httpExit($xml->saveXML(), Response::TYPE_XML, 'application/xrd+xml');
|
||||
}
|
||||
|
|
|
@ -8,14 +8,12 @@
|
|||
namespace Friendica\Module;
|
||||
|
||||
use Friendica\BaseModule;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Photo;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Network\HTTPException\BadRequestException;
|
||||
use Friendica\Network\HTTPException\NotFoundException;
|
||||
use Friendica\Protocol\ActivityNamespace;
|
||||
use Friendica\Protocol\Salmon;
|
||||
use Friendica\Util\Network;
|
||||
use Friendica\Util\XML;
|
||||
|
||||
|
@ -132,6 +130,11 @@ class Xrd extends BaseModule
|
|||
'subject' => 'acct:' . $owner['addr'],
|
||||
'aliases' => [$owner['url']],
|
||||
'links' => [
|
||||
[
|
||||
'rel' => ActivityNamespace::FEED,
|
||||
'type' => 'application/atom+xml',
|
||||
'href' => $owner['poll'] ?? $baseURL,
|
||||
],
|
||||
[
|
||||
'rel' => ActivityNamespace::WEBFINGERPROFILE,
|
||||
'type' => 'text/html',
|
||||
|
@ -142,19 +145,6 @@ class Xrd extends BaseModule
|
|||
'type' => 'application/activity+json',
|
||||
'href' => $owner['url'],
|
||||
],
|
||||
[
|
||||
'rel' => ActivityNamespace::OSTATUSSUB,
|
||||
'template' => $baseURL . '/contact/follow?url={uri}',
|
||||
],
|
||||
[
|
||||
'rel' => ActivityNamespace::FEED,
|
||||
'type' => 'application/atom+xml',
|
||||
'href' => $owner['poll'] ?? $baseURL,
|
||||
],
|
||||
[
|
||||
'rel' => 'salmon',
|
||||
'href' => $baseURL . '/salmon/' . $owner['nickname'],
|
||||
],
|
||||
[
|
||||
'rel' => ActivityNamespace::HCARD,
|
||||
'type' => 'text/html',
|
||||
|
@ -165,6 +155,14 @@ class Xrd extends BaseModule
|
|||
'type' => 'text/html',
|
||||
'href' => $baseURL,
|
||||
],
|
||||
[
|
||||
'rel' => 'salmon',
|
||||
'href' => $baseURL . '/receive/users/' . $owner['guid'],
|
||||
],
|
||||
[
|
||||
'rel' => ActivityNamespace::OSTATUSSUB,
|
||||
'template' => $baseURL . '/contact/follow?url={uri}',
|
||||
],
|
||||
]
|
||||
];
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
|
@ -218,24 +216,12 @@ class Xrd extends BaseModule
|
|||
],
|
||||
[
|
||||
'rel' => 'salmon',
|
||||
'href' => $baseURL . '/salmon/' . $owner['nickname'],
|
||||
],
|
||||
[
|
||||
'rel' => 'http://salmon-protocol.org/ns/salmon-replies',
|
||||
'href' => $baseURL . '/salmon/' . $owner['nickname'],
|
||||
],
|
||||
[
|
||||
'rel' => 'http://salmon-protocol.org/ns/salmon-mention',
|
||||
'href' => $baseURL . '/salmon/' . $owner['nickname'] . '/mention',
|
||||
'href' => $baseURL . '/receive/users/' . $owner['guid'],
|
||||
],
|
||||
[
|
||||
'rel' => ActivityNamespace::OSTATUSSUB,
|
||||
'template' => $baseURL . '/contact/follow?url={uri}',
|
||||
],
|
||||
[
|
||||
'rel' => 'magic-public-key',
|
||||
'href' => 'data:application/magic-public-key,' . Salmon::salmonKey($owner['spubkey']),
|
||||
],
|
||||
[
|
||||
'rel' => ActivityNamespace::OPENWEBAUTH,
|
||||
'type' => 'application/x-zot+json',
|
||||
|
@ -262,13 +248,13 @@ class Xrd extends BaseModule
|
|||
'2:Alias' => $alias,
|
||||
'1:link' => [
|
||||
'@attributes' => [
|
||||
'rel' => 'http://purl.org/macgirvin/dfrn/1.0',
|
||||
'rel' => ActivityNamespace::DFRN,
|
||||
'href' => $owner['url']
|
||||
]
|
||||
],
|
||||
'2:link' => [
|
||||
'@attributes' => [
|
||||
'rel' => 'http://schemas.google.com/g/2010#updates-from',
|
||||
'rel' => ActivityNamespace::FEED,
|
||||
'type' => 'application/atom+xml',
|
||||
'href' => $owner['poll']
|
||||
]
|
||||
|
@ -311,34 +297,16 @@ class Xrd extends BaseModule
|
|||
'8:link' => [
|
||||
'@attributes' => [
|
||||
'rel' => 'salmon',
|
||||
'href' => $baseURL . '/salmon/' . $owner['nickname']
|
||||
'href' => $baseURL . '/receive/users/' . $owner['guid']
|
||||
]
|
||||
],
|
||||
'9:link' => [
|
||||
'@attributes' => [
|
||||
'rel' => 'http://salmon-protocol.org/ns/salmon-replies',
|
||||
'href' => $baseURL . '/salmon/' . $owner['nickname']
|
||||
]
|
||||
],
|
||||
'10:link' => [
|
||||
'@attributes' => [
|
||||
'rel' => 'http://salmon-protocol.org/ns/salmon-mention',
|
||||
'href' => $baseURL . '/salmon/' . $owner['nickname'] . '/mention'
|
||||
]
|
||||
],
|
||||
'11:link' => [
|
||||
'@attributes' => [
|
||||
'rel' => ActivityNamespace::OSTATUSSUB,
|
||||
'template' => $baseURL . '/contact/follow?url={uri}'
|
||||
]
|
||||
],
|
||||
'12:link' => [
|
||||
'@attributes' => [
|
||||
'rel' => 'magic-public-key',
|
||||
'href' => 'data:application/magic-public-key,' . Salmon::salmonKey($owner['spubkey'])
|
||||
]
|
||||
],
|
||||
'13:link' => [
|
||||
'10:link' => [
|
||||
'@attributes' => [
|
||||
'rel' => ActivityNamespace::OPENWEBAUTH,
|
||||
'type' => 'application/x-zot+json',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue