]> git.mxchange.org Git - friendica.git/commitdiff
OStatus support removed
authorMichael <heluecht@pirati.ca>
Sat, 24 Aug 2024 04:27:00 +0000 (04:27 +0000)
committerMichael <heluecht@pirati.ca>
Wed, 11 Sep 2024 03:44:40 +0000 (03:44 +0000)
87 files changed:
database.sql
doc/Channels.md
doc/Connectors.md
doc/Improve-Performance.md
doc/Move-Account.md
doc/Protocol.md
doc/database.md
doc/database/db_contact.md
doc/database/db_post-delivery-data.md
doc/database/db_push_subscriber.md [deleted file]
doc/database/db_user-contact.md
doc/database/db_user.md
doc/de/Channels.md
doc/de/Connectors.md
mod/photos.php
src/App/Mode.php
src/Contact/LocalRelationship/Entity/LocalRelationship.php
src/Contact/LocalRelationship/Factory/LocalRelationship.php
src/Contact/LocalRelationship/Repository/LocalRelationship.php
src/Content/Text/BBCode.php
src/Content/Text/Plaintext.php
src/Content/Widget.php
src/Content/Widget/ContactBlock.php
src/Core/Protocol.php
src/Database/DBStructure.php
src/Model/Contact.php
src/Model/Contact/Relation.php
src/Model/Conversation.php
src/Model/GServer.php
src/Model/Item.php
src/Model/Post/DeliveryData.php
src/Model/Post/Engagement.php
src/Model/PushSubscriber.php [deleted file]
src/Model/Tag.php
src/Model/User.php
src/Module/Admin/Site.php
src/Module/Api/Mastodon/Search.php
src/Module/Api/Mastodon/Timelines/Tag.php
src/Module/Contact.php
src/Module/Contact/Follow.php
src/Module/Contact/Profile.php
src/Module/DFRN/Notify.php
src/Module/DFRN/Poll.php [deleted file]
src/Module/HCard.php
src/Module/NoScrape.php
src/Module/NodeInfo110.php
src/Module/NodeInfo120.php
src/Module/NodeInfo121.php
src/Module/NodeInfo122.php
src/Module/NodeInfo210.php
src/Module/OStatus/PubSub.php [deleted file]
src/Module/OStatus/PubSubHubBub.php [deleted file]
src/Module/OStatus/Repair.php [deleted file]
src/Module/OStatus/Salmon.php [deleted file]
src/Module/Profile/Common.php
src/Module/Profile/Contacts.php
src/Module/Profile/Conversations.php
src/Module/Profile/Profile.php
src/Module/PublicRSAKey.php [deleted file]
src/Module/Search/Acl.php
src/Module/Settings/Connectors.php
src/Module/WellKnown/HostMeta.php
src/Module/Xrd.php
src/Navigation/Notifications/Factory/Introduction.php
src/Network/HTTPClient/Client/HttpClientRequest.php
src/Network/Probe.php
src/Object/Post.php
src/Protocol/ActivityPub/Receiver.php
src/Protocol/ActivityPub/Transmitter.php
src/Protocol/DFRN.php
src/Protocol/Feed.php
src/Protocol/OStatus.php [deleted file]
src/Protocol/Salmon.php
src/Worker/MergeContact.php
src/Worker/Notifier.php
src/Worker/OnePoll.php
src/Worker/PollContacts.php
src/Worker/PubSubPublish.php [deleted file]
static/dbstructure.config.php
static/dbview.config.php
static/routes.config.php
update.php
view/lang/C/messages.po
view/templates/admin/site.tpl
view/templates/settings/connectors.tpl
view/theme/frio/templates/admin/site.tpl
view/theme/frio/templates/settings/connectors.tpl

index 14266c95e08343bba8f163dbdb26ed869baceee5..dae766cfea1cf4dbe9f3bcffa5a66509af0d92a6 100644 (file)
@@ -70,8 +70,6 @@ CREATE TABLE IF NOT EXISTS `user` (
        `theme` varchar(255) NOT NULL DEFAULT '' COMMENT 'user theme preference',
        `pubkey` text COMMENT 'RSA public key 4096 bit',
        `prvkey` text COMMENT 'RSA private key 4096 bit',
-       `spubkey` text COMMENT '',
-       `sprvkey` text COMMENT '',
        `verified` boolean NOT NULL DEFAULT '0' COMMENT 'user is verified through email',
        `blocked` boolean NOT NULL DEFAULT '0' COMMENT '1 for user is blocked',
        `blockwall` boolean NOT NULL DEFAULT '0' COMMENT 'Prohibit contacts to post to the profile page of the user',
@@ -183,7 +181,6 @@ CREATE TABLE IF NOT EXISTS `contact` (
        `remote_self` boolean NOT NULL DEFAULT '0' COMMENT '',
        `rel` tinyint unsigned NOT NULL DEFAULT 0 COMMENT 'The kind of the relation between the user and the contact',
        `protocol` char(4) NOT NULL DEFAULT '' COMMENT 'Protocol of the contact',
-       `subhub` boolean NOT NULL DEFAULT '0' COMMENT '',
        `hub-verify` varbinary(383) NOT NULL DEFAULT '' COMMENT '',
        `rating` tinyint NOT NULL DEFAULT 0 COMMENT 'Automatically detected feed poll frequency',
        `priority` tinyint unsigned NOT NULL DEFAULT 0 COMMENT 'Feed poll priority',
@@ -1345,7 +1342,6 @@ CREATE TABLE IF NOT EXISTS `post-delivery-data` (
        `dfrn` mediumint NOT NULL DEFAULT 0 COMMENT 'Number of successful deliveries via DFRN',
        `legacy_dfrn` mediumint NOT NULL DEFAULT 0 COMMENT 'Number of successful deliveries via legacy DFRN',
        `diaspora` mediumint NOT NULL DEFAULT 0 COMMENT 'Number of successful deliveries via Diaspora',
-       `ostatus` mediumint NOT NULL DEFAULT 0 COMMENT 'Number of successful deliveries via OStatus',
         PRIMARY KEY(`uri-id`),
        FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE
 ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Delivery data for items';
@@ -1812,26 +1808,6 @@ CREATE TABLE IF NOT EXISTS `profile_field` (
        FOREIGN KEY (`psid`) REFERENCES `permissionset` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT
 ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Custom profile fields';
 
---
--- TABLE push_subscriber
---
-CREATE TABLE IF NOT EXISTS `push_subscriber` (
-       `id` int unsigned NOT NULL auto_increment COMMENT 'sequential ID',
-       `uid` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'User id',
-       `callback_url` varbinary(383) NOT NULL DEFAULT '' COMMENT '',
-       `topic` varchar(255) NOT NULL DEFAULT '' COMMENT '',
-       `nickname` varchar(255) NOT NULL DEFAULT '' COMMENT '',
-       `push` tinyint NOT NULL DEFAULT 0 COMMENT 'Retrial counter',
-       `last_update` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Date of last successful trial',
-       `next_try` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Next retrial date',
-       `renewed` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Date of last subscription renewal',
-       `secret` varchar(255) NOT NULL DEFAULT '' COMMENT '',
-        PRIMARY KEY(`id`),
-        INDEX `next_try` (`next_try`),
-        INDEX `uid` (`uid`),
-       FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE
-) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Used for OStatus: Contains feed subscribers';
-
 --
 -- TABLE register
 --
@@ -2010,7 +1986,6 @@ CREATE TABLE IF NOT EXISTS `user-contact` (
        `remote_self` tinyint unsigned COMMENT '0 => No mirroring, 1-2 => Mirror as own post, 3 => Mirror as reshare',
        `fetch_further_information` tinyint unsigned COMMENT '0 => None, 1 => Fetch information, 3 => Fetch keywords, 2 => Fetch both',
        `ffi_keyword_denylist` text COMMENT '',
-       `subhub` boolean COMMENT '',
        `hub-verify` varbinary(383) COMMENT '',
        `protocol` char(4) COMMENT 'Protocol of the contact',
        `rating` tinyint COMMENT 'Automatically detected feed poll frequency',
@@ -3516,7 +3491,6 @@ CREATE VIEW `owner-view` AS SELECT
        `contact`.`poll` AS `poll`,
        `contact`.`confirm` AS `confirm`,
        `contact`.`poco` AS `poco`,
-       `contact`.`subhub` AS `subhub`,
        `contact`.`hub-verify` AS `hub-verify`,
        `contact`.`last-update` AS `last-update`,
        `contact`.`success_update` AS `success_update`,
@@ -3565,8 +3539,6 @@ CREATE VIEW `owner-view` AS SELECT
        `user`.`theme` AS `theme`,
        `user`.`pubkey` AS `upubkey`,
        `user`.`prvkey` AS `uprvkey`,
-       `user`.`sprvkey` AS `sprvkey`,
-       `user`.`spubkey` AS `spubkey`,
        `user`.`verified` AS `verified`,
        `user`.`blockwall` AS `blockwall`,
        `user`.`hidewall` AS `hidewall`,
@@ -3763,7 +3735,6 @@ CREATE VIEW `account-user-view` AS SELECT
        `ucontact`.`readonly` AS `readonly`,
        `ucontact`.`blocked` AS `blocked`,
        `ucontact`.`block_reason` AS `block_reason`,
-       `ucontact`.`subhub` AS `subhub`,
        `ucontact`.`hub-verify` AS `hub-verify`,
        `ucontact`.`reason` AS `reason`,
        `contact`.`notify` AS `dfrn-notify`,
index 1465c32da21ecd3e7d27787a9621e1496f9cac4b..63d25821705af793c468d23768a5da9b6488f4e9 100644 (file)
@@ -84,7 +84,6 @@ Alternatives are presented with "|".
     * network:dspr | network:diaspora - The Diaspora protocol is mainly used by Diaspora itself. Some other systems support the protocol as well like Hubzilla, Socialhome or Ganggo.
     * network:feed - RSS/Atom feeds
     * network:mail - Mails that had been imported via IMAP.
-    * network:stat | network:ostatus - The OStatus protocol is mainly used by old GNU Social installations.
     * network:dscs | network:discourse - Posts that are received by the Discourse connector.
     * network:tmbl | network:tumblr - Posts that are received by the Tumblr connector.
     * network:bsky | network:bluesky - Posts that are received by the Bluesky connector.
index 992e83bba9d986c242ebd2089b6f8491c9bf1dc0..b081f5b25cab9119c2e2c36b0440828cdb277f46 100644 (file)
@@ -28,23 +28,6 @@ Diaspora
 
 Add the Diaspora 'handle' to the 'Connect/Follow' text box on your [Contacts](contacts) page. 
 
-
-GNU Social
----
-
-This is described as the "federated social web" or OStatus contacts. 
-
-Please note that there are **no** privacy provisions on the OStatus network.
-Any message which is delivered to **any** OStatus member is visible to anybody in the world and will negate any privacy settings that you have in effect.
-These messages will also turn up in public searches. 
-
-Since OStatus communications do not use authentication, if you select the profile privacy option to hide your profile and messages from unknown viewers, OStatus members will **not** be able to receive your communications. 
-
-To connect with an OStatus member insert their profile URL or Identity address into the Connect box on your [Contacts](contacts) page.
-
-The GNU Social connector may be used if you wish posts to appear on an OStatus site using an existing OStatus account. 
-It is not necessary to do this, as you may 'follow' OStatus members from Friendica and they may follow you (by placing their own Identity Address into your 'Connect' page).
-
 Blogger, Wordpress, RSS feeds, arbitrary web pages
 ---
 
index 727fa104be24313897452bb11fed3440ce4f0541..9134cb6c74251e246da62c6c6e5700f45e683f0f 100644 (file)
@@ -14,10 +14,6 @@ Please go to /admin/site/ on your system and change the following values:
 
 This value reduces the data that is send from the server to the client. 50 is a value that doesn't influences image quality too much.
 
-    Set "OStatus conversation completion interval" to "never".
-
-If you have many OStatus contacts then completing of conversations can take some time. Since you will miss several comments in OStatus threads, you maybe should consider the option "At post arrival" instead.
-
     Enable "Use MySQL full text engine"
 
 When using MyISAM (default) or InnoDB on MariaDB 10 this speeds up search.
index 2983184be6c33d039f8fa8533d1bfb13c9a2a842..9e13d7cad8afa5e618d28aefbd75d62b39d93d4d 100644 (file)
@@ -21,11 +21,6 @@ Friendica will recreate your account on the new server, with your contacts and c
 A message is sent to Friendica contacts, to inform them about your move:
 If your contacts are running on an updated server, your details on their side will be automatically updated.
 
-GNU Social contacts
----
-Contacts on GNU Social will be archived, as we can't inform them about your move.
-You should ask them to remove your contact from their lists and re-add you, and you should do the same with their contact.
-
 Diaspora contacts
 ---
 Newer Diaspora servers are able to process "account migration" messages.
index 85fe09a5f1aee510dcbb414d7a1ef1117f93f260..af0002472c7072b3cfabd349493f9721399ea906 100644 (file)
@@ -20,23 +20,9 @@ Additional types are used for non standard activities.
 * [Link to the specification](http://activitystrea.ms/head/activity-schema.html)
 * [List of used ActivityStreams verbs and object types.](https://github.com/friendica/friendica/wiki/ActivityStreams)
 
-Salmon
----
-
-Salmon is used as a message exchange protocol for replies and mentions.
-
-* [Link to the protocol summary](http://www.salmon-protocol.org/salmon-protocol-summary)
-
 Portable Contacts
 ---
 
 Portable Contacts is used for friends lists.
 
 * [Link to the specification](https://web.archive.org/web/20160426223008/http://portablecontacts.net/draft-spec.html) (Link to archive.org)
-
-pubsubhubbub
----
-
-pubsubhubbub is used for OStatus.
-
-* [Link to the specification](https://pubsubhubbub.github.io/PubSubHubbub/pubsubhubbub-core-0.4.html)
index a98fca8fbd370eac31474f01b1626bee8171a4b9..4036b7ec14073d295d7f0ed28da90a433dc372f4 100644 (file)
@@ -80,7 +80,6 @@ Database Tables
 | [process](help/database/db_process) | Currently running system processes |
 | [profile](help/database/db_profile) | user profiles data |
 | [profile_field](help/database/db_profile_field) | Custom profile fields |
-| [push_subscriber](help/database/db_push_subscriber) | Used for OStatus: Contains feed subscribers |
 | [register](help/database/db_register) | registrations requiring admin approval |
 | [report](help/database/db_report) |  |
 | [report-post](help/database/db_report-post) | Individual posts attached to a moderation report |
index 8221f279e271418fae472c03a76dcdf749d524f8..cd66ce12de7ed1f09fda446578139daadd8246f3 100644 (file)
@@ -59,7 +59,6 @@ Fields
 | remote_self               |                                                                                                                | boolean            | NO   |     | 0                   |                |
 | rel                       | The kind of the relation between the user and the contact                                                      | tinyint unsigned   | NO   |     | 0                   |                |
 | protocol                  | Protocol of the contact                                                                                        | char(4)            | NO   |     |                     |                |
-| subhub                    |                                                                                                                | boolean            | NO   |     | 0                   |                |
 | hub-verify                |                                                                                                                | varbinary(383)     | NO   |     |                     |                |
 | rating                    | Automatically detected feed poll frequency                                                                     | tinyint            | NO   |     | 0                   |                |
 | priority                  | Feed poll priority                                                                                             | tinyint unsigned   | NO   |     | 0                   |                |
index ad4ca6af32b7f0f8dfc75af610b51650d10adcc3..332cfbcb3b6f1ba4cf3bc1b3592503be6b903012 100644 (file)
@@ -18,7 +18,6 @@ Fields
 | dfrn         | Number of successful deliveries via DFRN                                                                                                                   | mediumint    | NO   |     | 0       |       |
 | legacy_dfrn  | Number of successful deliveries via legacy DFRN                                                                                                            | mediumint    | NO   |     | 0       |       |
 | diaspora     | Number of successful deliveries via Diaspora                                                                                                               | mediumint    | NO   |     | 0       |       |
-| ostatus      | Number of successful deliveries via OStatus                                                                                                                | mediumint    | NO   |     | 0       |       |
 
 Indexes
 ------------
diff --git a/doc/database/db_push_subscriber.md b/doc/database/db_push_subscriber.md
deleted file mode 100644 (file)
index fbb2ebb..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-Table push_subscriber
-===========
-
-Used for OStatus: Contains feed subscribers
-
-Fields
-------
-
-| Field        | Description                       | Type               | Null | Key | Default             | Extra          |
-| ------------ | --------------------------------- | ------------------ | ---- | --- | ------------------- | -------------- |
-| id           | sequential ID                     | int unsigned       | NO   | PRI | NULL                | auto_increment |
-| uid          | User id                           | mediumint unsigned | NO   |     | 0                   |                |
-| callback_url |                                   | varbinary(383)     | NO   |     |                     |                |
-| topic        |                                   | varchar(255)       | NO   |     |                     |                |
-| nickname     |                                   | varchar(255)       | NO   |     |                     |                |
-| push         | Retrial counter                   | tinyint            | NO   |     | 0                   |                |
-| last_update  | Date of last successful trial     | datetime           | NO   |     | 0001-01-01 00:00:00 |                |
-| next_try     | Next retrial date                 | datetime           | NO   |     | 0001-01-01 00:00:00 |                |
-| renewed      | Date of last subscription renewal | datetime           | NO   |     | 0001-01-01 00:00:00 |                |
-| secret       |                                   | varchar(255)       | NO   |     |                     |                |
-
-Indexes
-------------
-
-| Name     | Fields   |
-| -------- | -------- |
-| PRIMARY  | id       |
-| next_try | next_try |
-| uid      | uid      |
-
-Foreign Keys
-------------
-
-| Field | Target Table | Target Field |
-|-------|--------------|--------------|
-| uid | [user](help/database/db_user) | uid |
-
-Return to [database documentation](help/database)
index 220454a0ee6e628854f6a593f61874d0a700dcc9..e52d8d495c4343a1cbb3ec9265e75aa0250ddac2 100644 (file)
@@ -25,7 +25,6 @@ Fields
 | remote_self               | 0 => No mirroring, 1-2 => Mirror as own post, 3 => Mirror as reshare       | tinyint unsigned   | YES  |     | NULL    |       |
 | fetch_further_information | 0 => None, 1 => Fetch information, 3 => Fetch keywords, 2 => Fetch both    | tinyint unsigned   | YES  |     | NULL    |       |
 | ffi_keyword_denylist      |                                                                            | text               | YES  |     | NULL    |       |
-| subhub                    |                                                                            | boolean            | YES  |     | NULL    |       |
 | hub-verify                |                                                                            | varbinary(383)     | YES  |     | NULL    |       |
 | protocol                  | Protocol of the contact                                                    | char(4)            | YES  |     | NULL    |       |
 | rating                    | Automatically detected feed poll frequency                                 | tinyint            | YES  |     | NULL    |       |
index 108a689ad1fa3b21d24f967d820344bf2fb9ae58..eb8ed06532f430a87a83447b4601aebcd31046f4 100644 (file)
@@ -27,8 +27,6 @@ Fields
 | theme                    | user theme preference                                                             | varchar(255)       | NO   |     |                     |                |
 | pubkey                   | RSA public key 4096 bit                                                           | text               | YES  |     | NULL                |                |
 | prvkey                   | RSA private key 4096 bit                                                          | text               | YES  |     | NULL                |                |
-| spubkey                  |                                                                                   | text               | YES  |     | NULL                |                |
-| sprvkey                  |                                                                                   | text               | YES  |     | NULL                |                |
 | verified                 | user is verified through email                                                    | boolean            | NO   |     | 0                   |                |
 | blocked                  | 1 for user is blocked                                                             | boolean            | NO   |     | 0                   |                |
 | blockwall                | Prohibit contacts to post to the profile page of the user                         | boolean            | NO   |     | 0                   |                |
index c9f9d690acbd22162a5d8b6aed4cd7cfd1d990f8..686fd129b1c2ac5a188fe93a791ee1afad2f2a93 100644 (file)
@@ -84,7 +84,6 @@ Alternativen werden durch "|" dargestellt.
     * network:dspr | network:diaspora - Das Diaspora-Protokoll wird hauptsächlich von Diaspora selbst genutzt. Ein paar andere Systeme unterstützen dieses Protokoll ebenfalls, wie Hubzilla, Socialhome or Ganggo.
     * network:feed - RSS/Atom feeds
     * network:mail - Mails die via IMAP importiert worden sind.
-    * network:stat | network:ostatus - Das OStatus-Protokoll wird hauptsächlich von alten GNU Social-Installationen genutzt.
     * network:dscs | network:discourse - Beiträge, die über den Discourse connector empfangen werden.
     * network:tmbl | network:tumblr - Beiträge, die über den Tumblr connector empfangen werden.
     * network:bsky | network:bluesky - Beiträge, die über den Bluesky connector empfangen werden.
index 7247124ef32ea67943f48a0463931ab001048b8f..a4289c3c3043cdbcb25dae57a01b0f5fc9e9110f 100644 (file)
@@ -27,24 +27,6 @@ Ebenso kannst Du deren Identitäts-Adresse in der "Verbinden"-Box auf Deiner ["K
 
 Füge die Diaspora-Identitäts-Adresse (z.B. name@diasporapod.com)auf Deiner ["Kontakte"-Seite](contacts) in das Feld "Neuen Kontakt hinzufügen" ein. 
 
-
-**GNU Social**
-
-Dieses Netzwerk wird als "federated social web" bzw. "OStatus"-Kontakte bezeichnet.
-
-Bitte beachte, dass es **keine** Einstellungen zur Privatssphäre im OStatus-Netzwerk gibt. 
-**Jede** Nachricht, die an eines dieser OStatus-Mitglieder verschickt wird, ist für jeden auf der Welt sichtbar; alle Privatssphäreneinstellungen verlieren ihre Wirkung. 
-Diese Nachrichten erscheinen ebenfalls in öffentlichen Suchergebnissen.
-
-Da die OStatus-Kommunikation keine Authentifizierung benutzt, können OStatus-Nutzer *keine* Nachrichten empfangen, wenn Du in Deinen Privatssphäreneinstellungen "Profil und Nachrichten vor Unbekannten verbergen" wählst.
-
-Um Dich mit einem OStatus-Mitglied zu verbinden, trage deren Profil-URL oder Identitäts-Adresse auf Deiner ["Kontakte"-Seite](contacts) in das Feld "Neuen Kontakt hinzufügen" ein.
-
-Der GNU Social-Konnektor kann genutzt werden, wenn Du Beiträge schreiben willst, die auf einer OStatus-Seite über einen existierenden OStatus-Account erscheinen sollen.
-
-Das ist nicht notwendig, wenn Du OStatus-Mitgliedern von Friendica aus folgst und diese Dir auch folgen, indem sie auf Deiner Kontaktseite ihre eigene Identitäts-Adresse eingeben.
-
-
 **Blogger, Wordpress, RSS feeds, andere Webseiten**
 
 Trage die URL auf Deiner ["Kontakte"-Seite](contacts) in das Feld "Neuen Kontakt hinzufügen" ein. 
index 4b8a0c621074ec95a65baf19737ba36015482ee7..abd62989a22162119c898a01660a5d3aec73906e 100644 (file)
@@ -388,38 +388,14 @@ function photos_post()
                                foreach ($tags as $tag) {
                                        if (strpos($tag, '@') === 0) {
                                                $profile = '';
-                                               $contact = null;
                                                $name = substr($tag, 1);
-
-                                               if ((strpos($name, '@')) || (strpos($name, 'http://'))) {
+                                               $contact = Contact::getByURL($name);
+                                               if (empty($contact)) {
                                                        $newname = $name;
-                                                       $links = @Probe::lrdd($name);
-
-                                                       if (count($links)) {
-                                                               foreach ($links as $link) {
-                                                                       if ($link['@attributes']['rel'] === ActivityNamespace::WEBFINGERPROFILE) {
-                                                                               $profile = $link['@attributes']['href'];
-                                                                       }
-
-                                                                       if ($link['@attributes']['rel'] === 'salmon') {
-                                                                               $salmon = '$url:' . str_replace(',', '%sc', $link['@attributes']['href']);
-
-                                                                               if (strlen($inform)) {
-                                                                                       $inform .= ',';
-                                                                               }
-
-                                                                               $inform .= $salmon;
-                                                                       }
-                                                               }
-                                                       }
-
-                                                       $taginfo[] = [$newname, $profile, $salmon];
-                                               } else {
-                                                       $newname = $name;
-                                                       $tagcid = 0;
-
                                                        if (strrpos($newname, '+')) {
                                                                $tagcid = intval(substr($newname, strrpos($newname, '+') + 1));
+                                                       } else {
+                                                               $tagcid = 0;
                                                        }
 
                                                        if ($tagcid) {
@@ -439,17 +415,17 @@ function photos_post()
                                                                        );
                                                                }
                                                        }
+                                               }
 
-                                                       if (DBA::isResult($contact)) {
-                                                               $newname = $contact['name'];
-                                                               $profile = $contact['url'];
+                                               if (DBA::isResult($contact)) {
+                                                       $newname = $contact['name'];
+                                                       $profile = $contact['url'];
 
-                                                               $notify = 'cid:' . $contact['id'];
-                                                               if (strlen($inform)) {
-                                                                       $inform .= ',';
-                                                               }
-                                                               $inform .= $notify;
+                                                       $notify = 'cid:' . $contact['id'];
+                                                       if (strlen($inform)) {
+                                                               $inform .= ',';
                                                        }
+                                                       $inform .= $notify;
                                                }
 
                                                if ($profile) {
index 3144b1b6efc29295ff941eff3bc1ae520f2648fd..070d67ee4ff968e21db11278aa597085b8dc5519 100644 (file)
@@ -53,11 +53,8 @@ class Mode
                'objects',
                'outbox',
                'poco',
-               'pubsub',
-               'pubsubhubbub',
                'receive',
                'rsd_xml',
-               'salmon',
                'statistics_json',
                'xrd',
        ];
index 7c1fafc090d6a74c6e0931eef96248d0fe680d1a..2fa51e0085b4a108569c2ecb585a5e0fbfbc96bb 100644 (file)
@@ -25,7 +25,6 @@ use Friendica\Model\Contact;
  * @property-read int    $remoteSelf
  * @property-read int    $fetchFurtherInformation
  * @property-read string $ffiKeywordDenylist
- * @property-read bool   $subhub
  * @property-read string $hubVerify
  * @property-read string $protocol
  * @property-read int    $rating
@@ -69,8 +68,6 @@ class LocalRelationship extends \Friendica\BaseEntity
        protected $fetchFurtherInformation;
        /** @var string */
        protected $ffiKeywordDenylist;
-       /** @var bool */
-       protected $subhub;
        /** @var string */
        protected $hubVerify;
        /** @var string */
@@ -80,7 +77,7 @@ class LocalRelationship extends \Friendica\BaseEntity
        /** @var int */
        protected $priority;
 
-       public function __construct(int $userId, int $contactId, bool $blocked = false, bool $ignored = false, bool $collapsed = false, bool $hidden = false, bool $pending = false, int $rel = Contact::NOTHING, string $info = '', bool $notifyNewPosts = false, int $remoteSelf = self::MIRROR_DEACTIVATED, int $fetchFurtherInformation = self::FFI_NONE, string $ffiKeywordDenylist = '', bool $subhub = false, string $hubVerify = '', string $protocol = Protocol::PHANTOM, ?int $rating = null, ?int $priority = null)
+       public function __construct(int $userId, int $contactId, bool $blocked = false, bool $ignored = false, bool $collapsed = false, bool $hidden = false, bool $pending = false, int $rel = Contact::NOTHING, string $info = '', bool $notifyNewPosts = false, int $remoteSelf = self::MIRROR_DEACTIVATED, int $fetchFurtherInformation = self::FFI_NONE, string $ffiKeywordDenylist = '', string $hubVerify = '', string $protocol = Protocol::PHANTOM, ?int $rating = null, ?int $priority = null)
        {
                $this->userId                  = $userId;
                $this->contactId               = $contactId;
@@ -95,7 +92,6 @@ class LocalRelationship extends \Friendica\BaseEntity
                $this->remoteSelf              = $remoteSelf;
                $this->fetchFurtherInformation = $fetchFurtherInformation;
                $this->ffiKeywordDenylist      = $ffiKeywordDenylist;
-               $this->subhub                  = $subhub;
                $this->hubVerify               = $hubVerify;
                $this->protocol                = $protocol;
                $this->rating                  = $rating;
index 1190e0e3f291c061e982736c2d33d69bdf2a0d44..1cdc308ed4ae719216c0ef916ce768842d23fef0 100644 (file)
@@ -34,7 +34,6 @@ class LocalRelationship extends BaseFactory implements ICanCreateFromTableRow
                        $row['remote_self'] ?? Entity\LocalRelationship::MIRROR_DEACTIVATED,
                        $row['fetch_further_information'] ?? Entity\LocalRelationship::FFI_NONE,
                        $row['ffi_keyword_denylist'] ?? '',
-                       $row['subhub'] ?? false,
                        $row['hub-verify'] ?? '',
                        $row['protocol'] ?? Protocol::PHANTOM,
                        $row['rating'] ?? null,
index cae561ddea6b71a94486a429b72dbe20ed9ab48e..2b9abc3dfc45eac5372ce1e5931b70c67b647b9b 100644 (file)
@@ -89,7 +89,6 @@ class LocalRelationship extends \Friendica\BaseRepository
                        'remote_self'               => $localRelationship->remoteSelf,
                        'fetch_further_information' => $localRelationship->fetchFurtherInformation,
                        'ffi_keyword_denylist'      => $localRelationship->ffiKeywordDenylist,
-                       'subhub'                    => $localRelationship->subhub,
                        'hub-verify'                => $localRelationship->hubVerify,
                        'protocol'                  => $localRelationship->protocol,
                        'rating'                    => $localRelationship->rating,
index 74ccca5cefbc8ae3558f4e15900393d5f507da0a..b54beef039393c652a5da51d377b87fa3638736f 100644 (file)
@@ -48,7 +48,6 @@ class BBCode
        const CONNECTORS   = 4;
        const TWITTER_API  = 5;
        const NPF          = 6;
-       const OSTATUS      = 7;
        const TWITTER      = 8;
        const BACKLINK     = 8;
        const ACTIVITYPUB  = 9;
@@ -910,9 +909,6 @@ class BBCode
 
                                $text = ($is_quote_share ? '<hr />' : '') . $headline . '<blockquote class="shared_content" dir="auto">' . trim($content) . '</blockquote>' . "\n";
 
-                               break;
-                       case self::OSTATUS:
-                               $text = ($is_quote_share ? '<br>' : '') . '<p>' . html_entity_decode('&#x2672; ', ENT_QUOTES, 'UTF-8') . ' @' . $author_contact['addr'] . ': ' . $content . '</p>' . "\n";
                                break;
                        case self::ACTIVITYPUB:
                                $author = '@<span class="vcard"><a href="' . $author_contact['url'] . '" class="url u-url mention" title="' . $author_contact['addr'] . '"><span class="fn nickname mention">' . $author_contact['addr'] . '</span></a>:</span>';
@@ -1252,7 +1248,7 @@ class BBCode
         * - 4: Used for WordPress, Libertree (before Markdown), pump.io and tumblr
         * - 5: Unused
         * - 6: Unused
-        * - 7: Used for dfrn, OStatus
+        * - 7: Used for dfrn
         * - 8: Used for Twitter, WP backlink text setting
         * - 9: ActivityPub
         *
@@ -1283,7 +1279,7 @@ class BBCode
         * - 4: Used for WordPress, Libertree (before Markdown), pump.io and tumblr
         * - 5: Unused
         * - 6: Unused
-        * - 7: Used for dfrn, OStatus
+        * - 7: Used for dfrn
         * - 8: Used for Twitter, WP backlink text setting
         * - 9: ActivityPub
         *
@@ -1971,7 +1967,7 @@ class BBCode
                                '@<a href="$2">$3</a>',
                                $text
                        );
-               } elseif (in_array($simple_html, [self::OSTATUS, self::ACTIVITYPUB])) {
+               } elseif (in_array($simple_html, [self::ACTIVITYPUB])) {
                        $text = preg_replace(
                                "/([@!])\[url\=(.*?)\](.*?)\[\/url\]/ism",
                                '<span class="h-card"><a href="$2" class="u-url mention">$1<span>$3</span></a></span>',
@@ -2017,7 +2013,7 @@ class BBCode
                        $text
                );
 
-               if (in_array($simple_html, [self::OSTATUS, self::TWITTER, self::BLUESKY])) {
+               if (in_array($simple_html, [self::TWITTER, self::BLUESKY])) {
                        $text = preg_replace_callback("/([^#@!])\[url\=([^\]]*)\](.*?)\[\/url\]/ism", [self::class, 'expandLinksCallback'], $text);
                        //$text = preg_replace("/[^#@!]\[url\=([^\]]*)\](.*?)\[\/url\]/ism", ' $2 [url]$1[/url]', $text);
                        $text = preg_replace("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", ' $2 [url]$1[/url]', $text);
@@ -2075,7 +2071,7 @@ class BBCode
                // Red compatibility, though the link can't be authenticated on Friendica
                $text = preg_replace("/\[zrl\=(.*?)\](.*?)\[\/zrl\]/ism", '[url=$1]$2[/url]', $text);
 
-               if (in_array($simple_html, [self::INTERNAL, self::EXTERNAL, self::DIASPORA, self::OSTATUS, self::MASTODON_API, self::TWITTER_API, self::ACTIVITYPUB])) {
+               if (in_array($simple_html, [self::INTERNAL, self::EXTERNAL, self::DIASPORA, self::MASTODON_API, self::TWITTER_API, self::ACTIVITYPUB])) {
                        $text = self::shortenLinkDescription($text, $simple_html);
                } else {
                        $text = self::unifyLinks($text);
index a812ce5db48a8049cc5b23c7a97cc4f4d07ad20c..ec28f823ffd2e61da878d3a705cf5fe42618e3af 100644 (file)
@@ -119,10 +119,6 @@ class Plaintext
                                $abstract = BBCode::getAbstract($item['body'], Protocol::TWITTER);
                                break;
 
-                       case BBCode::OSTATUS:
-                               $abstract = BBCode::getAbstract($item['body'], Protocol::STATUSNET);
-                               break;
-
                        case BBCode::BLUESKY:
                                $abstract = BBCode::getAbstract($item['body'], Protocol::BLUESKY);
                                break;
index 11793921ce2f3aa2673af708bdfd92ea94510a6f..184063a5f9ed56dc46c01b2ac83f2bca7e480e9d 100644 (file)
@@ -88,17 +88,13 @@ class Widget
        public static function unavailableNetworks(): array
        {
                // Always hide content from these networks
-               $networks = [Protocol::PHANTOM, Protocol::FACEBOOK, Protocol::APPNET, Protocol::TWITTER, Protocol::ZOT];
+               $networks = [Protocol::PHANTOM, Protocol::FACEBOOK, Protocol::APPNET, Protocol::TWITTER, Protocol::ZOT, Protocol::OSTATUS, Protocol::STATUSNET];
                Addon::loadAddons();
 
                if (!Addon::isEnabled("discourse")) {
                        $networks[] = Protocol::DISCOURSE;
                }
 
-               if (!Addon::isEnabled("statusnet")) {
-                       $networks[] = Protocol::STATUSNET;
-               }
-
                if (!Addon::isEnabled("pumpio")) {
                        $networks[] = Protocol::PUMPIO;
                }
@@ -107,10 +103,6 @@ class Widget
                        $networks[] = Protocol::TUMBLR;
                }
 
-               if (DI::config()->get("system", "ostatus_disabled")) {
-                       $networks[] = Protocol::OSTATUS;
-               }
-
                if (!DI::config()->get("system", "diaspora_enabled")) {
                        $networks[] = Protocol::DIASPORA;
                }
index 9dccca52234d78d13ece49d9cf717ccb98c0042d..917f97332248693ee2f7b25dab443e355d47abd1 100644 (file)
@@ -59,7 +59,7 @@ class ContactBlock
                        'hidden'  => false,
                        'archive' => false,
                        'failed'  => false,
-                       'network' => [Protocol::DFRN, Protocol::ACTIVITYPUB, Protocol::OSTATUS, Protocol::DIASPORA, Protocol::FEED],
+                       'network' => [Protocol::DFRN, Protocol::ACTIVITYPUB, Protocol::DIASPORA, Protocol::FEED],
                ]);
 
                $contacts_title = DI::l10n()->t('No contacts');
index f2a1bf45b6507d2cf2e77a3900e7f716c3740575..e8ffe5712365dc824b3417b25362cdd5917c5252 100644 (file)
@@ -8,14 +8,10 @@
 namespace Friendica\Core;
 
 use Friendica\Database\DBA;
-use Friendica\Model\Item;
 use Friendica\Model\User;
 use Friendica\Network\HTTPException;
-use Friendica\Protocol\Activity;
 use Friendica\Protocol\ActivityPub;
 use Friendica\Protocol\Diaspora;
-use Friendica\Protocol\OStatus;
-use Friendica\Protocol\Salmon;
 
 /**
  * Manage compatibility with federated networks
@@ -28,24 +24,24 @@ class Protocol
        const DIASPORA    = 'dspr';    // Diaspora, Hubzilla, Socialhome, Ganggo
        const FEED        = 'feed';    // RSS/Atom feeds with no known "post/notify" protocol
        const MAIL        = 'mail';    // IMAP/POP
-       const OSTATUS     = 'stat';    // GNU Social and other OStatus implementations
 
-       const NATIVE_SUPPORT = [self::DFRN, self::DIASPORA, self::OSTATUS, self::FEED, self::MAIL, self::ACTIVITYPUB];
+       const NATIVE_SUPPORT = [self::DFRN, self::DIASPORA, self::FEED, self::MAIL, self::ACTIVITYPUB];
 
-       const FEDERATED = [self::DFRN, self::DIASPORA, self::OSTATUS, self::ACTIVITYPUB];
+       const FEDERATED = [self::DFRN, self::DIASPORA, self::ACTIVITYPUB];
 
        const SUPPORT_PRIVATE = [self::DFRN, self::DIASPORA, self::MAIL, self::ACTIVITYPUB, self::PUMPIO];
 
        // Supported through a connector
        const DIASPORA2 = 'dspc';    // Diaspora connector
        const PUMPIO    = 'pump';    // pump.io
-       const STATUSNET = 'stac';    // Statusnet connector
        const TWITTER   = 'twit';    // Twitter
        const DISCOURSE = 'dscs';    // Discourse
        const TUMBLR    = 'tmbl';    // Tumblr
        const BLUESKY   = 'bsky';    // Bluesky
 
        // Dead protocols
+       const OSTATUS   = 'stat';    // GNU Social and other OStatus implementations
+       const STATUSNET = 'stac';    // Statusnet connector
        const APPNET    = 'apdn';    // app.net - Dead protocol
        const FACEBOOK  = 'face';    // Facebook API - Not working anymore, API is closed
        const GPLUS     = 'goog';    // Google+ - Dead in 2019
@@ -124,27 +120,10 @@ class Protocol
 
                $protocol = $protocol ?? $contact['protocol'];
 
-               if (in_array($protocol, [Protocol::OSTATUS, Protocol::DFRN])) {
-                       // create a follow slap
-                       $item = [
-                               'verb'    => Activity::FOLLOW,
-                               'gravity' => Item::GRAVITY_ACTIVITY,
-                               'follow'  => $contact['url'],
-                               'body'    => '',
-                               'title'   => '',
-                               'guid'    => '',
-                               'uri-id'  => 0,
-                       ];
-
-                       $slap = OStatus::salmon($item, $owner);
-
-                       if (!empty($contact['notify'])) {
-                               Salmon::slapper($owner, $contact['notify'], $slap);
-                       }
-               } elseif ($protocol == Protocol::DIASPORA) {
+               if ($protocol == self::DIASPORA) {
                        $contact = Diaspora::sendShare($owner, $contact);
                        Logger::notice('share returns: ' . $contact);
-               } elseif ($protocol == Protocol::ACTIVITYPUB) {
+               } elseif (in_array($protocol, [self::ACTIVITYPUB, self::DFRN])) {
                        $activity_id = ActivityPub\Transmitter::activityIDFromContact($contact['id']);
                        if (empty($activity_id)) {
                                // This really should never happen
@@ -175,33 +154,13 @@ class Protocol
                }
 
                $protocol = $contact['network'];
-               if (($protocol == Protocol::DFRN) && !empty($contact['protocol'])) {
+               if (($protocol == self::DFRN) && !empty($contact['protocol'])) {
                        $protocol = $contact['protocol'];
                }
 
-               if (in_array($protocol, [Protocol::OSTATUS, Protocol::DFRN])) {
-                       // create an unfollow slap
-                       $item = [
-                               'verb'    => Activity::O_UNFOLLOW,
-                               'gravity' => Item::GRAVITY_ACTIVITY,
-                               'follow'  => $contact['url'],
-                               'body'    => '',
-                               'title'   => '',
-                               'guid'    => '',
-                               'uri-id'  => 0,
-                       ];
-
-                       $slap = OStatus::salmon($item, $owner);
-
-                       if (empty($contact['notify'])) {
-                               Logger::notice('OStatus/DFRN Contact is missing notify, we quit here', ['id' => $contact['id']]);
-                               return null;
-                       }
-
-                       return Salmon::slapper($owner, $contact['notify'], $slap) === 0;
-               } elseif ($protocol == Protocol::DIASPORA) {
+               if ($protocol == self::DIASPORA) {
                        return Diaspora::sendUnshare($owner, $contact) > 0;
-               } elseif ($protocol == Protocol::ACTIVITYPUB) {
+               } elseif (in_array($protocol, [self::ACTIVITYPUB, self::DFRN])) {
                        return ActivityPub\Transmitter::sendContactUndo($contact['url'], $contact['id'], $owner);
                }
 
@@ -232,11 +191,11 @@ class Protocol
                }
 
                $protocol = $contact['network'];
-               if ($protocol == Protocol::DFRN && !empty($contact['protocol'])) {
+               if ($protocol == self::DFRN && !empty($contact['protocol'])) {
                        $protocol = $contact['protocol'];
                }
 
-               if ($protocol == Protocol::ACTIVITYPUB) {
+               if ($protocol == self::ACTIVITYPUB) {
                        return ActivityPub\Transmitter::sendContactReject($contact['url'], $contact['hub-verify'], $owner);
                }
 
index d3abc8c3ce53367aaeddce2e7973185f5882c2e1..f9be27da1028c00f625349769e592e7673627c3d 100644 (file)
@@ -72,7 +72,7 @@ class DBStructure
                $old_tables = ['fserver', 'gcign', 'gcontact', 'gcontact-relation', 'gfollower' ,'glink', 'item-delivery-data',
                        'item-activity', 'item-content', 'item_id', 'participation', 'poll', 'poll_result', 'queue', 'retriever_rule',
                        'deliverq', 'dsprphotoq', 'ffinder', 'sign', 'spam', 'term', 'user-item', 'thread', 'item', 'challenge',
-                       'auth_codes', 'tokens', 'clients', 'profile_check', 'host', 'conversation', 'fcontact', 'addon'];
+                       'auth_codes', 'tokens', 'clients', 'profile_check', 'host', 'conversation', 'fcontact', 'addon', 'push_subscriber'];
 
                $tables = DBA::selectToArray('INFORMATION_SCHEMA.TABLES', ['TABLE_NAME'],
                        ['TABLE_SCHEMA' => DBA::databaseName(), 'TABLE_TYPE' => 'BASE TABLE']);
index 8c055f3c02323672c95cc01d229eeafe23ffd583..c6bdba2dc0b24601893a01396529f3d4d56bb7f6 100644 (file)
@@ -788,10 +788,8 @@ class Contact
                        'url'         => DI::baseUrl() . '/profile/' . $user['nickname'],
                        'nurl'        => Strings::normaliseLink(DI::baseUrl() . '/profile/' . $user['nickname']),
                        'addr'        => $user['nickname'] . '@' . substr(DI::baseUrl(), strpos(DI::baseUrl(), '://') + 3),
-                       'request'     => DI::baseUrl() . '/dfrn_request/' . $user['nickname'],
-                       'notify'      => DI::baseUrl() . '/dfrn_notify/'  . $user['nickname'],
-                       'poll'        => DI::baseUrl() . '/dfrn_poll/'    . $user['nickname'],
-                       'confirm'     => DI::baseUrl() . '/dfrn_confirm/' . $user['nickname'],
+                       'notify'      => DI::baseUrl() . '/dfrn_notify/' . $user['nickname'],
+                       'poll'        => DI::baseUrl() . '/feed/' . $user['nickname'],
                        'name-date'   => DateTimeFormat::utcNow(),
                        'uri-date'    => DateTimeFormat::utcNow(),
                        'avatar-date' => DateTimeFormat::utcNow(),
@@ -873,10 +871,8 @@ class Contact
                        'nurl'         => Strings::normaliseLink($url),
                        'uri-id'       => ItemURI::getIdByURI($url),
                        'addr'         => $user['nickname'] . '@' . substr(DI::baseUrl(), strpos(DI::baseUrl(), '://') + 3),
-                       'request'      => DI::baseUrl() . '/dfrn_request/' . $user['nickname'],
                        'notify'       => DI::baseUrl() . '/dfrn_notify/' . $user['nickname'],
-                       'poll'         => DI::baseUrl() . '/dfrn_poll/' . $user['nickname'],
-                       'confirm'      => DI::baseUrl() . '/dfrn_confirm/' . $user['nickname'],
+                       'poll'         => DI::baseUrl() . '/feed/' . $user['nickname'],
                ];
 
                $avatar = Photo::selectFirst(['resource-id', 'type'], ['uid' => $uid, 'profile' => true]);
@@ -2532,22 +2528,6 @@ class Contact
                }
 
                self::update($fields, $condition);
-
-               // We mustn't set the update fields for OStatus contacts since they are updated in OnePoll
-               $condition['network'] = Protocol::OSTATUS;
-
-               // If the contact failed, propagate the update fields to all contacts
-               if (empty($fields['failed'])) {
-                       unset($fields['last-update']);
-                       unset($fields['success_update']);
-                       unset($fields['failure_update']);
-               }
-
-               if (empty($fields)) {
-                       return;
-               }
-
-               self::update($fields, $condition);
        }
 
        /**
@@ -3065,11 +3045,6 @@ class Contact
        /**
         * Takes a $uid and a url/handle and adds a new contact
         *
-        * Currently if the contact is DFRN, interactive needs to be true, to redirect to the
-        * dfrn_request page.
-        *
-        * Otherwise this can be used to bulk add StatusNet contacts, Twitter contacts, etc.
-        *
         * Returns an array
         * $return['success'] boolean true if successful
         * $return['message'] error text if success is false.
@@ -3170,35 +3145,24 @@ class Contact
                        return $result;
                }
 
-               if ($protocol === Protocol::OSTATUS && DI::config()->get('system', 'ostatus_disabled')) {
-                       $result['message'] .= DI::l10n()->t('The profile address specified belongs to a network which has been disabled on this site.') . '<br />';
-                       $ret['notify'] = '';
-               }
-
                if (!$ret['notify']) {
                        $result['message'] .= DI::l10n()->t('Limited profile. This person will be unable to receive direct/personal notifications from you.') . '<br />';
                }
 
-               $writeable = ((($protocol === Protocol::OSTATUS) && ($ret['notify'])) ? 1 : 0);
-
-               $subhub = (($protocol === Protocol::OSTATUS) ? true : false);
-
-               $hidden = (($protocol === Protocol::MAIL) ? 1 : 0);
+               $hidden = ($protocol === Protocol::MAIL);
 
                $pending = false;
                if (($protocol == Protocol::ACTIVITYPUB) && isset($ret['manually-approve'])) {
                        $pending = (bool)$ret['manually-approve'];
                }
 
-               if (in_array($protocol, [Protocol::MAIL, Protocol::DIASPORA, Protocol::ACTIVITYPUB])) {
-                       $writeable = 1;
-               }
+               $writeable = in_array($protocol, [Protocol::MAIL, Protocol::DIASPORA, Protocol::ACTIVITYPUB]);
 
                if (DBA::isResult($contact)) {
                        // update contact
                        $new_relation = (in_array($contact['rel'], [self::FOLLOWER, self::FRIEND]) ? self::FRIEND : self::SHARING);
 
-                       $fields = ['rel' => $new_relation, 'subhub' => $subhub, 'readonly' => false, 'network' => $ret['network']];
+                       $fields = ['rel' => $new_relation, 'readonly' => false, 'network' => $ret['network']];
 
                        if ($contact['pending'] && !empty($contact['hub-verify'])) {
                                ActivityPub\Transmitter::sendContactAccept($contact['url'], $contact['hub-verify'], $uid);
@@ -3236,7 +3200,6 @@ class Contact
                                'blocked'      => 0,
                                'readonly'     => 0,
                                'pending'      => $pending,
-                               'subhub'       => $subhub
                        ]);
                }
 
@@ -3258,11 +3221,6 @@ class Contact
                // Update the avatar
                self::updateAvatar($contact_id, $ret['photo']);
 
-               // pull feed and consume it, which should subscribe to the hub.
-               if ($contact['network'] == Protocol::OSTATUS) {
-                       Worker::add(Worker::PRIORITY_HIGH, 'OnePoll', $contact_id, 'force');
-               }
-
                if ($probed) {
                        GServer::updateFromProbeArray($ret);
                        self::updateFromProbeArray($contact_id, $ret);
@@ -3733,10 +3691,6 @@ class Contact
                        $networks[] = Protocol::DIASPORA;
                }
 
-               if (!DI::config()->get('system', 'ostatus_disabled')) {
-                       $networks[] = Protocol::OSTATUS;
-               }
-
                $condition = [
                        'network'        => $networks,
                        'server-failed'  => false,
index 4245bbe091a6ecc9ace2457f0baeb9fa54502807..036213045f29e010aa520fd8b10178534ffbf1e9 100644 (file)
@@ -284,7 +284,7 @@ class Relation
                        return false;
                }
 
-               if (!in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS])) {
+               if (!in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN])) {
                        $apcontact = APContact::getByURL($url, false);
                        if (empty($apcontact)) {
                                Logger::info('No discovery - The contact does not seem to speak ActivityPub.', ['id' => $contact['id'], 'url' => $url, 'network' => $contact['network']]);
@@ -369,7 +369,6 @@ class Relation
                Logger::info('Collecting suggestions', ['uid' => $uid, 'cid' => $cid, 'start' => $start, 'limit' => $limit]);
 
                $diaspora = DI::config()->get('system', 'diaspora_enabled') ? Protocol::DIASPORA : Protocol::ACTIVITYPUB;
-               $ostatus = !DI::config()->get('system', 'ostatus_disabled') ? Protocol::OSTATUS : Protocol::ACTIVITYPUB;
 
                // The query returns contacts where contacts interacted with whom the given user follows.
                // Contacts who already are in the user's contact table are ignored.
@@ -377,12 +376,12 @@ class Relation
                                (SELECT `cid` FROM `contact-relation` WHERE `relation-cid` = ?)
                                        AND NOT `cid` IN (SELECT `id` FROM `contact` WHERE `uid` = ? AND `nurl` IN
                                                (SELECT `nurl` FROM `contact` WHERE `uid` = ? AND `rel` IN (?, ?))) AND `id` = `cid`)
-                       AND NOT `hidden` AND `network` IN (?, ?, ?, ?)
+                       AND NOT `hidden` AND `network` IN (?, ?, ?)
                        AND NOT `uri-id` IN (SELECT `uri-id` FROM `account-suggestion` WHERE `uri-id` = `contact`.`uri-id` AND `uid` = ?)",
                        $cid,
                        0,
                        $uid, Contact::FRIEND, Contact::SHARING,
-                       Protocol::ACTIVITYPUB, Protocol::DFRN, $diaspora, $ostatus, $uid
+                       Protocol::ACTIVITYPUB, Protocol::DFRN, $diaspora, $uid
                        ], [
                                'order' => ['last-item' => true],
                                'limit' => $totallimit,
@@ -408,10 +407,10 @@ class Relation
                                (SELECT `relation-cid` FROM `contact-relation` WHERE `cid` = ?)
                                        AND NOT `cid` IN (SELECT `id` FROM `contact` WHERE `uid` = ? AND `nurl` IN
                                                (SELECT `nurl` FROM `contact` WHERE `uid` = ? AND `rel` IN (?, ?))) AND `id` = `cid`)
-                       AND NOT `hidden` AND `network` IN (?, ?, ?, ?)
+                       AND NOT `hidden` AND `network` IN (?, ?, ?)
                        AND NOT `uri-id` IN (SELECT `uri-id` FROM `account-suggestion` WHERE `uri-id` = `contact`.`uri-id` AND `uid` = ?)",
                        $cid, 0, $uid, Contact::FRIEND, Contact::SHARING,
-                       Protocol::ACTIVITYPUB, Protocol::DFRN, $diaspora, $ostatus, $uid],
+                       Protocol::ACTIVITYPUB, Protocol::DFRN, $diaspora, $uid],
                        ['order' => ['last-item' => true], 'limit' => $totallimit]
                );
 
@@ -429,10 +428,10 @@ class Relation
                // The query returns contacts that follow the given user but aren't followed by that user.
                $results = DBA::select('contact', [],
                        ["`nurl` IN (SELECT `nurl` FROM `contact` WHERE `uid` = ? AND `rel` = ?)
-                       AND NOT `hidden` AND `uid` = ? AND `network` IN (?, ?, ?, ?)
+                       AND NOT `hidden` AND `uid` = ? AND `network` IN (?, ?, ?)
                        AND NOT `uri-id` IN (SELECT `uri-id` FROM `account-suggestion` WHERE `uri-id` = `contact`.`uri-id` AND `uid` = ?)",
                        $uid, Contact::FOLLOWER, 0,
-                       Protocol::ACTIVITYPUB, Protocol::DFRN, $diaspora, $ostatus, $uid],
+                       Protocol::ACTIVITYPUB, Protocol::DFRN, $diaspora, $uid],
                        ['order' => ['last-item' => true], 'limit' => $totallimit]
                );
 
@@ -450,10 +449,10 @@ class Relation
                // The query returns any contact that isn't followed by that user.
                $results = DBA::select('contact', [],
                        ["NOT `nurl` IN (SELECT `nurl` FROM `contact` WHERE `uid` = ? AND `rel` IN (?, ?) AND `nurl` = `nurl`)
-                       AND NOT `hidden` AND `uid` = ? AND `network` IN (?, ?, ?, ?)
+                       AND NOT `hidden` AND `uid` = ? AND `network` IN (?, ?, ?)
                        AND NOT `uri-id` IN (SELECT `uri-id` FROM `account-suggestion` WHERE `uri-id` = `contact`.`uri-id` AND `uid` = ?)",
                        $uid, Contact::FRIEND, Contact::SHARING, 0,
-                       Protocol::ACTIVITYPUB, Protocol::DFRN, $diaspora, $ostatus, $uid],
+                       Protocol::ACTIVITYPUB, Protocol::DFRN, $diaspora, $uid],
                        ['order' => ['last-item' => true], 'limit' => $totallimit]
                );
 
index a76297c3706fd4b86d4b776d09525bff92bb2f24..510dd0f1c0240c2b17bea120aaba90247aeb296f 100644 (file)
@@ -16,7 +16,7 @@ class Conversation
        const PARCEL_ACTIVITYPUB        = 0;
        const PARCEL_DFRN               = 1; // Deprecated
        const PARCEL_DIASPORA           = 2;
-       const PARCEL_SALMON             = 3;
+       const PARCEL_SALMON             = 3; // @deprecated since version 2024.09
        const PARCEL_FEED               = 4; // Deprecated
        const PARCEL_SPLIT_CONVERSATION = 6; // @deprecated since version 2022.09
        const PARCEL_LEGACY_DFRN        = 7; // @deprecated since version 2021.09
index 207fe8b324efd8a8942430476a7542b413dce11f..bda394cc84de7736329b9ad17e891a6307f1bfa1 100644 (file)
@@ -2617,11 +2617,6 @@ class GServer
                                return;
                        }
 
-                       // We don't want to mark a server as OStatus when it had been marked with any other protocol before
-                       if ($protocol == Post\DeliveryData::OSTATUS) {
-                               return;
-                       }
-
                        // If the server is marked as ActivityPub then we won't change it to anything different
                        if ($old == Post\DeliveryData::ACTIVITYPUB) {
                                return;
index cb5857388a4ce06585fe665bb2bab63a22f15172..c4c6fa3d8b27d882c4bfd0087578257d5558ecf7 100644 (file)
@@ -602,16 +602,6 @@ class Item
                                Logger::notice('duplicated item with the same guid found.', $condition);
                                return true;
                        }
-               } elseif ($item['network'] == Protocol::OSTATUS) {
-                       // Check for an existing post with the same content. There seems to be a problem with OStatus.
-                       $condition = [
-                               "`body` = ? AND `network` = ? AND `created` = ? AND `contact-id` = ? AND `uid` = ?",
-                               $item['body'], $item['network'], $item['created'], $item['contact-id'], $item['uid']
-                       ];
-                       if (Post::exists($condition)) {
-                               Logger::notice('duplicated item with the same body found.', $item);
-                               return true;
-                       }
                }
 
                /*
@@ -705,13 +695,12 @@ class Item
        {
                if (empty($item['network']) || in_array($item['network'], Protocol::FEDERATED)) {
                        $condition = [
-                               '`uri-id` = ? AND `uid` = ? AND `network` IN (?, ?, ?, ?)',
+                               '`uri-id` = ? AND `uid` = ? AND `network` IN (?, ?, ?)',
                                $item['uri-id'],
                                $item['uid'],
                                Protocol::ACTIVITYPUB,
                                Protocol::DIASPORA,
-                               Protocol::DFRN,
-                               Protocol::OSTATUS
+                               Protocol::DFRN
                        ];
                        $existing = Post::selectFirst(['id', 'network'], $condition);
                        if (DBA::isResult($existing)) {
@@ -908,7 +897,7 @@ class Item
                /*
                 * Do we already have this item?
                 * We have to check several networks since Friendica posts could be repeated
-                * via OStatus (maybe Diaspora as well)
+                * via Diaspora.
                 */
                $duplicate = self::getDuplicateID($item);
                if ($duplicate) {
index af50aaf58ff2975dcb8a45a6f9325fe185f8ed4a..0c3dd35c5f4bc95d3d2174709e9fa4dc19417164 100644 (file)
@@ -29,7 +29,7 @@ class DeliveryData
        const DFRN = 2;
        const LEGACY_DFRN = 3; // @deprecated since version 2021.09
        const DIASPORA = 4;
-       const OSTATUS = 5;
+       const OSTATUS = 5; // @deprecated since version 2024.09
        const MAIL = 6;
 
        /**
@@ -83,9 +83,6 @@ class DeliveryData
                        case self::DIASPORA:
                                $increments[] = "`diaspora` = `diaspora` + 1";
                                break;
-                       case self::OSTATUS:
-                               $increments[] = "`ostatus` = `ostatus` + 1";
-                               break;
                }
 
                return DBA::update('post-delivery-data', $increments, ['uri-id' => $uri_id]);
index d7c00a5f194db5c8f8a0d052c1475ab4a2ec50b5..45e0fc15b2095b347d062b8b5664b163b95a852b 100644 (file)
@@ -30,8 +30,8 @@ class Engagement
        const ALTERNATIVES = ['source:news' => 'source:service', 'source:relay' => 'source:application',
                'media:picture' => 'media:image', 'media:photo' => 'media:image',
                'network:activitypub' => 'network:apub', 'network:friendica' => 'network:dfrn',
-               'network:diaspora' => 'network:dspr', 'network:ostatus' => 'network:stat',
-               'network:discourse' => 'network:dscs', 'network:tumblr' => 'network:tmbl', 'network:bluesky' => 'network:bsky'];
+               'network:diaspora' => 'network:dspr', 'network:discourse' => 'network:dscs',
+               'network:tumblr' => 'network:tmbl', 'network:bluesky' => 'network:bsky'];
        const MEDIA_NONE = 0;
        const MEDIA_IMAGE = 1;
        const MEDIA_VIDEO = 2;
diff --git a/src/Model/PushSubscriber.php b/src/Model/PushSubscriber.php
deleted file mode 100644 (file)
index e266e44..0000000
+++ /dev/null
@@ -1,174 +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\Model;
-
-use Friendica\Core\Logger;
-use Friendica\Core\Worker;
-use Friendica\Database\DBA;
-use Friendica\Util\DateTimeFormat;
-use GuzzleHttp\Psr7\Uri;
-
-class PushSubscriber
-{
-       /**
-        * Send subscription notifications for the given user
-        *
-        * @param integer $uid User ID
-        * @param int     $default_priority
-        * @return void
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        */
-       public static function publishFeed(int $uid, int $default_priority = Worker::PRIORITY_HIGH)
-       {
-               $condition = ['push' => 0, 'uid' => $uid];
-               DBA::update('push_subscriber', ['push' => 1, 'next_try' => DBA::NULL_DATETIME], $condition);
-
-               self::requeue($default_priority);
-       }
-
-       /**
-        * start workers to transmit the feed data
-        *
-        * @param int $default_priority
-        * @return void
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        */
-       public static function requeue(int $default_priority = Worker::PRIORITY_HIGH)
-       {
-               // We'll push to each subscriber that has push > 0,
-               // i.e. there has been an update (set in notifier.php).
-               $subscribers = DBA::select('push_subscriber', ['id', 'push', 'callback_url', 'nickname'], ["`push` > 0 AND `next_try` < ?", DateTimeFormat::utcNow()]);
-
-               while ($subscriber = DBA::fetch($subscribers)) {
-                       // We always handle retries with low priority
-                       if ($subscriber['push'] > 1) {
-                               $priority = Worker::PRIORITY_LOW;
-                       } else {
-                               $priority = $default_priority;
-                       }
-
-                       Logger::info('Publish feed to ' . $subscriber['callback_url'] . ' for ' . $subscriber['nickname'] . ' with priority ' . $priority);
-                       Worker::add($priority, 'PubSubPublish', (int)$subscriber['id']);
-               }
-
-               DBA::close($subscribers);
-       }
-
-       /**
-        * Renew the feed subscription
-        *
-        * @param integer $uid          User ID
-        * @param string  $nick         Priority for push workers
-        * @param integer $subscribe    Subscribe (Unsubscribe = false)
-        * @param string  $hub_callback Callback address
-        * @param string  $hub_topic    Feed topic
-        * @param string  $hub_secret   Subscription secret
-        * @return void
-        * @throws \Exception
-        */
-       public static function renew(int $uid, string $nick, int $subscribe, string $hub_callback, string $hub_topic, string $hub_secret)
-       {
-               // fetch the old subscription if it exists
-               $subscriber = DBA::selectFirst('push_subscriber', ['last_update', 'push'], ['callback_url' => $hub_callback]);
-
-               // delete old subscription if it exists
-               DBA::delete('push_subscriber', ['callback_url' => $hub_callback]);
-
-               if ($subscribe) {
-                       // if we are just updating an old subscription, keep the
-                       // old values for last_update but reset the push
-                       if (DBA::isResult($subscriber)) {
-                               $last_update = $subscriber['last_update'];
-                               $push_flag = min($subscriber['push'], 1);
-                       } else {
-                               $last_update = DateTimeFormat::utcNow();
-                               $push_flag = 0;
-                       }
-
-                       // subscribe means adding the row to the table
-                       $fields = ['uid' => $uid, 'callback_url' => $hub_callback,
-                               'topic' => $hub_topic, 'nickname' => $nick, 'push' => $push_flag,
-                               'last_update' => $last_update, 'renewed' => DateTimeFormat::utcNow(),
-                               'secret' => $hub_secret];
-                       DBA::insert('push_subscriber', $fields);
-
-                       Logger::notice("Successfully subscribed [$hub_callback] for $nick");
-               } else {
-                       Logger::notice("Successfully unsubscribed [$hub_callback] for $nick");
-                       // we do nothing here, since the row was already deleted
-               }
-       }
-
-       /**
-        * Delay the push subscriber
-        *
-        * @param integer $id Subscriber ID
-        * @return void
-        * @throws \Exception
-        */
-       public static function delay(int $id)
-       {
-               $subscriber = DBA::selectFirst('push_subscriber', ['push', 'callback_url', 'renewed', 'nickname'], ['id' => $id]);
-               if (!DBA::isResult($subscriber)) {
-                       return;
-               }
-
-               $retrial = $subscriber['push'];
-
-               if ($retrial > 14) {
-                       // End subscriptions if they weren't renewed for more than two months
-                       $days = round((time() -  strtotime($subscriber['renewed'])) / (60 * 60 * 24));
-
-                       if ($days > 60) {
-                               DBA::update('push_subscriber', ['push' => -1, 'next_try' => DBA::NULL_DATETIME], ['id' => $id]);
-                               Logger::info('Delivery error: Subscription ' . $subscriber['callback_url'] . ' for ' . $subscriber['nickname'] . ' is marked as ended.');
-                       } else {
-                               DBA::update('push_subscriber', ['push' => 0, 'next_try' => DBA::NULL_DATETIME], ['id' => $id]);
-                               Logger::info('Delivery error: Giving up ' . $subscriber['callback_url'] . ' for ' . $subscriber['nickname'] . ' for now.');
-                       }
-               } else {
-                       // Calculate the delay until the next trial
-                       $delay = (($retrial + 3) ** 4) + (rand(1, 30) * ($retrial + 1));
-                       $next = DateTimeFormat::utc('now + ' . $delay . ' seconds');
-
-                       $retrial = $retrial + 1;
-
-                       DBA::update('push_subscriber', ['push' => $retrial, 'next_try' => $next], ['id' => $id]);
-                       Logger::info('Delivery error: Next try (' . $retrial . ') ' . $subscriber['callback_url'] . ' for ' . $subscriber['nickname'] . ' at ' . $next);
-               }
-       }
-
-       /**
-        * Reset the push subscriber
-        *
-        * @param integer $id          Subscriber ID
-        * @param string  $last_update Date of last transmitted item
-        * @return void
-        * @throws \Exception
-        */
-       public static function reset(int $id, string $last_update)
-       {
-               $subscriber = DBA::selectFirst('push_subscriber', ['callback_url', 'nickname'], ['id' => $id]);
-               if (!DBA::isResult($subscriber)) {
-                       return;
-               }
-
-               // set last_update to the 'created' date of the last item, and reset push=0
-               $fields = ['push' => 0, 'next_try' => DBA::NULL_DATETIME, 'last_update' => $last_update];
-               DBA::update('push_subscriber', $fields, ['id' => $id]);
-               Logger::info('Subscriber ' . $subscriber['callback_url'] . ' for ' . $subscriber['nickname'] . ' is marked as vital');
-
-               $parts = parse_url($subscriber['callback_url']);
-               unset($parts['path']);
-               $server_url = (string)Uri::fromParts((array)$parts);
-               $gsid = GServer::getID($server_url, true);
-               if (!empty($gsid)) {
-                       GServer::setProtocol($gsid, Post\DeliveryData::OSTATUS);
-               }
-       }
-}
index ba2016be27160b632c4274819af16b4656fb4537..07767b4991952cb6ef3985f2a4300a233a0018ea 100644 (file)
@@ -594,9 +594,9 @@ class Tag
        public static function countByTag(string $search, int $uid = 0): int
        {
                $condition = ["`name` = ? AND (`uid` = ? OR (`uid` = ? AND NOT `global`))
-                       AND (`network` IN (?, ?, ?, ?) OR (`uid` = ? AND `uid` != ?))",
+                       AND (`network` IN (?, ?, ?) OR (`uid` = ? AND `uid` != ?))",
                        $search, 0, $uid,
-                       Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS, $uid, 0,
+                       Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, $uid, 0,
                ];
 
                return DBA::count('tag-search-view', $condition);
@@ -615,9 +615,9 @@ class Tag
        public static function getURIIdListByTag(string $search, int $uid = 0, int $start = 0, int $limit = 100, int $last_uriid = 0): array
        {
                $condition = ["`name` = ? AND (`uid` = ? OR (`uid` = ? AND NOT `global`))
-                       AND (`network` IN (?, ?, ?, ?) OR (`uid` = ? AND `uid` != ?))",
+                       AND (`network` IN (?, ?, ?) OR (`uid` = ? AND `uid` != ?))",
                        $search, 0, $uid,
-                       Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS, $uid, 0,
+                       Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, $uid, 0,
                ];
 
                if (!empty($last_uriid)) {
index 2a68e8f89937ad15a6502265122d511ff506ecc2..3310695a8e8f714ed2377fb14e7faecae2b4bfba 100644 (file)
@@ -152,8 +152,8 @@ class User
                }
 
                $system['name'] = App::PLATFORM . " '" . App::CODENAME . "' " . App::VERSION . '-' . DB_UPDATE_VERSION;
-               $system['sprvkey'] = $system['uprvkey'] = $system['prvkey'];
-               $system['spubkey'] = $system['upubkey'] = $system['pubkey'];
+               $system['uprvkey'] = $system['prvkey'];
+               $system['upubkey'] = $system['pubkey'];
                $system['nickname'] = $system['nick'];
                $system['page-flags'] = self::PAGE_FLAGS_SOAPBOX;
                $system['account-type'] = $system['contact-type'];
@@ -183,8 +183,6 @@ class User
                                'register_date' => $system['created'],
                                'pubkey' => $system['pubkey'],
                                'prvkey' => $system['prvkey'],
-                               'spubkey' => $system['spubkey'],
-                               'sprvkey' => $system['sprvkey'],
                                'guid' => System::createUUID(),
                                'verified' => true,
                                'page-flags' => self::PAGE_FLAGS_SOAPBOX,
@@ -1315,11 +1313,6 @@ class User
                $prvkey = $keys['prvkey'];
                $pubkey = $keys['pubkey'];
 
-               // Create another keypair for signing/verifying salmon protocol messages.
-               $sres = Crypto::newKeypair(512);
-               $sprvkey = $sres['prvkey'];
-               $spubkey = $sres['pubkey'];
-
                $insert_result = DBA::insert('user', [
                        'guid'     => System::createUUID(),
                        'username' => $username,
@@ -1329,8 +1322,6 @@ class User
                        'nickname' => $nickname,
                        'pubkey'   => $pubkey,
                        'prvkey'   => $prvkey,
-                       'spubkey'  => $spubkey,
-                       'sprvkey'  => $sprvkey,
                        'verified' => $verified,
                        'blocked'  => $blocked,
                        'language' => $language,
index a1d4ca772c69d5bbc72cea2b192540a08686253f..c162acce9bbc2a2a7e72d7bebd7b890860cc27c1 100644 (file)
@@ -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).')],
index a64cacf011c89aaff4fc8a51c451f4ff19d02a95..e87c710b09ef4d25bd052c797827aad287724218 100644 (file)
@@ -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);
index 92f05bb8ab2ca80ea066b4390c47c3d41483d533..3cd3fc2dcd7f03243e152ed55ed7505e592b99f8 100644 (file)
@@ -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`)"]);
index 32b82cc680e19892510939a6bc55db51879d9861..62b16816562a39b9a1caf0220c9ec8ef610268ed 100644 (file)
@@ -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]);
                }
        }
 
index b8995b2ba1962baa9a51ac3cdea1ee25ae53572b..23f88d9e2dd40198b1113c554241382042c9cbc0 100644 (file)
@@ -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'];
                }
index fd7626f6b5ba578f7b3202d5b90a03f31704795a..b0125179082137944183574db7fa8cd83fbbcaf1 100644 (file)
@@ -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');
index 9290e8ffed6e75cc6c187f94747a8cf6d17dfd74..f7178f74881c00dbb280ee202667abb807153b5a 100644 (file)
@@ -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;
                }
diff --git a/src/Module/DFRN/Poll.php b/src/Module/DFRN/Poll.php
deleted file mode 100644 (file)
index 099fd51..0000000
+++ /dev/null
@@ -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);
-       }
-}
index 11c7386f629147cd939be6ee8491370ab408d756..95dcbf598d25b3162cbf3237e9bbad983af74469 100644 (file)
@@ -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";
                }
 
index 40b30704300868bbb3dea456ba579c378ecd7cf3..9ea239e0eaba5bc0ffbd05a2beca9d731cdf7a99 100644 (file)
@@ -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}";
                }
index 3d5a288a55f063d5be75aad7c206956d236e07ed..2e58e6edd53379429a9ce4054d1ffa0a5c6e0a8c 100644 (file)
@@ -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';
index 7711daf4f35cded951aecb208b538fd2cb129769..fc1e48171a58b37c532a25051527274ad7f97e2f 100644 (file)
@@ -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';
index 5d5ce309365cb076336b0f14fb0d3e7bc69f7c90..6a343c1c9d2d0f1fdd5acf13fe6b10cd84081df8 100644 (file)
@@ -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';
index 6c8e62e52d138fe684a1922717359b73704759ac..0ad5b71ff8dd48151cb2a6eba8a322300d3808c5 100644 (file)
@@ -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';
index 743de88c67b23bf22116929bb68a2dd58af38185..04a1635d86caea6bcf81d2a1ccfee362c0eca0cb 100644 (file)
@@ -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';
diff --git a/src/Module/OStatus/PubSub.php b/src/Module/OStatus/PubSub.php
deleted file mode 100644 (file)
index 45cf614..0000000
+++ /dev/null
@@ -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);
-       }
-}
diff --git a/src/Module/OStatus/PubSubHubBub.php b/src/Module/OStatus/PubSubHubBub.php
deleted file mode 100644 (file)
index d010891..0000000
+++ /dev/null
@@ -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();
-       }
-}
diff --git a/src/Module/OStatus/Repair.php b/src/Module/OStatus/Repair.php
deleted file mode 100644 (file)
index 28ef89a..0000000
+++ /dev/null
@@ -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,
-               ]);
-       }
-}
diff --git a/src/Module/OStatus/Salmon.php b/src/Module/OStatus/Salmon.php
deleted file mode 100644 (file)
index 18f207a..0000000
+++ /dev/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();
-       }
-}
index 09cdf3cec61af9959dadce7d98a4334ead9f263c..539b132c1eb0489609c1a36578a97f322513545e 100644 (file)
@@ -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);
index 9f370bbad9d417a85fa981f61e4db346b2e5262e..09bac2cee680c34f11f844d5e75d7c61231f4782 100644 (file)
@@ -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) {
index a598015e5281d7dcf01a81910bd4e96095528c47..20ff5040e5b63f46f3edfa7d3550de56e3608870 100644 (file)
@@ -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";
index 844a16a6be36c16c59ca62756d0c78cc1df7a3ba..5df1afc3c01e5151c688a77b2e2c0cfd5d442bea 100644 (file)
@@ -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";
                }
diff --git a/src/Module/PublicRSAKey.php b/src/Module/PublicRSAKey.php
deleted file mode 100644 (file)
index b90d01f..0000000
+++ /dev/null
@@ -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'
-               );
-       }
-}
index d81d56e9d0f3aac837ede4a20ca710b7354b0aec..ad1dc180be79984e61b38ca4f8d795ba8772ccf6 100644 (file)
@@ -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`",
index 4444db6a586bba8e82cf63d66da1a5d8952e5703..3e6829a0d6a47c6fa3f9d56a8ab374c535631442 100644 (file)
@@ -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,
 
index 0ae149a279932d97488f1828670aa7f02dee8619..938d31a03e9f5ee648b26bc5a6c3b4460f0dd579 100644 (file)
@@ -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');
        }
index a5d7d2df47bd14da50ff11d9b2dce47f5730ea1f..7c156f5174e6619bf2fd71204fdad3ede69ef44f 100644 (file)
@@ -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',
index 2f5d12dc20d6c21437de36e0607e64db8d8b5264..2763c6ecc002dc8219216501522cbe45432043d4 100644 (file)
@@ -140,8 +140,8 @@ class Introduction extends BaseFactory
                                        }
 
                                        $formattedIntroductions[] = new ValueObject\Introduction([
-                                               'label'          => (($intro['network'] !== Protocol::OSTATUS) ? 'friend_request' : 'follower'),
-                                               'str_type'       => (($intro['network'] !== Protocol::OSTATUS) ? $this->l10n->t('Friend/Connect Request') : $this->l10n->t('New Follower')),
+                                               'label'          => 'friend_request',
+                                               'str_type'       => $this->l10n->t('Friend/Connect Request'),
                                                'dfrn_id'        => $intro['issued-id'],
                                                'uid'            => $this->session->getLocalUserId(),
                                                'intro_id'       => $intro['intro_id'],
index 40897a56182fc166322933104c964aa9fa9be10b..46dc05cfd53d1cb65aa5788ad0220eb7bb71e5e4 100644 (file)
@@ -24,7 +24,6 @@ class HttpClientRequest
        public const MEDIAPROXY      = 'MediaProxy/1';
        public const MEDIAVERIFIER   = 'MediaVerifier/1';
        public const OSTATUS         = 'OStatus/1';
-       public const SALMON          = 'Salmon/1';
        public const SERVERINFO      = 'ServerInfo/1';
        public const SERVERDISCOVER  = 'ServerDiscover/1';
        public const SITEINFO        = 'SiteInfo/1';
index 21a190c7df47a1492d1cda245d6addb0ac861233..99fb9ed2112ab2db63b042419e9b53abdc80a0ca 100644 (file)
@@ -869,20 +869,6 @@ class Probe
                                $data['baseurl'] = trim($link['href'], '/');
                        } elseif (($link['rel'] == 'http://webfinger.net/rel/blog') && !empty($link['href'])) {
                                $data['url'] = $link['href'];
-                       } elseif (($link['rel'] == 'magic-public-key') && !empty($link['href'])) {
-                               $pubkey = $link['href'];
-
-                               if (substr($pubkey, 0, 5) === 'data:') {
-                                       if (strstr($pubkey, ',')) {
-                                               $pubkey = substr($pubkey, strpos($pubkey, ',') + 1);
-                                       } else {
-                                               $pubkey = substr($pubkey, 5);
-                                       }
-                                       try {
-                                               $data['pubkey'] = Salmon::magicKeyToPem($pubkey);
-                                       } catch (\Throwable $e) {
-                                       }
-                               }
                        }
                }
                
index dd8939225cedb9729275e9ddde53d8fddf436304..dfc98a6d144dd15b579d4e24275b562e0a462685 100644 (file)
@@ -98,8 +98,8 @@ class Post
                                        continue;
                                }
 
-                               // You can always comment on Diaspora and OStatus items
-                               if (in_array($item['network'], [Protocol::OSTATUS, Protocol::DIASPORA]) && (DI::userSession()->getLocalUserId() == $item['uid'])) {
+                               // You can always comment on Diaspora items
+                               if (in_array($item['network'], [Protocol::DIASPORA]) && (DI::userSession()->getLocalUserId() == $item['uid'])) {
                                        $item['writable'] = true;
                                }
 
index 498e141ecc6917b219930f3d6cede349c6aeb83d..12fd91b7cf61978647fe5f55116e356296d61325 100644 (file)
@@ -1285,8 +1285,6 @@ class Receiver
                        DBA::close($parents);
                }
 
-               self::switchContacts($receivers, $actor);
-
                // "birdsitelive" is a service that mirrors tweets into the fediverse
                // These posts can be fetched without authentication, but are not marked as public
                // We treat them as unlisted posts to be able to handle them.
@@ -1369,62 +1367,6 @@ class Receiver
                return false;
        }
 
-       /**
-        * Switches existing contacts to ActivityPub
-        *
-        * @param integer $cid Contact ID
-        * @param integer $uid User ID
-        * @param string  $url Profile URL
-        * @return void
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        * @throws \ImagickException
-        */
-       public static function switchContact(int $cid, int $uid, string $url)
-       {
-               if (DBA::exists('contact', ['id' => $cid, 'network' => Protocol::ACTIVITYPUB])) {
-                       Logger::info('Contact is already ActivityPub', ['id' => $cid, 'uid' => $uid, 'url' => $url]);
-                       return;
-               }
-
-               if (Contact::updateFromProbe($cid)) {
-                       Logger::info('Update was successful', ['id' => $cid, 'uid' => $uid, 'url' => $url]);
-               }
-
-               // Send a new follow request to be sure that the connection still exists
-               if (($uid != 0) && DBA::exists('contact', ['id' => $cid, 'rel' => [Contact::SHARING, Contact::FRIEND], 'network' => Protocol::ACTIVITYPUB])) {
-                       Logger::info('Contact had been switched to ActivityPub. Sending a new follow request.', ['uid' => $uid, 'url' => $url]);
-                       ActivityPub\Transmitter::sendActivity('Follow', $url, $uid);
-               }
-       }
-
-       /**
-        * @TODO Fix documentation and type-hints
-        *
-        * @param $receivers
-        * @param $actor
-        * @return void
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        * @throws \ImagickException
-        */
-       private static function switchContacts($receivers, $actor)
-       {
-               if (empty($actor)) {
-                       return;
-               }
-
-               foreach ($receivers as $receiver) {
-                       $contact = DBA::selectFirst('contact', ['id'], ['uid' => $receiver['uid'], 'network' => Protocol::OSTATUS, 'nurl' => Strings::normaliseLink($actor)]);
-                       if (DBA::isResult($contact)) {
-                               self::switchContact($contact['id'], $receiver['uid'], $actor);
-                       }
-
-                       $contact = DBA::selectFirst('contact', ['id'], ['uid' => $receiver['uid'], 'network' => Protocol::OSTATUS, 'alias' => [Strings::normaliseLink($actor), $actor]]);
-                       if (DBA::isResult($contact)) {
-                               self::switchContact($contact['id'], $receiver['uid'], $actor);
-                       }
-               }
-       }
-
        /**
         * @TODO Fix documentation and type-hints
         *
index 3ca96937385f3269127d8cb018218a7ff7cb1134..03597383797a446da098e6192709003c40e883ce 100644 (file)
@@ -642,7 +642,7 @@ class Transmitter
                        $networks = Protocol::FEDERATED;
                } else {
                        // For now only send to these contacts:
-                       $networks = [Protocol::ACTIVITYPUB, Protocol::OSTATUS];
+                       $networks = [Protocol::ACTIVITYPUB];
                }
 
                $data = ['to' => [], 'cc' => [], 'bto' => [], 'bcc' => [], 'audience' => $audience];
@@ -1019,7 +1019,7 @@ class Transmitter
                        $networks = Protocol::FEDERATED;
                } else {
                        // For now only send to these contacts:
-                       $networks = [Protocol::ACTIVITYPUB, Protocol::OSTATUS];
+                       $networks = [Protocol::ACTIVITYPUB];
                }
 
                $condition = [
index 1cd5a39511c6fbc64bc9a9a72153e0d9202bcc34..7b82adaf9117cd5dec4c5130850265168ef295a9 100644 (file)
@@ -85,8 +85,7 @@ class DFRN
                        $user['uprvkey'] = $user['prvkey'];
                } else {
                        $user = ['importer_uid' => 0, 'uprvkey' => '', 'timezone' => 'UTC',
-                               'nickname' => '', 'sprvkey' => '', 'spubkey' => '',
-                               'page-flags' => 0, 'account-type' => 0, 'prvnets' => 0];
+                               'nickname' => '', 'page-flags' => 0, 'account-type' => 0, 'prvnets' => 0];
                }
 
                return array_merge($contact, $user);
@@ -363,21 +362,6 @@ class DFRN
                $attributes = ['rel' => 'alternate', 'type' => 'text/html', 'href' => $alternatelink];
                XML::addElement($doc, $root, 'link', '', $attributes);
 
-
-               if ($public) {
-                       // DFRN itself doesn't uses this. But maybe someone else wants to subscribe to the public feed.
-                       OStatus::addHubLink($doc, $root, $owner['nick']);
-
-                       $attributes = ['rel' => 'salmon', 'href' => DI::baseUrl() . '/salmon/' . $owner['nick']];
-                       XML::addElement($doc, $root, 'link', '', $attributes);
-
-                       $attributes = ['rel' => 'http://salmon-protocol.org/ns/salmon-replies', 'href' => DI::baseUrl() . '/salmon/' . $owner['nick']];
-                       XML::addElement($doc, $root, 'link', '', $attributes);
-
-                       $attributes = ['rel' => 'http://salmon-protocol.org/ns/salmon-mention', 'href' => DI::baseUrl() . '/salmon/' . $owner['nick']];
-                       XML::addElement($doc, $root, 'link', '', $attributes);
-               }
-
                // For backward compatibility we keep this element
                if (in_array($owner['page-flags'], [User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_COMM_MAN])) {
                        XML::addElement($doc, $root, 'dfrn:community', 1);
index 72fe345ece5dab9807a640e6052de5e72186c89c..999f88febca373ae24229af1fd7bc35afe989b6f 100644 (file)
@@ -799,7 +799,7 @@ class Feed
                        $frequency = [];
                        $oldest = time();
                        $newest = 0;
-                       $oldest_date = $newest_date = '';
+                       $newest_date = '';
 
                        foreach ($creation_dates as $date) {
                                $timestamp = strtotime($date);
@@ -822,7 +822,6 @@ class Feed
                                }
                                if ($oldest > $day) {
                                        $oldest = $day;
-                                       $oldest_date = $date;
                                }
 
                                if ($newest < $day) {
@@ -919,11 +918,6 @@ class Feed
                        $rating = 9;
                }
 
-               // Friendica and OStatus are checked once a day
-               if (in_array($contact['network'], [Protocol::DFRN, Protocol::OSTATUS])) {
-                       $rating = 8;
-               }
-
                // Check archived contacts or contacts with unsupported protocols once a month
                if ($contact['archive'] || in_array($contact['network'], [Protocol::ZOT, Protocol::PHANTOM])) {
                        $rating = 10;
@@ -1030,10 +1024,9 @@ class Feed
 
                $condition = [
                        "`uid` = ? AND `received` > ? AND NOT `deleted` AND `gravity` IN (?, ?)
-                       AND `private` != ? AND `visible` AND `wall` AND `parent-network` IN (?, ?, ?, ?)",
+                       AND `private` != ? AND `visible` AND `wall` AND `parent-network` IN (?, ?, ?)",
                        $owner['uid'], $check_date, Item::GRAVITY_PARENT, Item::GRAVITY_COMMENT,
-                       Item::PRIVATE, Protocol::ACTIVITYPUB,
-                       Protocol::OSTATUS, Protocol::DFRN, Protocol::DIASPORA
+                       Item::PRIVATE, Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA
                ];
 
                if ($filter === 'comments') {
@@ -1123,8 +1116,6 @@ class Feed
                $attributes = ['href' => $owner['url'], 'rel' => 'alternate', 'type' => 'text/html'];
                XML::addElement($doc, $root, 'link', '', $attributes);
 
-               OStatus::addHubLink($doc, $root, $owner['nick']);
-
                $attributes = ['href' => DI::baseUrl() . $selfUri, 'rel' => 'self', 'type' => 'application/atom+xml'];
                XML::addElement($doc, $root, 'link', '', $attributes);
 
@@ -1166,7 +1157,7 @@ class Feed
                        Logger::info('Feed entry author does not match feed owner', ['owner' => $owner['url'], 'author' => $item['author-link']]);
                }
 
-               $entry = OStatus::entryHeader($doc, $owner, $item, false);
+               $entry = self::entryHeader($doc, $owner, $item, false);
 
                self::entryContent($doc, $entry, $item, self::getTitle($item), '', true);
 
@@ -1191,7 +1182,7 @@ class Feed
        private static function entryContent(DOMDocument $doc, DOMElement $entry, array $item, $title, string $verb = '', bool $complete = true)
        {
                if ($verb == '') {
-                       $verb = OStatus::constructVerb($item);
+                       $verb = self::constructVerb($item);
                }
 
                XML::addElement($doc, $entry, 'id', $item['uri']);
@@ -1278,7 +1269,7 @@ class Feed
                        }
                }
 
-               OStatus::getAttachment($doc, $entry, $item);
+               self::getAttachment($doc, $entry, $item);
        }
 
        /**
@@ -1346,4 +1337,89 @@ class Feed
                }
                return $replace;
        }
+
+       /**
+        * Adds attachment data to the XML document
+        *
+        * @param DOMDocument $doc  XML document
+        * @param DOMElement  $root XML root element where the hub links are added
+        * @param array       $item Data of the item that is to be posted
+        * @return void
+        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+        */
+       private static function getAttachment(DOMDocument $doc, DOMElement $root, array $item)
+       {
+               foreach (Post\Media::getByURIId($item['uri-id'], [Post\Media::AUDIO, Post\Media::IMAGE, Post\Media::VIDEO, Post\Media::DOCUMENT, Post\Media::TORRENT]) as $attachment) {
+                       $attributes = ['rel' => 'enclosure',
+                               'href' => $attachment['url'],
+                               'type' => $attachment['mimetype']];
+
+                       if (!empty($attachment['size'])) {
+                               $attributes['length'] = intval($attachment['size']);
+                       }
+                       if (!empty($attachment['description'])) {
+                               $attributes['title'] = $attachment['description'];
+                       }
+
+                       XML::addElement($doc, $root, 'link', '', $attributes);
+               }
+       }
+
+       /**
+        * @TODO Picture attachments should look like this:
+        *      <a href="https://status.pirati.ca/attachment/572819" title="https://status.pirati.ca/file/heluecht-20151202T222602-rd3u49p.gif"
+        *      class="attachment thumbnail" id="attachment-572819" rel="nofollow external">https://status.pirati.ca/attachment/572819</a>
+        */
+
+       /**
+        * Returns the given activity if present - otherwise returns the "post" activity
+        *
+        * @param array $item Data of the item that is to be posted
+        * @return string activity
+        */
+       private static function constructVerb(array $item): string
+       {
+               if (!empty($item['verb'])) {
+                       return $item['verb'];
+               }
+
+               return Activity::POST;
+       }
+
+       /**
+        * Adds a header element to the XML document
+        *
+        * @param DOMDocument $doc      XML document
+        * @param array       $owner    Contact data of the poster
+        * @param array       $item
+        * @param bool        $toplevel Is it for en entry element (false) or a feed entry (true)?
+        * @return DOMElement The entry element where the elements are added
+        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+        * @throws \ImagickException
+        */
+       private static function entryHeader(DOMDocument $doc, array $owner, array $item, bool $toplevel): DOMElement
+       {
+               if (!$toplevel) {
+                       $entry = $doc->createElement('entry');
+
+                       if ($owner['contact-type'] == Contact::TYPE_COMMUNITY) {
+                               $entry->setAttribute('xmlns:activity', ActivityNamespace::ACTIVITY);
+
+                               $contact = Contact::getByURL($item['author-link']) ?: $owner;
+                               $contact['nickname'] = $contact['nickname'] ?? $contact['nick'];
+                               $author = self::addAuthor($doc, $contact, false);
+                               $entry->appendChild($author);
+                       }
+               } else {
+                       $entry = $doc->createElementNS(ActivityNamespace::ATOM1, 'entry');
+
+                       $entry->setAttribute('xmlns:thr', ActivityNamespace::THREAD);
+                       $entry->setAttribute('xmlns:poco', ActivityNamespace::POCO);
+
+                       $author = self::addAuthor($doc, $owner);
+                       $entry->appendChild($author);
+               }
+
+               return $entry;
+       }
 }
diff --git a/src/Protocol/OStatus.php b/src/Protocol/OStatus.php
deleted file mode 100644 (file)
index 71b6fba..0000000
+++ /dev/null
@@ -1,1822 +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\Protocol;
-
-use DOMDocument;
-use DOMElement;
-use DOMXPath;
-use Friendica\App;
-use Friendica\Content\Text\BBCode;
-use Friendica\Content\Text\HTML;
-use Friendica\Core\Cache\Enum\Duration;
-use Friendica\Core\Logger;
-use Friendica\Core\Protocol;
-use Friendica\Database\DBA;
-use Friendica\DI;
-use Friendica\Model\APContact;
-use Friendica\Model\Contact;
-use Friendica\Model\Conversation;
-use Friendica\Model\Item;
-use Friendica\Model\ItemURI;
-use Friendica\Model\Post;
-use Friendica\Model\Tag;
-use Friendica\Model\User;
-use Friendica\Network\HTTPClient\Client\HttpClientAccept;
-use Friendica\Network\HTTPClient\Client\HttpClientOptions;
-use Friendica\Network\HTTPClient\Client\HttpClientRequest;
-use Friendica\Network\Probe;
-use Friendica\Util\DateTimeFormat;
-use Friendica\Util\Images;
-use Friendica\Util\Proxy;
-use Friendica\Util\Strings;
-use Friendica\Util\XML;
-
-/**
- * This class contain functions for the OStatus protocol
- */
-class OStatus
-{
-       private static $itemlist;
-       private static $conv_list = [];
-
-       /**
-        * Fetches author data
-        *
-        * @param DOMXPath $xpath     The xpath object
-        * @param object   $context   The xml context of the author details
-        * @param array    $importer  user record of the importing user
-        * @param array    $contact   Called by reference, will contain the fetched contact
-        * @param bool     $onlyfetch Only fetch the header without updating the contact entries
-        *
-        * @return array Array of author related entries for the item
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        * @throws \ImagickException
-        */
-       private static function fetchAuthor(DOMXPath $xpath, $context, array $importer, array &$contact = null, bool $onlyfetch): array
-       {
-               $author = [];
-               $author['author-link'] = XML::getFirstNodeValue($xpath, 'atom:author/atom:uri/text()', $context);
-               $author['author-name'] = XML::getFirstNodeValue($xpath, 'atom:author/atom:name/text()', $context);
-               $addr = XML::getFirstNodeValue($xpath, 'atom:author/atom:email/text()', $context);
-
-               $aliaslink = $author['author-link'];
-
-               $alternate_item = $xpath->query("atom:author/atom:link[@rel='alternate']", $context)->item(0);
-               if (is_object($alternate_item)) {
-                       foreach ($alternate_item->attributes as $attributes) {
-                               if (($attributes->name == 'href') && ($attributes->textContent != '')) {
-                                       $author['author-link'] = $attributes->textContent;
-                               }
-                       }
-               }
-               $author['author-id'] = Contact::getIdForURL($author['author-link']);
-
-               $author['contact-id'] = ($contact['id'] ?? 0) ?: $author['author-id'];
-
-               $contact = [];
-
-/*
-               This here would be better, but we would get problems with contacts from the statusnet addon
-               This is kept here as a reminder for the future
-
-               $cid = Contact::getIdForURL($author['author-link'], $importer['uid']);
-               if ($cid) {
-                       $contact = DBA::selectFirst('contact', [], ['id' => $cid]);
-               }
-*/
-               if ($aliaslink != '') {
-                       $contact = DBA::selectFirst('contact', [], [
-                               "`uid` = ? AND `alias` = ? AND `rel` IN (?, ?)",
-                               $importer['uid'],
-                               $aliaslink,
-                               Contact::SHARING, Contact::FRIEND,
-                       ]);
-               }
-
-               if (!DBA::isResult($contact) && $author['author-link'] != '') {
-                       if ($aliaslink == '') {
-                               $aliaslink = $author['author-link'];
-                       }
-
-                       $contact = DBA::selectFirst('contact', [], [
-                               "`uid` = ? AND `nurl` IN (?, ?) AND `rel` IN (?, ?)",
-                               $importer['uid'],
-                               Strings::normaliseLink($author['author-link']),
-                               Strings::normaliseLink($aliaslink),
-                               Contact::SHARING,
-                               Contact::FRIEND,
-                       ]);
-               }
-
-               if (!DBA::isResult($contact) && ($addr != '')) {
-                       $contact = DBA::selectFirst('contact', [], [
-                               "`uid` = ? AND `addr` = ? AND `rel` IN (?, ?)",
-                               $importer['uid'],
-                               $addr,
-                               Contact::SHARING,
-                               Contact::FRIEND,
-                       ]);
-               }
-
-               if (DBA::isResult($contact)) {
-                       if ($contact['blocked']) {
-                               $contact['id'] = -1;
-                       } elseif (!empty(APContact::getByURL($contact['url'], false))) {
-                               ActivityPub\Receiver::switchContact($contact['id'], $importer['uid'], $contact['url']);
-                       }
-                       $author['contact-id'] = $contact['id'];
-               }
-
-               $avatarlist = [];
-               $avatars = $xpath->query("atom:author/atom:link[@rel='avatar']", $context);
-               foreach ($avatars as $avatar) {
-                       $href = '';
-                       $width = 0;
-                       foreach ($avatar->attributes as $attributes) {
-                               if ($attributes->name == 'href') {
-                                       $href = $attributes->textContent;
-                               }
-                               if ($attributes->name == 'width') {
-                                       $width = $attributes->textContent;
-                               }
-                       }
-                       if ($href != '') {
-                               $avatarlist[$width] = $href;
-                       }
-               }
-               if (count($avatarlist) > 0) {
-                       krsort($avatarlist);
-                       $author['author-avatar'] = Probe::fixAvatar(current($avatarlist), $author['author-link']);
-               }
-
-               $displayname = XML::getFirstNodeValue($xpath, 'atom:author/poco:displayName/text()', $context);
-               if ($displayname != '') {
-                       $author['author-name'] = $displayname;
-               }
-
-               $author['owner-id'] = $author['author-id'];
-
-               // Only update the contacts if it is an OStatus contact
-               if (DBA::isResult($contact) && ($contact['id'] > 0) && !$onlyfetch && ($contact['network'] == Protocol::OSTATUS)) {
-
-                       // Update contact data
-                       $current = $contact;
-                       unset($current['name-date']);
-
-                       // This query doesn't seem to work
-                       // $value = $xpath->query("atom:link[@rel='salmon']", $context)->item(0)->nodeValue;
-                       // if ($value != "")
-                       //      $contact["notify"] = $value;
-
-                       // This query doesn't seem to work as well - I hate these queries
-                       // $value = $xpath->query("atom:link[@rel='self' and @type='application/atom+xml']", $context)->item(0)->nodeValue;
-                       // if ($value != "")
-                       //      $contact["poll"] = $value;
-
-                       $contact['url'] = $author['author-link'];
-                       $contact['nurl'] = Strings::normaliseLink($contact['url']);
-
-                       $value = XML::getFirstNodeValue($xpath, 'atom:author/atom:uri/text()', $context);
-                       if ($value != '') {
-                               $contact['alias'] = $value;
-                       }
-
-                       $value = XML::getFirstNodeValue($xpath, 'atom:author/poco:displayName/text()', $context);
-                       if ($value != '') {
-                               $contact['name'] = $value;
-                       }
-
-                       $value = XML::getFirstNodeValue($xpath, 'atom:author/poco:preferredUsername/text()', $context);
-                       if ($value != '') {
-                               $contact['nick'] = $value;
-                       }
-
-                       $value = XML::getFirstNodeValue($xpath, 'atom:author/poco:note/text()', $context);
-                       if ($value != '') {
-                               $contact['about'] = HTML::toBBCode($value);
-                       }
-
-                       $value = XML::getFirstNodeValue($xpath, 'atom:author/poco:address/poco:formatted/text()', $context);
-                       if ($value != '') {
-                               $contact['location'] = $value;
-                       }
-
-                       $contact['name-date'] = DateTimeFormat::utcNow();
-
-                       Contact::update($contact, ['id' => $contact['id']], $current);
-
-                       if (!empty($author['author-avatar']) && ($author['author-avatar'] != $current['avatar'])) {
-                               Logger::info('Update profile picture for contact ' . $contact['id']);
-                               Contact::updateAvatar($contact['id'], $author['author-avatar']);
-                       }
-
-                       // Ensure that we are having this contact (with uid=0)
-                       $cid = Contact::getIdForURL($aliaslink);
-
-                       if ($cid) {
-                               $fields = ['url', 'nurl', 'name', 'nick', 'alias', 'about', 'location'];
-                               $old_contact = DBA::selectFirst('contact', $fields, ['id' => $cid]);
-
-                               // Update it with the current values
-                               $fields = [
-                                       'url' => $author['author-link'],
-                                       'name' => $contact['name'],
-                                       'nurl' => Strings::normaliseLink($author['author-link']),
-                                       'nick' => $contact['nick'],
-                                       'alias' => $contact['alias'],
-                                       'about' => $contact['about'],
-                                       'location' => $contact['location'],
-                                       'success_update' => DateTimeFormat::utcNow(),
-                                       'last-update' => DateTimeFormat::utcNow(),
-                               ];
-
-                               Contact::update($fields, ['id' => $cid], $old_contact);
-
-                               // Update the avatar
-                               if (!empty($author['author-avatar'])) {
-                                       Contact::updateAvatar($cid, $author['author-avatar']);
-                               }
-                       }
-               } elseif (empty($contact['network']) || ($contact['network'] != Protocol::DFRN)) {
-                       $contact = [];
-               }
-
-               return $author;
-       }
-
-       /**
-        * Fetches author data from a given XML string
-        *
-        * @param string $xml      The XML
-        * @param array  $importer user record of the importing user
-        *
-        * @return array Array of author related entries for the item
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        * @throws \ImagickException
-        */
-       public static function salmonAuthor(string $xml, array $importer): array
-       {
-               if (empty($xml)) {
-                       return [];
-               }
-
-               $doc = new DOMDocument();
-               @$doc->loadXML($xml);
-
-               $xpath = new DOMXPath($doc);
-               $xpath->registerNamespace('atom', ActivityNamespace::ATOM1);
-               $xpath->registerNamespace('thr', ActivityNamespace::THREAD);
-               $xpath->registerNamespace('georss', ActivityNamespace::GEORSS);
-               $xpath->registerNamespace('activity', ActivityNamespace::ACTIVITY);
-               $xpath->registerNamespace('media', ActivityNamespace::MEDIA);
-               $xpath->registerNamespace('poco', ActivityNamespace::POCO);
-               $xpath->registerNamespace('ostatus', ActivityNamespace::OSTATUS);
-               $xpath->registerNamespace('statusnet', ActivityNamespace::STATUSNET);
-
-               $contact = ['id' => 0];
-
-               // Fetch the first author
-               $authordata = $xpath->query('//author')->item(0);
-               $author = self::fetchAuthor($xpath, $authordata, $importer, $contact, true);
-               return $author;
-       }
-
-       /**
-        * Read attributes from element
-        *
-        * @param object $element Element object
-        * @return array attributes
-        */
-       private static function readAttributes($element): array
-       {
-               $attribute = [];
-
-               foreach ($element->attributes as $attributes) {
-                       $attribute[$attributes->name] = $attributes->textContent;
-               }
-
-               return $attribute;
-       }
-
-       /**
-        * Imports an XML string containing OStatus elements
-        *
-        * @param string $xml      The XML
-        * @param array  $importer user record of the importing user
-        * @param array  $contact  contact
-        * @param string $hub      Called by reference, returns the fetched hub data
-        * @return void
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        * @throws \ImagickException
-        */
-       public static function import($xml, array $importer, array &$contact, &$hub)
-       {
-               self::process($xml, $importer, $contact, $hub, false, true, Conversation::PUSH);
-       }
-
-       /**
-        * Internal feed processing
-        *
-        * @param string  $xml        The XML
-        * @param array   $importer   user record of the importing user
-        * @param array   $contact    contact
-        * @param string  $hub        Called by reference, returns the fetched hub data
-        * @param boolean $stored     Is the post fresh imported or from the database?
-        * @param boolean $initialize Is it the leading post so that data has to be initialized?
-        * @param integer $direction  Direction, default UNKNOWN(0)
-        * @return boolean Could the XML be processed?
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        * @throws \ImagickException
-        */
-       private static function process(string $xml, array $importer, array &$contact = null, string &$hub, bool $stored = false, bool $initialize = true, int $direction = Conversation::UNKNOWN)
-       {
-               if ($initialize) {
-                       self::$itemlist = [];
-                       self::$conv_list = [];
-               }
-
-               Logger::info('Import OStatus message for user ' . $importer['uid']);
-
-               if (empty($xml)) {
-                       return false;
-               }
-
-               $doc = new DOMDocument();
-               @$doc->loadXML($xml);
-
-               $xpath = new DOMXPath($doc);
-               $xpath->registerNamespace('atom', ActivityNamespace::ATOM1);
-               $xpath->registerNamespace('thr', ActivityNamespace::THREAD);
-               $xpath->registerNamespace('georss', ActivityNamespace::GEORSS);
-               $xpath->registerNamespace('activity', ActivityNamespace::ACTIVITY);
-               $xpath->registerNamespace('media', ActivityNamespace::MEDIA);
-               $xpath->registerNamespace('poco', ActivityNamespace::POCO);
-               $xpath->registerNamespace('ostatus', ActivityNamespace::OSTATUS);
-               $xpath->registerNamespace('statusnet', ActivityNamespace::STATUSNET);
-
-               $hub = '';
-               $hub_items = $xpath->query("/atom:feed/atom:link[@rel='hub']")->item(0);
-               if (is_object($hub_items)) {
-                       $hub_attributes = $hub_items->attributes;
-                       if (is_object($hub_attributes)) {
-                               foreach ($hub_attributes as $hub_attribute) {
-                                       if ($hub_attribute->name == 'href') {
-                                               $hub = $hub_attribute->textContent;
-                                               Logger::info('Found hub ', ['hub' => $hub]);
-                                       }
-                               }
-                       }
-               }
-
-               // Initial header elements
-               $header = [
-                       'uid'     => $importer['uid'],
-                       'network' => Protocol::OSTATUS,
-                       'wall'    => 0,
-                       'origin'  => 0,
-                       'gravity' => Item::GRAVITY_COMMENT,
-               ];
-
-               if (!is_object($doc->firstChild) || empty($doc->firstChild->tagName)) {
-                       return false;
-               }
-
-               $first_child = $doc->firstChild->tagName;
-
-               if ($first_child == 'feed') {
-                       $entries = $xpath->query('/atom:feed/atom:entry');
-               } else {
-                       $entries = $xpath->query('/atom:entry');
-               }
-
-               if ($entries->length == 1) {
-                       // We reformat the XML to make it better readable
-                       $doc2 = new DOMDocument();
-                       $doc2->loadXML($xml);
-                       $doc2->preserveWhiteSpace = false;
-                       $doc2->formatOutput = true;
-                       $xml2 = $doc2->saveXML();
-
-                       $header['protocol'] = Conversation::PARCEL_SALMON;
-                       $header['source'] = $xml2;
-                       $header['direction'] = $direction;
-               } elseif (!$initialize) {
-                       return false;
-               }
-
-               // Fetch the first author
-               $authordata = $xpath->query('//author')->item(0);
-               $author = self::fetchAuthor($xpath, $authordata, $importer, $contact, $stored);
-
-               // Reverse the order of the entries
-               $entrylist = [];
-
-               foreach ($entries as $entry) {
-                       $entrylist[] = $entry;
-               }
-
-               foreach (array_reverse($entrylist) as $entry) {
-                       // fetch the author
-                       $authorelement = $xpath->query('/atom:entry/atom:author', $entry);
-
-                       if ($authorelement->length == 0) {
-                               $authorelement = $xpath->query('atom:author', $entry);
-                       }
-
-                       if ($authorelement->length > 0) {
-                               $author = self::fetchAuthor($xpath, $entry, $importer, $contact, $stored);
-                       }
-
-                       $item = array_merge($header, $author);
-
-                       $item['uri'] = XML::getFirstNodeValue($xpath, 'atom:id/text()', $entry);
-                       $item['uri-id'] = ItemURI::insert(['uri' => $item['uri']]);
-
-                       $item['verb'] = XML::getFirstNodeValue($xpath, 'activity:verb/text()', $entry);
-
-                       // Delete a message
-                       if (in_array($item['verb'], ['qvitter-delete-notice', Activity::DELETE, 'delete'])) {
-                               self::deleteNotice($item);
-                               continue;
-                       }
-
-                       if (in_array($item['verb'], [Activity::O_UNFAVOURITE, Activity::UNFAVORITE])) {
-                               // Ignore "Unfavorite" message
-                               Logger::info('Ignore unfavorite message ', ['item' => $item]);
-                               continue;
-                       }
-
-                       // Deletions come with the same uri, so we check for duplicates after processing deletions
-                       if (Post::exists(['uid' => $importer['uid'], 'uri' => $item['uri']])) {
-                               Logger::info('Post with URI ' . $item['uri'] . ' already existed for user ' . $importer['uid'] . '.');
-                               continue;
-                       } else {
-                               Logger::info('Processing post with URI ' .  $item['uri'] . ' for user ' . $importer['uid'] . '.');
-                       }
-
-                       if ($item['verb'] == Activity::JOIN) {
-                               // ignore "Join" messages
-                               Logger::info('Ignore join message ', ['item' => $item]);
-                               continue;
-                       }
-
-                       if ($item['verb'] == 'http://mastodon.social/schema/1.0/block') {
-                               // ignore mastodon "block" messages
-                               Logger::info('Ignore block message ', ['item' => $item]);
-                               continue;
-                       }
-
-                       if ($item['verb'] == Activity::FOLLOW) {
-                               Contact::addRelationship($importer, $contact, $item);
-                               continue;
-                       }
-
-                       if ($item['verb'] == Activity::O_UNFOLLOW) {
-                               $dummy = null;
-                               Contact::removeFollower($contact);
-                               continue;
-                       }
-
-                       if ($item['verb'] == Activity::FAVORITE) {
-                               $orig_uri = $xpath->query('activity:object/atom:id', $entry)->item(0)->nodeValue;
-                               Logger::notice('Favorite', ['uri' => $orig_uri, 'item' => $item]);
-
-                               $item['body'] = $item['verb'] = Activity::LIKE;
-                               $item['thr-parent'] = $orig_uri;
-                               $item['gravity'] = Item::GRAVITY_ACTIVITY;
-                               $item['object-type'] = Activity\ObjectType::NOTE;
-                       }
-
-                       // http://activitystrea.ms/schema/1.0/rsvp-yes
-                       if (!in_array($item['verb'], [Activity::POST, Activity::LIKE, Activity::SHARE])) {
-                               Logger::info('Unhandled verb', ['verb' => $item['verb'], 'item' => $item]);
-                       }
-
-                       self::processPost($xpath, $entry, $item, $importer);
-
-                       if ($initialize && (count(self::$itemlist) > 0)) {
-                               if (self::$itemlist[0]['uri'] == self::$itemlist[0]['thr-parent']) {
-                                       $uid = self::$itemlist[0]['uid'];
-                                       // We will import it everytime, when it is started by our contacts
-                                       $valid = Contact::isSharingByURL(self::$itemlist[0]['author-link'], $uid);
-
-                                       if (!$valid) {
-                                               // If not, then it depends on this setting
-                                               $valid = !$uid || DI::pConfig()->get($uid, 'system', 'accept_only_sharer') != Item::COMPLETION_NONE;
-
-                                               if ($valid) {
-                                                       Logger::info('Item with URI ' . self::$itemlist[0]['uri'] . ' will be imported due to the system settings.');
-                                               }
-                                       } else {
-                                               Logger::info('Item with URI ' . self::$itemlist[0]['uri'] . ' belongs to a contact (' . self::$itemlist[0]['contact-id'] . '). It will be imported.');
-                                       }
-
-                                       if ($valid && DI::pConfig()->get($uid, 'system', 'accept_only_sharer') != Item::COMPLETION_LIKE) {
-                                               // Never post a thread when the only interaction by our contact was a like
-                                               $valid = false;
-                                               $verbs = [Activity::POST, Activity::SHARE];
-                                               foreach (self::$itemlist as $item) {
-                                                       if (in_array($item['verb'], $verbs) && Contact::isSharingByURL($item['author-link'], $item['uid'])) {
-                                                               $valid = true;
-                                                       }
-                                               }
-                                               if ($valid) {
-                                                       Logger::info('Item with URI ' . self::$itemlist[0]['uri'] . ' will be imported since the thread contains posts or shares.');
-                                               }
-                                       }
-                               } else {
-                                       $valid = true;
-                               }
-
-                               if ($valid) {
-                                       $default_contact = 0;
-                                       for ($key = count(self::$itemlist) - 1; $key >= 0; $key--) {
-                                               if (empty(self::$itemlist[$key]['contact-id'])) {
-                                                       self::$itemlist[$key]['contact-id'] = $default_contact;
-                                               } else {
-                                                       $default_contact = $item['contact-id'];
-                                               }
-                                       }
-                                       foreach (self::$itemlist as $item) {
-                                               $found = Post::exists(['uid' => $importer['uid'], 'uri' => $item['uri']]);
-                                               if ($found) {
-                                                       Logger::notice('Item with URI ' . $item['uri'] . ' for user ' . $importer['uid'] . ' already exists.');
-                                               } elseif ($item['contact-id'] < 0) {
-                                                       Logger::notice('Item with URI ' . $item['uri'] . ' is from a blocked contact.');
-                                               } else {
-                                                       $ret = Item::insert($item);
-                                                       Logger::info('Item with URI ' . $item['uri'] . ' for user ' . $importer['uid'] . ' stored. Return value: ' . $ret);
-                                               }
-                                       }
-                               }
-                               self::$itemlist = [];
-                       }
-                       Logger::info('Processing done for post with URI ' . $item['uri'] . ' for user '.$importer['uid'] . '.');
-               }
-               return true;
-       }
-
-       /**
-        * Removes notice item from database
-        *
-        * @param array $item item
-        * @return void
-        * @throws \Exception
-        */
-       private static function deleteNotice(array $item)
-       {
-               $condition = ['uid' => $item['uid'], 'author-id' => $item['author-id'], 'uri' => $item['uri']];
-               if (!Post::exists($condition)) {
-                       Logger::notice('Item from ' . $item['author-link'] . ' with uri ' . $item['uri'] . ' for user ' . $item['uid'] . " wasn't found. We don't delete it.");
-                       return;
-               }
-
-               Item::markForDeletion($condition);
-
-               Logger::notice('Deleted item with URI ' . $item['uri'] . ' for user ' . $item['uid']);
-       }
-
-       /**
-        * Processes the XML for a post
-        *
-        * @param DOMXPath $xpath    The xpath object
-        * @param object   $entry    The xml entry that is processed
-        * @param array    $item     The item array
-        * @param array    $importer user record of the importing user
-        * @return void
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        * @throws \ImagickException
-        */
-       private static function processPost(DOMXPath $xpath, $entry, array &$item, array $importer)
-       {
-               $item['body'] = HTML::toBBCode(XML::getFirstNodeValue($xpath, 'atom:content/text()', $entry));
-               $item['object-type'] = XML::getFirstNodeValue($xpath, 'activity:object-type/text()', $entry);
-               if (($item['object-type'] == Activity\ObjectType::BOOKMARK) || ($item['object-type'] == Activity\ObjectType::EVENT)) {
-                       $item['title'] = XML::getFirstNodeValue($xpath, 'atom:title/text()', $entry);
-                       $item['body'] = XML::getFirstNodeValue($xpath, 'atom:summary/text()', $entry);
-               } elseif ($item['object-type'] == Activity\ObjectType::QUESTION) {
-                       $item['title'] = XML::getFirstNodeValue($xpath, 'atom:title/text()', $entry);
-               }
-
-               $item['created'] = XML::getFirstNodeValue($xpath, 'atom:published/text()', $entry);
-               $item['edited'] = XML::getFirstNodeValue($xpath, 'atom:updated/text()', $entry);
-               $item['conversation'] = XML::getFirstNodeValue($xpath, 'ostatus:conversation/text()', $entry);
-
-               $conv = $xpath->query('ostatus:conversation', $entry);
-               if (is_object($conv->item(0))) {
-                       foreach ($conv->item(0)->attributes as $attributes) {
-                               if ($attributes->name == 'ref') {
-                                       $item['conversation'] = $attributes->textContent;
-                               }
-                               if ($attributes->name == 'href') {
-                                       $item['conversation'] = $attributes->textContent;
-                               }
-                       }
-               }
-
-               $related = '';
-
-               $inreplyto = $xpath->query('thr:in-reply-to', $entry);
-               if (is_object($inreplyto->item(0))) {
-                       foreach ($inreplyto->item(0)->attributes as $attributes) {
-                               if ($attributes->name == 'ref') {
-                                       $item['thr-parent'] = $attributes->textContent;
-                               }
-                               if ($attributes->name == 'href') {
-                                       $related = $attributes->textContent;
-                               }
-                       }
-               }
-
-               $georsspoint = $xpath->query('georss:point', $entry);
-               if (!empty($georsspoint) && ($georsspoint->length > 0)) {
-                       $item['coord'] = $georsspoint->item(0)->nodeValue;
-               }
-
-               $categories = $xpath->query('atom:category', $entry);
-               if ($categories) {
-                       foreach ($categories as $category) {
-                               foreach ($category->attributes as $attributes) {
-                                       if ($attributes->name == 'term') {
-                                               // Store the hashtag
-                                               Tag::store($item['uri-id'], Tag::HASHTAG, $attributes->textContent);
-                                       }
-                               }
-                       }
-               }
-
-               $self = '';
-               $add_body = '';
-
-               $links = $xpath->query('atom:link', $entry);
-               if ($links) {
-                       $link_data = self::processLinks($links, $item);
-                       $self = $link_data['self'];
-                       $add_body = $link_data['add_body'];
-               }
-
-               $repeat_of = '';
-
-               $notice_info = $xpath->query('statusnet:notice_info', $entry);
-               if ($notice_info && ($notice_info->length > 0)) {
-                       foreach ($notice_info->item(0)->attributes as $attributes) {
-                               if ($attributes->name == 'source') {
-                                       $item['app'] = strip_tags($attributes->textContent);
-                               }
-                               if ($attributes->name == 'repeat_of') {
-                                       $repeat_of = $attributes->textContent;
-                               }
-                       }
-               }
-               // Is it a repeated post?
-               if (($repeat_of != '') || ($item['verb'] == Activity::SHARE)) {
-                       $link_data = self::processRepeatedItem($xpath, $entry, $item, $importer);
-                       if (!empty($link_data['add_body'])) {
-                               $add_body .= $link_data['add_body'];
-                       }
-               }
-
-               $item['body'] .= $add_body;
-
-               Tag::storeFromBody($item['uri-id'], $item['body']);
-
-               // Mastodon Content Warning
-               if (($item['verb'] == Activity::POST) && $xpath->evaluate('boolean(atom:summary)', $entry)) {
-                       $clear_text = XML::getFirstNodeValue($xpath, 'atom:summary/text()', $entry);
-                       if (!empty($clear_text)) {
-                               $item['content-warning'] = HTML::toBBCode($clear_text);
-                       }
-               }
-
-               if (isset($item['thr-parent'])) {
-                       if (!Post::exists(['uid' => $importer['uid'], 'uri' => $item['thr-parent']])) {
-                               if ($related != '') {
-                                       self::fetchRelated($related, $item['thr-parent'], $importer);
-                               }
-                       } else {
-                               Logger::info('Reply with URI ' . $item['uri'] . ' already existed for user ' . $importer['uid'] . '.');
-                       }
-               } else {
-                       $item['thr-parent'] = $item['uri'];
-                       $item['gravity'] = Item::GRAVITY_PARENT;
-               }
-
-               self::$itemlist[] = $item;
-       }
-
-       /**
-        * Fetch related posts and processes them
-        *
-        * @param string $related     The link to the related item
-        * @param string $related_uri The related item in "uri" format
-        * @param array  $importer    user record of the importing user
-        * @return void
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        * @throws \ImagickException
-        */
-       private static function fetchRelated(string $related, string $related_uri, array $importer)
-       {
-               $stored = false;
-               $curlResult = DI::httpClient()->get($related, HttpClientAccept::ATOM_XML, [HttpClientOptions::REQUEST => HttpClientRequest::OSTATUS]);
-
-               if (!$curlResult->isSuccess() || empty($curlResult->getBodyString())) {
-                       return;
-               }
-
-               $xml = '';
-
-               if ($curlResult->inHeader('Content-Type') &&
-                       in_array('application/atom+xml', $curlResult->getHeader('Content-Type'))) {
-                       Logger::info('Directly fetched XML for URI ' . $related_uri);
-                       $xml = $curlResult->getBodyString();
-               }
-
-               if ($xml == '') {
-                       $doc = new DOMDocument();
-                       if (!@$doc->loadHTML($curlResult->getBodyString())) {
-                               return;
-                       }
-                       $xpath = new DOMXPath($doc);
-
-                       $atom_file = '';
-
-                       $links = $xpath->query('//link');
-                       if ($links) {
-                               foreach ($links as $link) {
-                                       $attribute = self::readAttributes($link);
-                                       if (($attribute['rel'] == 'alternate') && ($attribute['type'] == 'application/atom+xml')) {
-                                               $atom_file = $attribute['href'];
-                                       }
-                               }
-                               if ($atom_file != '') {
-                                       $curlResult = DI::httpClient()->get($atom_file, HttpClientAccept::ATOM_XML, [HttpClientOptions::REQUEST => HttpClientRequest::OSTATUS]);
-
-                                       if ($curlResult->isSuccess()) {
-                                               Logger::info('Fetched XML for URI ' . $related_uri);
-                                               $xml = $curlResult->getBodyString();
-                                       }
-                               }
-                       }
-               }
-
-               // Workaround for older GNU Social servers
-               if (($xml == '') && strstr($related, '/notice/')) {
-                       $curlResult = DI::httpClient()->get(str_replace('/notice/', '/api/statuses/show/', $related) . '.atom', HttpClientAccept::ATOM_XML, [HttpClientOptions::REQUEST => HttpClientRequest::OSTATUS]);
-
-                       if ($curlResult->isSuccess()) {
-                               Logger::info('GNU Social workaround to fetch XML for URI ' . $related_uri);
-                               $xml = $curlResult->getBodyString();
-                       }
-               }
-
-               // Even more worse workaround for GNU Social ;-)
-               if ($xml == '') {
-                       $related_guess = self::convertHref($related_uri);
-                       $curlResult = DI::httpClient()->get(str_replace('/notice/', '/api/statuses/show/', $related_guess) . '.atom', HttpClientAccept::ATOM_XML, [HttpClientOptions::REQUEST => HttpClientRequest::OSTATUS]);
-
-                       if ($curlResult->isSuccess()) {
-                               Logger::info('GNU Social workaround 2 to fetch XML for URI ' . $related_uri);
-                               $xml = $curlResult->getBodyString();
-                       }
-               }
-
-               if ($xml != '') {
-                       $hub = '';
-                       self::process($xml, $importer, $contact, $hub, $stored, false, Conversation::PULL);
-               } else {
-                       Logger::info('XML could not be fetched for URI: ' . $related_uri . ' - href: ' . $related);
-               }
-               return;
-       }
-
-       /**
-        * Processes the XML for a repeated post
-        *
-        * @param DOMXPath $xpath    The xpath object
-        * @param object   $entry    The xml entry that is processed
-        * @param array    $item     The item array
-        * @param array    $importer user record of the importing user
-        *
-        * @return array with data from links
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        * @throws \ImagickException
-        */
-       private static function processRepeatedItem(DOMXPath $xpath, $entry, array &$item, array $importer): array
-       {
-               $activityobject = $xpath->query('activity:object', $entry)->item(0);
-
-               if (!is_object($activityobject)) {
-                       return [];
-               }
-
-               $link_data = [];
-
-               $orig_uri = XML::getFirstNodeValue($xpath, 'atom:id/text()', $activityobject);
-
-               $links = $xpath->query('atom:link', $activityobject);
-               if ($links) {
-                       $link_data = self::processLinks($links, $item);
-               }
-
-               $orig_body = XML::getFirstNodeValue($xpath, 'atom:content/text()', $activityobject);
-               $orig_created = XML::getFirstNodeValue($xpath, 'atom:published/text()', $activityobject);
-               $orig_edited = XML::getFirstNodeValue($xpath, 'atom:updated/text()', $activityobject);
-
-               $orig_author = self::fetchAuthor($xpath, $activityobject, $importer, $dummy, false);
-
-               $item['author-name'] = $orig_author['author-name'];
-               $item['author-link'] = $orig_author['author-link'];
-               $item['author-id'] = $orig_author['author-id'];
-
-               $item['body'] = HTML::toBBCode($orig_body);
-               $item['created'] = $orig_created;
-               $item['edited'] = $orig_edited;
-
-               $item['uri'] = $orig_uri;
-
-               $item['verb'] = XML::getFirstNodeValue($xpath, 'activity:verb/text()', $activityobject);
-
-               $item['object-type'] = XML::getFirstNodeValue($xpath, 'activity:object-type/text()', $activityobject);
-
-               // Mastodon Content Warning
-               if (($item['verb'] == Activity::POST) && $xpath->evaluate('boolean(atom:summary)', $activityobject)) {
-                       $clear_text = XML::getFirstNodeValue($xpath, 'atom:summary/text()', $activityobject);
-                       if (!empty($clear_text)) {
-                               $item['content-warning'] = HTML::toBBCode($clear_text);
-                       }
-               }
-
-               $inreplyto = $xpath->query('thr:in-reply-to', $activityobject);
-               if (is_object($inreplyto->item(0))) {
-                       foreach ($inreplyto->item(0)->attributes as $attributes) {
-                               if ($attributes->name == 'ref') {
-                                       $item['thr-parent'] = $attributes->textContent;
-                               }
-                       }
-               }
-
-               return $link_data;
-       }
-
-       /**
-        * Processes links in the XML
-        *
-        * @param object $links The xml data that contain links
-        * @param array  $item  The item array
-        * @return array with data from the links
-        */
-       private static function processLinks($links, array &$item): array
-       {
-               $link_data = ['add_body' => '', 'self' => ''];
-
-               foreach ($links as $link) {
-                       $attribute = self::readAttributes($link);
-
-                       if (!empty($attribute['rel']) && !empty($attribute['href'])) {
-                               switch ($attribute['rel']) {
-                                       case 'alternate':
-                                               $item['plink'] = $attribute['href'];
-                                               if (($item['object-type'] == Activity\ObjectType::QUESTION)
-                                                       || ($item['object-type'] == Activity\ObjectType::EVENT)
-                                               ) {
-                                                       Post\Media::insert(['uri-id' => $item['uri-id'], 'type' => Post\Media::UNKNOWN,
-                                                               'url' => $attribute['href'], 'mimetype' => $attribute['type'] ?? null,
-                                                               'size' => $attribute['length'] ?? null, 'description' => $attribute['title'] ?? null]);
-                                               }
-                                               break;
-
-                                       case 'ostatus:conversation':
-                                               $link_data['conversation'] = $attribute['href'];
-                                               $item['conversation'] = $link_data['conversation'];
-                                               break;
-
-                                       case 'enclosure':
-                                               $filetype = strtolower(substr($attribute['type'], 0, strpos($attribute['type'], '/')));
-                                               if ($filetype == 'image') {
-                                                       $link_data['add_body'] .= "\n[img]".$attribute['href'].'[/img]';
-                                               } else {
-                                                       Post\Media::insert(['uri-id' => $item['uri-id'], 'type' => Post\Media::DOCUMENT,
-                                                               'url' => $attribute['href'], 'mimetype' => $attribute['type'],
-                                                               'size' => $attribute['length'] ?? null, 'description' => $attribute['title'] ?? null]);
-                                               }
-                                               break;
-
-                                       case 'related':
-                                               if ($item['object-type'] != Activity\ObjectType::BOOKMARK) {
-                                                       if (!isset($item['thr-parent'])) {
-                                                               $item['thr-parent'] = $attribute['href'];
-                                                       }
-                                                       $link_data['related'] = $attribute['href'];
-                                               } else {
-                                                       Post\Media::insert(['uri-id' => $item['uri-id'], 'type' => Post\Media::UNKNOWN,
-                                                               'url' => $attribute['href'], 'mimetype' => $attribute['type'] ?? null,
-                                                               'size' => $attribute['length'] ?? null, 'description' => $attribute['title'] ?? null]);
-                                               }
-                                               break;
-
-                                       case 'self':
-                                               if (empty($item['plink'])) {
-                                                       $item['plink'] = $attribute['href'];
-                                               }
-                                               $link_data['self'] = $attribute['href'];
-                                               break;
-
-                                       default:
-                                               Logger::notice('Unsupported rel=' . $attribute['rel'] . ', href=' . $attribute['href'] . ', object-type=' . $item['object-type']);
-                               }
-                       }
-               }
-               return $link_data;
-       }
-
-       /**
-        * Create an url out of an uri
-        *
-        * @param string $href URI in the format "parameter1:parameter1:..."
-        * @return string URL in the format http(s)://....
-        */
-       private static function convertHref(string $href): string
-       {
-               $elements = explode(':', $href);
-
-               if ((count($elements) <= 2) || ($elements[0] != 'tag')) {
-                       return $href;
-               }
-
-               $server = explode(',', $elements[1]);
-               $conversation = explode('=', $elements[2]);
-
-               if ((count($elements) == 4) && ($elements[2] == 'post')) {
-                       return 'http://' . $server[0] . '/notice/' . $elements[3];
-               }
-
-               if ((count($conversation) != 2) || ($conversation[1] == '')) {
-                       return $href;
-               }
-
-               if ($elements[3] == 'objectType=thread') {
-                       return 'http://' . $server[0] . '/conversation/' . $conversation[1];
-               } else {
-                       return 'http://' . $server[0] . '/notice/' . $conversation[1];
-               }
-       }
-
-       /**
-        * Adds the header elements to the XML document
-        *
-        * @param DOMDocument $doc       XML document
-        * @param array       $owner     Contact data of the poster
-        * @param string      $filter    The related feed filter (activity, posts or comments)
-        *
-        * @return DOMElement Header root element
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        */
-       private static function addHeader(DOMDocument $doc, array $owner, string $filter): DOMElement
-       {
-               $root = $doc->createElementNS(ActivityNamespace::ATOM1, 'feed');
-               $doc->appendChild($root);
-
-               $root->setAttribute('xmlns:thr', ActivityNamespace::THREAD);
-               $root->setAttribute('xmlns:georss', ActivityNamespace::GEORSS);
-               $root->setAttribute('xmlns:activity', ActivityNamespace::ACTIVITY);
-               $root->setAttribute('xmlns:media', ActivityNamespace::MEDIA);
-               $root->setAttribute('xmlns:poco', ActivityNamespace::POCO);
-               $root->setAttribute('xmlns:ostatus', ActivityNamespace::OSTATUS);
-               $root->setAttribute('xmlns:statusnet', ActivityNamespace::STATUSNET);
-               $root->setAttribute('xmlns:mastodon', ActivityNamespace::MASTODON);
-
-               $title = '';
-               $selfUri = '/feed/' . $owner['nick'] . '/';
-               switch ($filter) {
-                       case 'activity':
-                               $title = DI::l10n()->t('%s\'s timeline', $owner['name']);
-                               $selfUri .= $filter;
-                               break;
-
-                       case 'posts':
-                               $title = DI::l10n()->t('%s\'s posts', $owner['name']);
-                               break;
-
-                       case 'comments':
-                               $title = DI::l10n()->t('%s\'s comments', $owner['name']);
-                               $selfUri .= $filter;
-                               break;
-               }
-
-               $selfUri = '/dfrn_poll/' . $owner['nick'];
-
-               $attributes = [
-                       'uri' => 'https://friendi.ca',
-                       'version' => App::VERSION . '-' . DB_UPDATE_VERSION,
-               ];
-               XML::addElement($doc, $root, 'generator', App::PLATFORM, $attributes);
-               XML::addElement($doc, $root, 'id', DI::baseUrl() . '/profile/' . $owner['nick']);
-               XML::addElement($doc, $root, 'title', $title);
-               XML::addElement($doc, $root, 'subtitle', sprintf("Updates from %s on %s", $owner['name'], DI::config()->get('config', 'sitename')));
-               XML::addElement($doc, $root, 'logo', User::getAvatarUrl($owner, Proxy::SIZE_SMALL));
-               XML::addElement($doc, $root, 'updated', DateTimeFormat::utcNow(DateTimeFormat::ATOM));
-
-               $author = self::addAuthor($doc, $owner, true);
-               $root->appendChild($author);
-
-               $attributes = [
-                       'href' => $owner['url'],
-                       'rel' => 'alternate',
-                       'type' => 'text/html',
-               ];
-               XML::addElement($doc, $root, 'link', '', $attributes);
-
-               /// @TODO We have to find out what this is
-               /// $attributes = array("href" => DI::baseUrl()."/sup",
-               ///             "rel" => "http://api.friendfeed.com/2008/03#sup",
-               ///             "type" => "application/json");
-               /// XML::addElement($doc, $root, "link", "", $attributes);
-
-               self::addHubLink($doc, $root, $owner['nick']);
-
-               $attributes = ['href' => DI::baseUrl() . '/salmon/' . $owner['nick'], 'rel' => 'salmon'];
-               XML::addElement($doc, $root, 'link', '', $attributes);
-
-               $attributes = ['href' => DI::baseUrl() . '/salmon/' . $owner['nick'], 'rel' => 'http://salmon-protocol.org/ns/salmon-replies'];
-               XML::addElement($doc, $root, 'link', '', $attributes);
-
-               $attributes = ['href' => DI::baseUrl() . '/salmon/' . $owner['nick'], 'rel' => 'http://salmon-protocol.org/ns/salmon-mention'];
-               XML::addElement($doc, $root, 'link', '', $attributes);
-
-               $attributes = ['href' => DI::baseUrl() . $selfUri, 'rel' => 'self', 'type' => 'application/atom+xml'];
-               XML::addElement($doc, $root, 'link', '', $attributes);
-
-               if ($owner['contact-type'] == Contact::TYPE_COMMUNITY) {
-                       $members = DBA::count('contact', [
-                               'uid'     => $owner['uid'],
-                               'self'    => false,
-                               'pending' => false,
-                               'archive' => false,
-                               'hidden'  => false,
-                               'blocked' => false,
-                       ]);
-                       XML::addElement($doc, $root, 'statusnet:group_info', '', ['member_count' => $members]);
-               }
-
-               return $root;
-       }
-
-       /**
-        * Add the link to the push hubs to the XML document
-        *
-        * @param DOMDocument $doc  XML document
-        * @param DOMElement  $root XML root element where the hub links are added
-        * @param string      $nick Nickname
-        * @return void
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        */
-       public static function addHubLink(DOMDocument $doc, DOMElement $root, string $nick)
-       {
-               $h = DI::baseUrl() . '/pubsubhubbub/' . $nick;
-               XML::addElement($doc, $root, 'link', '', ['href' => $h, 'rel' => 'hub']);
-       }
-
-       /**
-        * Adds attachment data to the XML document
-        *
-        * @param DOMDocument $doc  XML document
-        * @param DOMElement  $root XML root element where the hub links are added
-        * @param array       $item Data of the item that is to be posted
-        * @return void
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        */
-       public static function getAttachment(DOMDocument $doc, DOMElement $root, array $item)
-       {
-               foreach (Post\Media::getByURIId($item['uri-id'], [Post\Media::AUDIO, Post\Media::IMAGE, Post\Media::VIDEO, Post\Media::DOCUMENT, Post\Media::TORRENT]) as $attachment) {
-                       $attributes = ['rel' => 'enclosure',
-                               'href' => $attachment['url'],
-                               'type' => $attachment['mimetype']];
-
-                       if (!empty($attachment['size'])) {
-                               $attributes['length'] = intval($attachment['size']);
-                       }
-                       if (!empty($attachment['description'])) {
-                               $attributes['title'] = $attachment['description'];
-                       }
-
-                       XML::addElement($doc, $root, 'link', '', $attributes);
-               }
-       }
-
-       /**
-        * Adds the author element to the XML document
-        *
-        * @param DOMDocument $doc          XML document
-        * @param array       $owner        Contact data of the poster
-        * @param bool        $show_profile Whether to show profile
-        * @return DOMElement Author element
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        */
-       private static function addAuthor(DOMDocument $doc, array $owner, bool $show_profile = true): DOMElement
-       {
-               $profile = DBA::selectFirst('profile', ['homepage', 'publish'], ['uid' => $owner['uid']]);
-               $author = $doc->createElement('author');
-               XML::addElement($doc, $author, 'id', $owner['url']);
-               if ($owner['contact-type'] == Contact::TYPE_COMMUNITY) {
-                       XML::addElement($doc, $author, 'activity:object-type', Activity\ObjectType::GROUP);
-               } else {
-                       XML::addElement($doc, $author, 'activity:object-type', Activity\ObjectType::PERSON);
-               }
-
-               XML::addElement($doc, $author, 'uri', $owner['url']);
-               XML::addElement($doc, $author, 'name', $owner['nick']);
-               XML::addElement($doc, $author, 'email', $owner['addr']);
-               if ($show_profile) {
-                       XML::addElement($doc, $author, 'summary', BBCode::convertForUriId($owner['uri-id'], $owner['about'], BBCode::OSTATUS));
-               }
-
-               $attributes = [
-                       'rel' => 'alternate',
-                       'type' => 'text/html',
-                       'href' => $owner['url'],
-               ];
-               XML::addElement($doc, $author, 'link', '', $attributes);
-
-               $attributes = [
-                       'rel' => 'avatar',
-                       'type' => 'image/jpeg', // To-Do?
-                       'media:width' => Proxy::PIXEL_SMALL,
-                       'media:height' => Proxy::PIXEL_SMALL,
-                       'href' => User::getAvatarUrl($owner, Proxy::SIZE_SMALL),
-               ];
-               XML::addElement($doc, $author, 'link', '', $attributes);
-
-               if (isset($owner['thumb'])) {
-                       $attributes = [
-                               'rel' => 'avatar',
-                               'type' => 'image/jpeg', // To-Do?
-                               'media:width' => Proxy::PIXEL_THUMB,
-                               'media:height' => Proxy::PIXEL_THUMB,
-                               'href' => User::getAvatarUrl($owner, Proxy::SIZE_THUMB),
-                       ];
-                       XML::addElement($doc, $author, 'link', '', $attributes);
-               }
-
-               XML::addElement($doc, $author, 'poco:preferredUsername', $owner['nick']);
-               XML::addElement($doc, $author, 'poco:displayName', $owner['name']);
-               if ($show_profile) {
-                       XML::addElement($doc, $author, 'poco:note', BBCode::convertForUriId($owner['uri-id'], $owner['about'], BBCode::OSTATUS));
-
-                       if (trim($owner['location']) != '') {
-                               $element = $doc->createElement('poco:address');
-                               XML::addElement($doc, $element, 'poco:formatted', $owner['location']);
-                               $author->appendChild($element);
-                       }
-               }
-
-               if (DBA::isResult($profile) && !$show_profile) {
-                       if (trim($profile['homepage']) != '') {
-                               $urls = $doc->createElement('poco:urls');
-                               XML::addElement($doc, $urls, 'poco:type', 'homepage');
-                               XML::addElement($doc, $urls, 'poco:value', $profile['homepage']);
-                               XML::addElement($doc, $urls, 'poco:primary', 'true');
-                               $author->appendChild($urls);
-                       }
-
-                       XML::addElement($doc, $author, 'followers', '', ['url' => DI::baseUrl() . '/profile/' . $owner['nick'] . '/contacts/followers']);
-                       XML::addElement($doc, $author, 'statusnet:profile_info', '', ['local_id' => $owner['uid']]);
-
-                       if ($profile['publish']) {
-                               XML::addElement($doc, $author, 'mastodon:scope', 'public');
-                       }
-               }
-
-               return $author;
-       }
-
-       /**
-        * @TODO Picture attachments should look like this:
-        *      <a href="https://status.pirati.ca/attachment/572819" title="https://status.pirati.ca/file/heluecht-20151202T222602-rd3u49p.gif"
-        *      class="attachment thumbnail" id="attachment-572819" rel="nofollow external">https://status.pirati.ca/attachment/572819</a>
-        */
-
-       /**
-        * Returns the given activity if present - otherwise returns the "post" activity
-        *
-        * @param array $item Data of the item that is to be posted
-        * @return string activity
-        */
-       public static function constructVerb(array $item): string
-       {
-               if (!empty($item['verb'])) {
-                       return $item['verb'];
-               }
-
-               return Activity::POST;
-       }
-
-       /**
-        * Returns the given object type if present - otherwise returns the "note" object type
-        *
-        * @param array $item Data of the item that is to be posted
-        * @return string Object type
-        */
-       private static function constructObjecttype(array $item): string
-       {
-               if (!empty($item['object-type']) && in_array($item['object-type'], [Activity\ObjectType::NOTE, Activity\ObjectType::COMMENT])) {
-                       return $item['object-type'];
-               }
-
-               return Activity\ObjectType::NOTE;
-       }
-
-       /**
-        * Adds an entry element to the XML document
-        *
-        * @param DOMDocument $doc       XML document
-        * @param array       $item      Data of the item that is to be posted
-        * @param array       $owner     Contact data of the poster
-        * @param bool        $toplevel  optional default false
-        *
-        * @return DOMElement Entry element
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        * @throws \ImagickException
-        */
-       private static function entry(DOMDocument $doc, array $item, array $owner, bool $toplevel = false): DOMElement
-       {
-               if ($item['verb'] == Activity::LIKE) {
-                       return self::likeEntry($doc, $item, $owner, $toplevel);
-               } elseif (in_array($item['verb'], [Activity::FOLLOW, Activity::O_UNFOLLOW])) {
-                       return self::followEntry($doc, $item, $owner, $toplevel);
-               } else {
-                       return self::noteEntry($doc, $item, $owner, $toplevel);
-               }
-       }
-
-       /**
-        * Adds an entry element with a "like"
-        *
-        * @param DOMDocument $doc      XML document
-        * @param array       $item     Data of the item that is to be posted
-        * @param array       $owner    Contact data of the poster
-        * @param bool        $toplevel Is it for en entry element (false) or a feed entry (true)?
-        * @return DOMElement Entry element with "like"
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        * @throws \ImagickException
-        */
-       private static function likeEntry(DOMDocument $doc, array $item, array $owner, bool $toplevel): DOMElement
-       {
-               if (($item['gravity'] != Item::GRAVITY_PARENT) && (Strings::normaliseLink($item['author-link']) != Strings::normaliseLink($owner['url']))) {
-                       Logger::info('OStatus entry is from author ' . $owner['url'] . ' - not from ' . $item['author-link'] . '. Quitting.');
-               }
-
-               $entry = self::entryHeader($doc, $owner, $item, $toplevel);
-
-               $verb = ActivityNamespace::ACTIVITY_SCHEMA . 'favorite';
-               self::entryContent($doc, $entry, $item, $owner, 'Favorite', $verb, false);
-
-               $parent = Post::selectFirst([], ['uri' => $item['thr-parent'], 'uid' => $item['uid']]);
-               if (DBA::isResult($parent)) {
-                       $as_object = $doc->createElement('activity:object');
-
-                       XML::addElement($doc, $as_object, 'activity:object-type', self::constructObjecttype($parent));
-
-                       self::entryContent($doc, $as_object, $parent, $owner, 'New entry');
-
-                       $entry->appendChild($as_object);
-               }
-
-               self::entryFooter($doc, $entry, $item, $owner);
-
-               return $entry;
-       }
-
-       /**
-        * Adds the person object element to the XML document
-        *
-        * @param DOMDocument $doc     XML document
-        * @param array       $owner   Contact data of the poster
-        * @param array       $contact Contact data of the target
-        * @return DOMElement author element
-        */
-       private static function addPersonObject(DOMDocument $doc, array $owner, array $contact): DOMElement
-       {
-               $object = $doc->createElement('activity:object');
-               XML::addElement($doc, $object, 'activity:object-type', Activity\ObjectType::PERSON);
-
-               if ($contact['network'] == Protocol::PHANTOM) {
-                       XML::addElement($doc, $object, 'id', $contact['url']);
-                       return $object;
-               }
-
-               XML::addElement($doc, $object, 'id', $contact['alias']);
-               XML::addElement($doc, $object, 'title', $contact['nick']);
-
-               XML::addElement($doc, $object, 'link', '', [
-                       'rel' => 'alternate',
-                       'type' => 'text/html',
-                       'href' => $contact['url'],
-               ]);
-
-               $attributes = [
-                       'rel' => 'avatar',
-                       'type' => 'image/jpeg', // To-Do?
-                       'media:width' => 300,
-                       'media:height' => 300,
-                       'href' => $contact['photo'],
-               ];
-               XML::addElement($doc, $object, 'link', '', $attributes);
-
-               XML::addElement($doc, $object, 'poco:preferredUsername', $contact['nick']);
-               XML::addElement($doc, $object, 'poco:displayName', $contact['name']);
-
-               if (trim($contact['location']) != '') {
-                       $element = $doc->createElement('poco:address');
-                       XML::addElement($doc, $element, 'poco:formatted', $contact['location']);
-                       $object->appendChild($element);
-               }
-
-               return $object;
-       }
-
-       /**
-        * Adds a follow/unfollow entry element
-        *
-        * @param DOMDocument $doc      XML document
-        * @param array       $item     Data of the follow/unfollow message
-        * @param array       $owner    Contact data of the poster
-        * @param bool        $toplevel Is it for en entry element (false) or a feed entry (true)?
-        * @return DOMElement Entry element
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        * @throws \ImagickException
-        */
-       private static function followEntry(DOMDocument $doc, array $item, array $owner, bool $toplevel): DOMElement
-       {
-               $item['id'] = $item['parent'] = 0;
-               $item['created'] = $item['edited'] = date('c');
-               $item['private'] = Item::PRIVATE;
-
-               $contact = Contact::getByURL($item['follow']);
-               $item['follow'] = $contact['url'];
-
-               if ($contact['alias']) {
-                       $item['follow'] = $contact['alias'];
-               } else {
-                       $contact['alias'] = $contact['url'];
-               }
-
-               $condition = ['uid' => $owner['uid'], 'nurl' => Strings::normaliseLink($contact['url'])];
-               $user_contact = DBA::selectFirst('contact', ['id'], $condition);
-
-               if (DBA::isResult($user_contact)) {
-                       $connect_id = $user_contact['id'];
-               } else {
-                       $connect_id = 0;
-               }
-
-               if ($item['verb'] == Activity::FOLLOW) {
-                       $message = DI::l10n()->t('%s is now following %s.');
-                       $title = DI::l10n()->t('following');
-                       $action = 'subscription';
-               } else {
-                       $message = DI::l10n()->t('%s stopped following %s.');
-                       $title = DI::l10n()->t('stopped following');
-                       $action = 'unfollow';
-               }
-
-               $item['uri'] = $item['parent-uri'] = $item['thr-parent']
-                               = 'tag:' . DI::baseUrl()->getHost() .
-                                 ','.date('Y-m-d').':'.$action.':'.$owner['uid'].
-                               ':person:'.$connect_id.':'.$item['created'];
-
-               $item['body'] = sprintf($message, $owner['nick'], $contact['nick']);
-
-               $entry = self::entryHeader($doc, $owner, $item, $toplevel);
-
-               self::entryContent($doc, $entry, $item, $owner, $title);
-
-               $object = self::addPersonObject($doc, $owner, $contact);
-               $entry->appendChild($object);
-
-               self::entryFooter($doc, $entry, $item, $owner);
-
-               return $entry;
-       }
-
-       /**
-        * Adds a regular entry element
-        *
-        * @param DOMDocument $doc       XML document
-        * @param array       $item      Data of the item that is to be posted
-        * @param array       $owner     Contact data of the poster
-        * @param bool        $toplevel  Is it for en entry element (false) or a feed entry (true)?
-        * @return DOMElement Entry element
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        * @throws \ImagickException
-        */
-       private static function noteEntry(DOMDocument $doc, array $item, array $owner, bool $toplevel): DOMElement
-       {
-               if (($item['gravity'] != Item::GRAVITY_PARENT) && (Strings::normaliseLink($item['author-link']) != Strings::normaliseLink($owner['url']))) {
-                       Logger::info('OStatus entry is from author ' . $owner['url'] . ' - not from ' . $item['author-link'] . '. Quitting.');
-               }
-
-               if (!$toplevel) {
-                       if (!empty($item['title'])) {
-                               $title = BBCode::convertForUriId($item['uri-id'], $item['title'], BBCode::OSTATUS);
-                       } else {
-                               $title = sprintf('New note by %s', $owner['nick']);
-                       }
-               } else {
-                       $title = sprintf('New comment by %s', $owner['nick']);
-               }
-
-               $entry = self::entryHeader($doc, $owner, $item, $toplevel);
-
-               XML::addElement($doc, $entry, 'activity:object-type', Activity\ObjectType::NOTE);
-
-               self::entryContent($doc, $entry, $item, $owner, $title, '', true);
-
-               self::entryFooter($doc, $entry, $item, $owner, true);
-
-               return $entry;
-       }
-
-       /**
-        * Adds a header element to the XML document
-        *
-        * @param DOMDocument $doc      XML document
-        * @param array       $owner    Contact data of the poster
-        * @param array       $item
-        * @param bool        $toplevel Is it for en entry element (false) or a feed entry (true)?
-        * @return DOMElement The entry element where the elements are added
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        * @throws \ImagickException
-        */
-       public static function entryHeader(DOMDocument $doc, array $owner, array $item, bool $toplevel): DOMElement
-       {
-               if (!$toplevel) {
-                       $entry = $doc->createElement('entry');
-
-                       if ($owner['contact-type'] == Contact::TYPE_COMMUNITY) {
-                               $entry->setAttribute('xmlns:activity', ActivityNamespace::ACTIVITY);
-
-                               $contact = Contact::getByURL($item['author-link']) ?: $owner;
-                               $contact['nickname'] = $contact['nickname'] ?? $contact['nick'];
-                               $author = self::addAuthor($doc, $contact, false);
-                               $entry->appendChild($author);
-                       }
-               } else {
-                       $entry = $doc->createElementNS(ActivityNamespace::ATOM1, 'entry');
-
-                       $entry->setAttribute('xmlns:thr', ActivityNamespace::THREAD);
-                       $entry->setAttribute('xmlns:georss', ActivityNamespace::GEORSS);
-                       $entry->setAttribute('xmlns:activity', ActivityNamespace::ACTIVITY);
-                       $entry->setAttribute('xmlns:media', ActivityNamespace::MEDIA);
-                       $entry->setAttribute('xmlns:poco', ActivityNamespace::POCO);
-                       $entry->setAttribute('xmlns:ostatus', ActivityNamespace::OSTATUS);
-                       $entry->setAttribute('xmlns:statusnet', ActivityNamespace::STATUSNET);
-                       $entry->setAttribute('xmlns:mastodon', ActivityNamespace::MASTODON);
-
-                       $author = self::addAuthor($doc, $owner);
-                       $entry->appendChild($author);
-               }
-
-               return $entry;
-       }
-
-       /**
-        * Adds elements to the XML document
-        *
-        * @param DOMDocument $doc       XML document
-        * @param DOMElement  $entry     Entry element where the content is added
-        * @param array       $item      Data of the item that is to be posted
-        * @param array       $owner     Contact data of the poster
-        * @param string      $title     Title for the post
-        * @param string      $verb      The activity verb
-        * @param bool        $complete  Add the "status_net" element?
-        * @return void
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        */
-       private static function entryContent(DOMDocument $doc, DOMElement $entry, array $item, array $owner, string $title, string $verb = '', bool $complete = true)
-       {
-               if ($verb == '') {
-                       $verb = self::constructVerb($item);
-               }
-
-               XML::addElement($doc, $entry, 'id', $item['uri']);
-               XML::addElement($doc, $entry, 'title', html_entity_decode($title, ENT_QUOTES, 'UTF-8'));
-
-               $body = Post\Media::addAttachmentsToBody($item['uri-id'], DI::contentItem()->addSharedPost($item));
-               $body = Post\Media::addHTMLLinkToBody($item['uri-id'], $body);
-
-               if (!empty($item['title'])) {
-                       $body = '[b]' . $item['title'] . "[/b]\n\n" . $body;
-               }
-
-               $body = BBCode::convertForUriId($item['uri-id'], $body, BBCode::OSTATUS);
-
-               XML::addElement($doc, $entry, 'content', $body, ['type' => 'html']);
-
-               XML::addElement($doc, $entry, 'link', '', [
-                       'rel' => 'alternate',
-                       'type' => 'text/html',
-                       'href' => DI::baseUrl() . '/display/' . $item['guid'],
-               ]);
-
-               if ($complete && ($item['id'] > 0)) {
-                       XML::addElement($doc, $entry, 'status_net', '', ['notice_id' => $item['id']]);
-               }
-
-               XML::addElement($doc, $entry, 'activity:verb', $verb);
-
-               XML::addElement($doc, $entry, 'published', DateTimeFormat::utc($item['created'] . '+00:00', DateTimeFormat::ATOM));
-               XML::addElement($doc, $entry, 'updated', DateTimeFormat::utc($item['edited'] . '+00:00', DateTimeFormat::ATOM));
-       }
-
-       /**
-        * Adds the elements at the foot of an entry to the XML document
-        *
-        * @param DOMDocument $doc       XML document
-        * @param object      $entry     The entry element where the elements are added
-        * @param array       $item      Data of the item that is to be posted
-        * @param array       $owner     Contact data of the poster
-        * @param bool        $complete  default true
-        * @return void
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        */
-       private static function entryFooter(DOMDocument $doc, $entry, array $item, array $owner, bool $complete = true)
-       {
-               $mentioned = [];
-
-               if ($item['gravity'] != Item::GRAVITY_PARENT) {
-                       $parent = Post::selectFirst(['guid', 'author-link', 'owner-link'], ['id' => $item['parent']]);
-
-                       $thrparent = Post::selectFirst(['guid', 'author-link', 'owner-link', 'plink'], ['uid' => $owner['uid'], 'uri' => $item['thr-parent']]);
-
-                       if (DBA::isResult($thrparent)) {
-                               $mentioned[$thrparent['author-link']] = $thrparent['author-link'];
-                               $mentioned[$thrparent['owner-link']]  = $thrparent['owner-link'];
-                               $parent_plink                         = $thrparent['plink'];
-                       } elseif (DBA::isResult($parent)) {
-                               $mentioned[$parent['author-link']] = $parent['author-link'];
-                               $mentioned[$parent['owner-link']]  = $parent['owner-link'];
-                               $parent_plink                      = DI::baseUrl() . '/display/' . $parent['guid'];
-                       } else {
-                               DI::logger()->notice('Missing parent and thr-parent for child item', ['item' => $item]);
-                       }
-
-                       if (isset($parent_plink)) {
-                               $attributes = [
-                                       'ref'  => $item['thr-parent'],
-                                       'href' => $parent_plink];
-                               XML::addElement($doc, $entry, 'thr:in-reply-to', '', $attributes);
-
-                               $attributes = [
-                                       'rel'  => 'related',
-                                       'href' => $parent_plink];
-                               XML::addElement($doc, $entry, 'link', '', $attributes);
-                       }
-               }
-
-               if (intval($item['parent']) > 0) {
-                       $conversation_href = $conversation_uri = $item['conversation'];
-
-                       XML::addElement($doc, $entry, 'link', '', ['rel' => 'ostatus:conversation', 'href' => $conversation_href]);
-
-                       $attributes = [
-                               'href' => $conversation_href,
-                               'local_id' => $item['parent'],
-                               'ref' => $conversation_uri,
-                       ];
-
-                       XML::addElement($doc, $entry, 'ostatus:conversation', $conversation_uri, $attributes);
-               }
-
-               // uri-id isn't present for follow entry pseudo-items
-               $tags = Tag::getByURIId($item['uri-id'] ?? 0);
-               foreach ($tags as $tag) {
-                       $mentioned[$tag['url']] = $tag['url'];
-               }
-
-               // Make sure that mentions are accepted (GNU Social has problems with mixing HTTP and HTTPS)
-               $newmentions = [];
-               foreach ($mentioned as $mention) {
-                       $newmentions[str_replace('http://', 'https://', $mention)] = str_replace('http://', 'https://', $mention);
-                       $newmentions[str_replace('https://', 'http://', $mention)] = str_replace('https://', 'http://', $mention);
-               }
-               $mentioned = $newmentions;
-
-               foreach ($mentioned as $mention) {
-                       $contact = Contact::getByURL($mention, false, ['contact-type']);
-                       if (!empty($contact) && ($contact['contact-type'] == Contact::TYPE_COMMUNITY)) {
-                               XML::addElement($doc, $entry, 'link', '', [
-                                       'rel' => 'mentioned',
-                                       'ostatus:object-type' => Activity\ObjectType::GROUP,
-                                       'href' => $mention,
-                               ]);
-                       } else {
-                               XML::addElement($doc, $entry, 'link', '', [
-                                       'rel' => 'mentioned',
-                                       'ostatus:object-type' => Activity\ObjectType::PERSON,
-                                               'href' => $mention,
-                               ]);
-                       }
-               }
-
-               if ($owner['contact-type'] == Contact::TYPE_COMMUNITY) {
-                       XML::addElement($doc, $entry, 'link', '', [
-                               'rel' => 'mentioned',
-                               'ostatus:object-type' => 'http://activitystrea.ms/schema/1.0/group',
-                               'href' => $owner['url']
-                       ]);
-               }
-
-               if ($item['private'] != Item::PRIVATE) {
-                       XML::addElement($doc, $entry, 'link', '', ['rel' => 'ostatus:attention',
-                                                                       'href' => 'http://activityschema.org/collection/public']);
-                       XML::addElement($doc, $entry, 'link', '', ['rel' => 'mentioned',
-                                                                       'ostatus:object-type' => 'http://activitystrea.ms/schema/1.0/collection',
-                                                                       'href' => 'http://activityschema.org/collection/public']);
-                       XML::addElement($doc, $entry, 'mastodon:scope', 'public');
-               }
-
-               foreach ($tags as $tag) {
-                       if ($tag['type'] == Tag::HASHTAG) {
-                               XML::addElement($doc, $entry, 'category', '', ['term' => $tag['name']]);
-                       }
-               }
-
-               self::getAttachment($doc, $entry, $item);
-
-               if ($complete && ($item['id'] > 0)) {
-                       $app = $item['app'];
-                       if ($app == '') {
-                               $app = 'web';
-                       }
-
-                       $attributes = ['local_id' => $item['id'], 'source' => $app];
-
-                       if (isset($parent['id'])) {
-                               $attributes['repeat_of'] = $parent['id'];
-                       }
-
-                       if ($item['coord'] != '') {
-                               XML::addElement($doc, $entry, 'georss:point', $item['coord']);
-                       }
-
-                       XML::addElement($doc, $entry, 'statusnet:notice_info', '', $attributes);
-               }
-       }
-
-       /**
-        * Creates the XML feed for a given nickname
-        *
-        * Supported filters:
-        * - activity (default): all the public posts
-        * - posts: all the public top-level posts
-        * - comments: all the public replies
-        *
-        * Updates the provided last_update parameter if the result comes from the
-        * cache or it is empty
-        *
-        * @param string  $owner_nick  Nickname of the feed owner
-        * @param string  $last_update Date of the last update (in "Y-m-d H:i:s" format)
-        * @param integer $max_items   Number of maximum items to fetch
-        * @param string  $filter      Feed items filter (activity, posts or comments)
-        * @param boolean $nocache     Wether to bypass caching
-        * @return string XML feed or empty string on error
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        * @throws \ImagickException
-        */
-       public static function feed(string $owner_nick, string &$last_update, int $max_items = 300, string $filter = 'activity', bool $nocache = false): string
-       {
-               $stamp = microtime(true);
-
-               $owner = User::getOwnerDataByNick($owner_nick);
-               if (!$owner) {
-                       return '';
-               }
-
-               $cachekey = 'ostatus:feed:' . $owner_nick . ':' . $filter . ':' . $last_update;
-
-               $previous_created = $last_update;
-
-               // Don't cache when the last item was posted less than 15 minutes ago (Cache duration)
-               if ((time() - strtotime($owner['last-item'])) < 15*60) {
-                       $result = DI::cache()->get($cachekey);
-                       if (!$nocache && !is_null($result)) {
-                               Logger::info('Feed duration: ' . number_format(microtime(true) - $stamp, 3) . ' - ' . $owner_nick . ' - ' . $filter . ' - ' . $previous_created . ' (cached)');
-                               $last_update = $result['last_update'];
-                               return $result['feed'];
-                       }
-               }
-
-               if (!strlen($last_update)) {
-                       $last_update = 'now -30 days';
-               }
-
-               $check_date = DateTimeFormat::utc($last_update);
-               $authorid = Contact::getIdForURL($owner['url']);
-
-               $condition = [
-                       "`uid` = ? AND `received` > ? AND NOT `deleted` AND `private` != ? AND `visible` AND `wall` AND `parent-network` IN (?, ?)",
-                       $owner['uid'],
-                       $check_date,
-                       Item::PRIVATE,
-                       Protocol::OSTATUS,
-                       Protocol::DFRN,
-               ];
-
-               if ($filter === 'comments') {
-                       $condition[0] .= " AND `object-type` = ? ";
-                       $condition[] = Activity\ObjectType::COMMENT;
-               }
-
-               if ($owner['contact-type'] != Contact::TYPE_COMMUNITY) {
-                       $condition[0] .= " AND `contact-id` = ? AND `author-id` = ?";
-                       $condition[] = $owner['id'];
-                       $condition[] = $authorid;
-               }
-
-               $params = ['order' => ['received' => true], 'limit' => $max_items];
-
-               if ($filter === 'posts') {
-                       $ret = Post::selectThread([], $condition, $params);
-               } else {
-                       $ret = Post::select([], $condition, $params);
-               }
-
-               $items = Post::toArray($ret);
-
-               $doc = new DOMDocument('1.0', 'utf-8');
-               $doc->formatOutput = true;
-
-               $root = self::addHeader($doc, $owner, $filter);
-
-               foreach ($items as $item) {
-                       if (DI::config()->get('system', 'ostatus_debug')) {
-                               $item['body'] .= '🍼';
-                       }
-
-                       if (in_array($item['verb'], [Activity::FOLLOW, Activity::O_UNFOLLOW, Activity::LIKE])) {
-                               continue;
-                       }
-
-                       $entry = self::entry($doc, $item, $owner, false);
-                       $root->appendChild($entry);
-
-                       if ($last_update < $item['created']) {
-                               $last_update = $item['created'];
-                       }
-               }
-
-               $feeddata = trim($doc->saveXML());
-
-               $msg = ['feed' => $feeddata, 'last_update' => $last_update];
-               DI::cache()->set($cachekey, $msg, Duration::QUARTER_HOUR);
-
-               Logger::info('Feed duration: ' . number_format(microtime(true) - $stamp, 3) . ' - ' . $owner_nick . ' - ' . $filter . ' - ' . $previous_created);
-
-               return $feeddata;
-       }
-
-       /**
-        * Creates the XML for a salmon message
-        *
-        * @param array $item  Data of the item that is to be posted
-        * @param array $owner Contact data of the poster
-        *
-        * @return string XML for the salmon
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        * @throws \ImagickException
-        */
-       public static function salmon(array $item, array $owner): string
-       {
-               $doc = new DOMDocument('1.0', 'utf-8');
-               $doc->formatOutput = true;
-
-               if (DI::config()->get('system', 'ostatus_debug')) {
-                       $item['body'] .= '🐟';
-               }
-
-               $entry = self::entry($doc, $item, $owner, true);
-
-               $doc->appendChild($entry);
-
-               return trim($doc->saveXML());
-       }
-
-       /**
-        * Checks if the given contact url does support OStatus
-        *
-        * @param string  $url    profile url
-        * @return boolean
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        * @throws \ImagickException
-        */
-       public static function isSupportedByContactUrl(string $url): bool
-       {
-               $probe = Probe::uri($url, Protocol::OSTATUS);
-               return $probe['network'] == Protocol::OSTATUS;
-       }
-}
index 7b0ffb7b34609d0a33d9eb1a24f21e205b0bbb1f..5d8673e8a65fbc4e8159b984dcfe7f37056a0554 100644 (file)
@@ -7,17 +7,7 @@
 
 namespace Friendica\Protocol;
 
-use Friendica\Core\Logger;
-use Friendica\Core\Protocol;
-use Friendica\DI;
-use Friendica\Model\Item;
-use Friendica\Network\HTTPClient\Client\HttpClientAccept;
-use Friendica\Network\HTTPClient\Client\HttpClientRequest;
-use Friendica\Network\Probe;
 use Friendica\Protocol\Salmon\Format\Magic;
-use Friendica\Util\Crypto;
-use Friendica\Util\Strings;
-use Friendica\Util\XML;
 use phpseclib3\Crypt\PublicKeyLoader;
 
 /**
@@ -28,206 +18,6 @@ use phpseclib3\Crypt\PublicKeyLoader;
  */
 class Salmon
 {
-       /**
-        * @param string $uri     Uniform Resource Identifier
-        * @param string $keyhash encoded key
-        * @return string Key or empty string on any errors
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        */
-       public static function getKey(string $uri, string $keyhash): string
-       {
-               $ret = [];
-
-               Logger::info('Fetching salmon key for ' . $uri);
-
-               $arr = Probe::lrdd($uri);
-
-               if (is_array($arr)) {
-                       foreach ($arr as $a) {
-                               if ($a['@attributes']['rel'] === 'magic-public-key') {
-                                       $ret[] = $a['@attributes']['href'];
-                               }
-                       }
-               } else {
-                       return '';
-               }
-
-               // We have found at least one key URL
-               // If it's inline, parse it - otherwise get the key
-
-               if (count($ret) > 0) {
-                       for ($x = 0; $x < count($ret); $x++) {
-                               if (substr($ret[$x], 0, 5) === 'data:') {
-                                       if (strstr($ret[$x], ',')) {
-                                               $ret[$x] = substr($ret[$x], strpos($ret[$x], ',') + 1);
-                                       } else {
-                                               $ret[$x] = substr($ret[$x], 5);
-                                       }
-                               } elseif (Strings::normaliseLink($ret[$x]) == 'http://') {
-                                       $ret[$x] = DI::httpClient()->fetch($ret[$x], HttpClientAccept::MAGIC_KEY, 0, '', HttpClientRequest::SALMON);
-                                       Logger::debug('Fetched public key', ['url' => $ret[$x]]);
-                               }
-                       }
-               }
-
-
-               Logger::notice('Key located', ['ret' => $ret]);
-
-               if (count($ret) == 1) {
-                       /* We only found one key so we don't care if the hash matches.
-                        * If it's the wrong key we'll find out soon enough because
-                        * message verification will fail. This also covers some older
-                        * software which don't supply a keyhash. As long as they only
-                        * have one key we'll be right.
-                        */
-                       return (string) $ret[0];
-               } else {
-                       foreach ($ret as $a) {
-                               $hash = Strings::base64UrlEncode(hash('sha256', $a));
-                               if ($hash == $keyhash) {
-                                       return $a;
-                               }
-                       }
-               }
-
-               return '';
-       }
-
-       /**
-        * @param array  $owner owner
-        * @param string $url   url
-        * @param string $slap  slap
-        * @return integer
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        */
-       public static function slapper(array $owner, string $url, string $slap): int
-       {
-               // does contact have a salmon endpoint?
-
-               if (!strlen($url)) {
-                       return -1;
-               }
-
-               if (!$owner['sprvkey']) {
-                       Logger::notice(sprintf(
-                               "user '%s' (%d) does not have a salmon private key. Send failed.",
-                               $owner['name'],
-                               $owner['uid']
-                       ));
-                       return -1;
-               }
-
-               Logger::info('slapper called for ' . $url . '. Data: ' . $slap);
-
-               // create a magic envelope
-
-               $data      = Strings::base64UrlEncode($slap);
-               $data_type = 'application/atom+xml';
-               $encoding  = 'base64url';
-               $algorithm = 'RSA-SHA256';
-               $keyhash   = Strings::base64UrlEncode(hash('sha256', self::salmonKey($owner['spubkey'])), true);
-
-               $precomputed = '.' . Strings::base64UrlEncode($data_type) . '.' . Strings::base64UrlEncode($encoding) . '.' . Strings::base64UrlEncode($algorithm);
-
-               // GNU Social format
-               $signature   = Strings::base64UrlEncode(Crypto::rsaSign($data . $precomputed, $owner['sprvkey']));
-
-               // Compliant format
-               $signature2  = Strings::base64UrlEncode(Crypto::rsaSign(str_replace('=', '', $data . $precomputed), $owner['sprvkey']));
-
-               // Old Status.net format
-               $signature3  = Strings::base64UrlEncode(Crypto::rsaSign($data, $owner['sprvkey']));
-
-               // At first try the non compliant method that works for GNU Social
-               $xmldata = [
-                       'me:env' => [
-                               'me:data' => $data,
-                               '@attributes' => ['type' => $data_type],
-                               'me:encoding' => $encoding,
-                               'me:alg' => $algorithm,
-                               'me:sig' => $signature,
-                               '@attributes2' => ['key_id' => $keyhash],
-                       ]
-               ];
-
-               $namespaces = ['me' => ActivityNamespace::SALMON_ME];
-
-               $salmon = XML::fromArray($xmldata, $dummy, false, $namespaces);
-
-               // slap them
-               $postResult = DI::httpClient()->post($url, $salmon, [
-                       'Content-type' => 'application/magic-envelope+xml',
-                       'Content-length' => strlen($salmon),
-               ], 0, HttpClientRequest::SALMON);
-
-               $return_code = $postResult->getReturnCode();
-
-               // check for success, e.g. 2xx
-
-               if ($return_code > 299) {
-                       Logger::notice('GNU Social salmon failed. Falling back to compliant mode');
-
-                       // Now try the compliant mode that normally isn't used for GNU Social
-                       $xmldata = [
-                               'me:env' => [
-                                       'me:data' => $data,
-                                       '@attributes' => ['type' => $data_type],
-                                       'me:encoding' => $encoding,
-                                       'me:alg' => $algorithm,
-                                       'me:sig' => $signature2,
-                                       '@attributes2' => ['key_id' => $keyhash]
-                               ]
-                       ];
-
-                       $salmon = XML::fromArray($xmldata, $dummy, false, $namespaces);
-
-                       // slap them
-                       $postResult = DI::httpClient()->post($url, $salmon, [
-                               'Content-type' => 'application/magic-envelope+xml',
-                               'Content-length' => strlen($salmon),
-                       ], 0, HttpClientRequest::SALMON);
-                       $return_code = $postResult->getReturnCode();
-               }
-
-               if ($return_code > 299) {
-                       Logger::notice('compliant salmon failed. Falling back to old status.net');
-
-                       // Last try. This will most likely fail as well.
-                       $xmldata = [
-                               'me:env' => [
-                                       'me:data' => $data,
-                                       '@attributes' => ['type' => $data_type],
-                                       'me:encoding' => $encoding,
-                                       'me:alg' => $algorithm,
-                                       'me:sig' => $signature3,
-                                       '@attributes2' => ['key_id' => $keyhash],
-                               ]
-                       ];
-
-                       $salmon = XML::fromArray($xmldata, $dummy, false, $namespaces);
-
-                       // slap them
-                       $postResult = DI::httpClient()->post($url, $salmon, [
-                               'Content-type' => 'application/magic-envelope+xml',
-                               'Content-length' => strlen($salmon)
-                       ], 0, HttpClientRequest::SALMON);
-                       $return_code = $postResult->getReturnCode();
-               }
-
-               Item::incrementOutbound(Protocol::OSTATUS);
-               Logger::info('slapper for ' . $url . ' returned ' . $return_code);
-
-               if (!$return_code) {
-                       return -1;
-               }
-
-               if (($return_code == 503) && $postResult->inHeader('retry-after')) {
-                       return -1;
-               }
-
-               return (($return_code >= 200) && ($return_code < 300)) ? 0 : 1;
-       }
-
        /**
         * @param string $pubkey public key
         * @return string
index 1d074ae9d51e1a07de361a05a3806a226d8577f6..5c32f80fec5f475bafeab1cbeb0c695ecd0c6333 100644 (file)
@@ -71,7 +71,7 @@ class MergeContact
         */
        private static function mergePersonalContacts(int $first, int $duplicate)
        {
-               $fields = ['self', 'remote_self', 'rel', 'prvkey', 'subhub', 'hub-verify', 'priority', 'writable', 'archive', 'pending',
+               $fields = ['self', 'remote_self', 'rel', 'prvkey', 'hub-verify', 'priority', 'writable', 'archive', 'pending',
                        'rating', 'notify_new_posts', 'fetch_further_information', 'ffi_keyword_denylist', 'block_reason'];
                $c1 = Contact::getById($first, $fields);
                $c2 = Contact::getById($duplicate, $fields);
@@ -87,7 +87,7 @@ class MergeContact
                        $ctarget[$field] = $c1[$field] ?: $c2[$field];
                }
 
-               foreach (['remote_self', 'subhub', 'writable', 'notify_new_posts'] as $field) {
+               foreach (['remote_self', 'writable', 'notify_new_posts'] as $field) {
                        $ctarget[$field] = $c1[$field] || $c2[$field];
                }
 
index 8aabb9217c5219486b20ad111ec6c65138da406f..73ff4685f84e5853c18911f358a5e0404962d8fa 100644 (file)
@@ -19,17 +19,13 @@ use Friendica\Model\Circle;
 use Friendica\Model\GServer;
 use Friendica\Model\Item;
 use Friendica\Model\Post;
-use Friendica\Model\PushSubscriber;
 use Friendica\Model\Tag;
 use Friendica\Model\User;
 use Friendica\Protocol\Activity;
 use Friendica\Protocol\ActivityPub;
 use Friendica\Protocol\Diaspora;
 use Friendica\Protocol\Delivery;
-use Friendica\Protocol\OStatus;
-use Friendica\Protocol\Salmon;
 use Friendica\Util\LDSignature;
-use Friendica\Util\Network;
 use Friendica\Util\Strings;
 
 /*
@@ -52,7 +48,6 @@ class Notifier
                $target_id = $post_uriid;
                $top_level = false;
                $recipients = [];
-               $url_recipients = [];
 
                $delivery_contacts_stmt = null;
                $target_item = [];
@@ -149,12 +144,6 @@ class Notifier
 
                $unlisted = false;
 
-               // Do a PuSH
-               $push_notify = false;
-
-               // Deliver directly to a group, don't PuSH
-               $direct_group_delivery = false;
-
                $only_ap_delivery = false;
 
                $followup = false;
@@ -268,32 +257,6 @@ class Notifier
                                $recipients_followup  = [$parent['contact-id']];
 
                                Logger::info('Followup', ['target' => $target_id, 'guid' => $target_item['guid'], 'to' => $parent['contact-id']]);
-
-                               if (($target_item['private'] != Item::PRIVATE) &&
-                                       (strlen($target_item['allow_cid'].$target_item['allow_gid'].
-                                               $target_item['deny_cid'].$target_item['deny_gid']) == 0))
-                                       $push_notify = true;
-
-                               if (($thr_parent && ($thr_parent['network'] == Protocol::OSTATUS)) || ($parent['network'] == Protocol::OSTATUS)) {
-                                       $push_notify = true;
-
-                                       if ($parent["network"] == Protocol::OSTATUS) {
-                                               // Distribute the message to the DFRN contacts as if this wasn't a followup since OStatus can't relay comments
-                                               // Currently it is work at progress
-                                               $condition = ['uid' => $uid, 'network' => Protocol::DFRN, 'blocked' => false, 'pending' => false, 'archive' => false];
-                                               $followup_contacts_stmt = DBA::select('contact', ['id'], $condition);
-                                               while($followup_contact = DBA::fetch($followup_contacts_stmt)) {
-                                                       $recipients_followup[] = $followup_contact['id'];
-                                               }
-                                               DBA::close($followup_contacts_stmt);
-                                       }
-                               }
-
-                               if ($direct_group_delivery) {
-                                       $push_notify = false;
-                               }
-
-                               Logger::info('Notify ' . $target_item["guid"] .' via PuSH: ' . ($push_notify ? "Yes":"No"));
                        } elseif ($exclusive_delivery) {
                                $followup = true;
 
@@ -338,17 +301,11 @@ class Notifier
                                                foreach ($people as $person) {
                                                        if (substr($person,0,4) === 'cid:') {
                                                                $recipients[] = intval(substr($person,4));
-                                                       } else {
-                                                               $url_recipients[] = substr($person,4);
                                                        }
                                                }
                                        }
                                }
 
-                               if (count($url_recipients)) {
-                                       Logger::notice('Deliver', ['target' => $target_id, 'guid' => $target_item['guid'], 'recipients' => $url_recipients]);
-                               }
-
                                $recipients = array_unique(array_merge($recipients, $allow_people, $allow_circles));
                                $deny = array_unique(array_merge($deny_people, $deny_circles));
                                $recipients = array_diff($recipients, $deny);
@@ -368,39 +325,7 @@ class Notifier
                                }
                        }
 
-                       // If the thread parent is OStatus then do some magic to distribute the messages.
-                       // We have not only to look at the parent, since it could be a Friendica thread.
-                       if (($thr_parent && ($thr_parent['network'] == Protocol::OSTATUS)) || ($parent['network'] == Protocol::OSTATUS)) {
-                               $diaspora_delivery = false;
-
-                               Logger::info('Some parent is OStatus for ' . $target_item['guid'] . ' - Author: ' . $thr_parent['author-id'] . ' - Owner: ' . $thr_parent['owner-id']);
-
-                               // Send a salmon to the parent author
-                               $probed_contact = DBA::selectFirst('contact', ['url', 'notify'], ['id' => $thr_parent['author-id']]);
-                               if (DBA::isResult($probed_contact) && !empty($probed_contact['notify'])) {
-                                       Logger::notice('Notify parent author', ['url' => $probed_contact['url'], 'notify' => $probed_contact['notify']]);
-                                       $url_recipients[$probed_contact['notify']] = $probed_contact['notify'];
-                               }
-
-                               // Send a salmon to the parent owner
-                               $probed_contact = DBA::selectFirst('contact', ['url', 'notify'], ['id' => $thr_parent['owner-id']]);
-                               if (DBA::isResult($probed_contact) && !empty($probed_contact['notify'])) {
-                                       Logger::notice('Notify parent owner', ['url' => $probed_contact['url'], 'notify' => $probed_contact['notify']]);
-                                       $url_recipients[$probed_contact['notify']] = $probed_contact['notify'];
-                               }
-
-                               // Send a salmon notification to every person we mentioned in the post
-                               foreach (Tag::getByURIId($target_item['uri-id'], [Tag::MENTION, Tag::EXCLUSIVE_MENTION, Tag::IMPLICIT_MENTION]) as $tag) {
-                                       $probed_contact = Contact::getByURL($tag['url']);
-                                       if (!empty($probed_contact['notify'])) {
-                                               Logger::notice('Notify mentioned user', ['url' => $probed_contact['url'], 'notify' => $probed_contact['notify']]);
-                                               $url_recipients[$probed_contact['notify']] = $probed_contact['notify'];
-                                       }
-                               }
-
-                               // It only makes sense to distribute answers to OStatus messages to Friendica and OStatus - but not Diaspora
-                               $networks = [Protocol::DFRN];
-                       } elseif ($diaspora_delivery) {
+                       if ($diaspora_delivery) {
                                $networks = [Protocol::DFRN, Protocol::DIASPORA, Protocol::MAIL];
                                if (($parent['network'] == Protocol::DIASPORA) || ($thr_parent['network'] == Protocol::DIASPORA)) {
                                        Logger::info('Add AP contacts', ['target' => $target_id, 'guid' => $target_item['guid']]);
@@ -453,15 +378,11 @@ class Notifier
                        $conversants = array_merge($contacts, $participants);
 
                        $delivery_queue_count += self::delivery($cmd, $post_uriid, $sender_uid, $target_item, $thr_parent, $owner, $batch_delivery, true, $conversants, $ap_contacts, []);
-
-                       $push_notify = true;
                }
 
                $contacts = DBA::toArray($delivery_contacts_stmt);
                $delivery_queue_count += self::delivery($cmd, $post_uriid, $sender_uid, $target_item, $thr_parent, $owner, $batch_delivery, false, $contacts, $ap_contacts, $conversants);
 
-               $delivery_queue_count += self::deliverOStatus($target_id, $target_item, $owner, $url_recipients, $public_message, $push_notify);
-
                if (!empty($target_item)) {
                        Logger::info('Calling hooks for ' . $cmd . ' ' . $target_id);
 
@@ -612,50 +533,6 @@ class Notifier
                return $delivery_queue_count;
        }
 
-       /**
-        * Deliver the message via OStatus
-        *
-        * @param int $target_id
-        * @param array $target_item
-        * @param array $owner
-        * @param array $url_recipients
-        * @param bool $public_message
-        * @param bool $push_notify
-        *
-        * @return int Count of sent Salmon notifications
-        * @throws InternalServerErrorException
-        * @throws Exception
-        */
-       private static function deliverOStatus(int $target_id, array $target_item, array $owner, array $url_recipients, bool $public_message, bool $push_notify): int
-       {
-               $a = DI::app();
-               $delivery_queue_count = 0;
-
-               $url_recipients = array_filter($url_recipients);
-               // send salmon slaps to mentioned remote tags (@foo@example.com) in OStatus posts
-               // They are especially used for notifications to OStatus users that don't follow us.
-               if (count($url_recipients) && ($public_message || $push_notify) && !empty($target_item)) {
-                       $slap = OStatus::salmon($target_item, $owner);
-                       foreach ($url_recipients as $url) {
-                               Logger::info('Salmon delivery', ['item' => $target_id, 'to' => $url]);
-
-                               $delivery_queue_count++;
-                               Salmon::slapper($owner, $url, $slap);
-                               Item::incrementOutbound(Protocol::OSTATUS);
-                               Post\DeliveryData::incrementQueueDone($target_item['uri-id'], Post\DeliveryData::OSTATUS);
-                       }
-               }
-
-               // Notify PuSH subscribers (Used for OStatus distribution of regular posts)
-               if ($push_notify) {
-                       Logger::info('Activating internal PuSH', ['uid' => $owner['uid']]);
-
-                       // Handling the pubsubhubbub requests
-                       PushSubscriber::publishFeed($owner['uid'], $a->getQueueValue('priority'));
-               }
-               return $delivery_queue_count;
-       }
-
        /**
         * Checks if the current delivery shouldn't be transported to Diaspora.
         * This is done for posts from AP authors or posts that are comments to AP authors.
index bde45e39166c62449612034dcd2f725ffdda58c3..f720d25692732c4f7c2220c6c322af27cc3283a7 100644 (file)
@@ -59,15 +59,10 @@ class OnePoll
 
                $updated = DateTimeFormat::utcNow();
 
-               // Possibly switch the remote contact to AP
-               if ($success && ($contact['network'] === Protocol::OSTATUS)) {
-                       ActivityPub\Receiver::switchContact($contact['id'], $importer_uid, $contact['url']);
-               }
-
                $contact = DBA::selectFirst('contact', [], ['id' => $contact_id]);
 
                if ($success && ($importer_uid != 0) && in_array($contact['rel'], [Contact::SHARING, Contact::FRIEND])
-                       && in_array($contact['network'], [Protocol::FEED, Protocol::MAIL, Protocol::OSTATUS])) {
+                       && in_array($contact['network'], [Protocol::FEED, Protocol::MAIL])) {
                        $importer = User::getOwnerDataById($importer_uid);
                        if (empty($importer)) {
                                Logger::warning('No self contact for user', ['uid' => $importer_uid]);
@@ -113,7 +108,7 @@ class OnePoll
         */
        private static function updateContact(array $contact, array $fields)
        {
-               if (in_array($contact['network'], [Protocol::FEED, Protocol::MAIL, Protocol::OSTATUS])) {
+               if (in_array($contact['network'], [Protocol::FEED, Protocol::MAIL])) {
                        // Update the user's contact
                        Contact::update($fields, ['id' => $contact['id']]);
 
index 6fab4292c67a0877b28ee2f69ade6eed72e7497b..66b3cc39dab41cd4e14190b689e764a4c5144f8c 100644 (file)
@@ -27,7 +27,7 @@ class PollContacts
                        $abandon_days = 0;
                }
 
-               $condition = ['network' => [Protocol::FEED, Protocol::MAIL, Protocol::OSTATUS], 'self' => false, 'blocked' => false, 'archive' => false];
+               $condition = ['network' => [Protocol::FEED, Protocol::MAIL], 'self' => false, 'blocked' => false, 'archive' => false];
 
                if (!empty($abandon_days)) {
                        $condition = DBA::mergeConditions($condition,
diff --git a/src/Worker/PubSubPublish.php b/src/Worker/PubSubPublish.php
deleted file mode 100644 (file)
index 72b07c9..0000000
+++ /dev/null
@@ -1,86 +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\Worker;
-
-use Friendica\Core\Logger;
-use Friendica\Database\DBA;
-use Friendica\DI;
-use Friendica\Model\PushSubscriber;
-use Friendica\Network\HTTPClient\Client\HttpClientRequest;
-use Friendica\Protocol\OStatus;
-
-class PubSubPublish
-{
-       /**
-        * Publishes subscriber id
-        *
-        * @param int $pubsubpublish_id Push subscriber id
-        * @return void
-        */
-       public static function execute(int $pubsubpublish_id = 0)
-       {
-               if ($pubsubpublish_id == 0) {
-                       return;
-               }
-
-               self::publish($pubsubpublish_id);
-       }
-
-       /**
-        * Publishes push subscriber
-        *
-        * @param int $id Push subscriber id
-        * @return void
-        */
-       private static function publish(int $id)
-       {
-               $subscriber = DBA::selectFirst('push_subscriber', [], ['id' => $id]);
-               if (!DBA::isResult($subscriber)) {
-                       return;
-               }
-
-               /// @todo Check server status with GServer::check()
-               // Before this can be done we need a way to safely detect the server url.
-
-               Logger::info('Generate feed of user ' . $subscriber['nickname'] . ' to ' . $subscriber['callback_url'] . ' - last updated ' . $subscriber['last_update']);
-
-               $last_update = $subscriber['last_update'];
-               $params = OStatus::feed($subscriber['nickname'], $last_update);
-
-               if (!$params) {
-                       return;
-               }
-
-               $hmac_sig = hash_hmac('sha1', $params, $subscriber['secret']);
-
-               $headers = [
-                       'Content-type' => 'application/atom+xml',
-                       'Link' => sprintf(
-                               '<%s>;rel=hub,<%s>;rel=self',
-                               DI::baseUrl() . '/pubsubhubbub/' . $subscriber['nickname'],
-                               $subscriber['topic']
-                       ),
-                       'X-Hub-Signature' => 'sha1=' . $hmac_sig
-               ];
-
-               Logger::debug('POST', ['headers' => $headers, 'params' => $params]);
-
-               $postResult = DI::httpClient()->post($subscriber['callback_url'], $params, $headers, 0, HttpClientRequest::PUBSUB);
-               $ret = $postResult->getReturnCode();
-
-               if ($ret >= 200 && $ret <= 299) {
-                       Logger::info('Successfully pushed to ' . $subscriber['callback_url']);
-
-                       PushSubscriber::reset($subscriber['id'], $last_update);
-               } else {
-                       Logger::notice('Delivery error when pushing to ' . $subscriber['callback_url'] . ' HTTP: ' . $ret);
-
-                       PushSubscriber::delay($subscriber['id']);
-               }
-       }
-}
index 69dec5c507f5da922c57aa7bee9ca35087d1df7b..9d77d7b8271306089293ec31d51a8458a5dea3bc 100644 (file)
@@ -115,8 +115,6 @@ return [
                        "theme" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "user theme preference"],
                        "pubkey" => ["type" => "text", "comment" => "RSA public key 4096 bit"],
                        "prvkey" => ["type" => "text", "comment" => "RSA private key 4096 bit"],
-                       "spubkey" => ["type" => "text", "comment" => ""],
-                       "sprvkey" => ["type" => "text", "comment" => ""],
                        "verified" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "user is verified through email"],
                        "blocked" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 for user is blocked"],
                        "blockwall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Prohibit contacts to post to the profile page of the user"],
@@ -229,7 +227,6 @@ return [
                        "remote_self" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
                        "rel" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "The kind of the relation between the user and the contact"],
                        "protocol" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => "Protocol of the contact"],
-                       "subhub" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
                        "hub-verify" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""],
                        "rating" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => "Automatically detected feed poll frequency"],
                        "priority" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "Feed poll priority"],
@@ -1353,7 +1350,6 @@ return [
                        "dfrn" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Number of successful deliveries via DFRN"],
                        "legacy_dfrn" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Number of successful deliveries via legacy DFRN"],
                        "diaspora" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Number of successful deliveries via Diaspora"],
-                       "ostatus" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Number of successful deliveries via OStatus"],
                ],
                "indexes" => [
                        "PRIMARY" => ["uri-id"],
@@ -1785,26 +1781,6 @@ return [
                        "psid" => ["psid"],
                ]
        ],
-       "push_subscriber" => [
-               "comment" => "Used for OStatus: Contains feed subscribers",
-               "fields" => [
-                       "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
-                       "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id"],
-                       "callback_url" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""],
-                       "topic" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
-                       "nickname" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
-                       "push" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => "Retrial counter"],
-                       "last_update" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of last successful trial"],
-                       "next_try" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Next retrial date"],
-                       "renewed" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of last subscription renewal"],
-                       "secret" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
-               ],
-               "indexes" => [
-                       "PRIMARY" => ["id"],
-                       "next_try" => ["next_try"],
-                       "uid" => ["uid"]
-               ]
-       ],
        "register" => [
                "comment" => "registrations requiring admin approval",
                "fields" => [
@@ -1979,7 +1955,6 @@ return [
                        "remote_self" => ["type" => "tinyint unsigned", "comment" => "0 => No mirroring, 1-2 => Mirror as own post, 3 => Mirror as reshare"],
                        "fetch_further_information" => ["type" => "tinyint unsigned", "comment" => "0 => None, 1 => Fetch information, 3 => Fetch keywords, 2 => Fetch both"],
                        "ffi_keyword_denylist" => ["type" => "text", "comment" => ""],
-                       "subhub" => ["type" => "boolean", "comment" => ""],
                        "hub-verify" => ["type" => "varbinary(383)", "comment" => ""],
                        "protocol" => ["type" => "char(4)", "comment" => "Protocol of the contact"],
                        "rating" => ["type" => "tinyint", "comment" => "Automatically detected feed poll frequency"],
index 87f41b5896af693a79d023f4d5d7d576d654c8ca..f5b293189762b542a1afd5f308d86c2b66674637 100644 (file)
                        "poll" => ["contact", "poll"],
                        "confirm" => ["contact", "confirm"],
                        "poco" => ["contact", "poco"],
-                       "subhub" => ["contact", "subhub"],
                        "hub-verify" => ["contact", "hub-verify"],
                        "last-update" => ["contact", "last-update"],
                        "success_update" => ["contact", "success_update"],
                        "theme" => ["user", "theme"],
                        "upubkey" => ["user", "pubkey"],
                        "uprvkey" => ["user", "prvkey"],
-                       "sprvkey" => ["user", "sprvkey"],
-                       "spubkey" => ["user", "spubkey"],
                        "verified" => ["user", "verified"],
                        "blockwall" => ["user", "blockwall"],
                        "hidewall" => ["user", "hidewall"],
                        "readonly" => ["ucontact", "readonly"],
                        "blocked" => ["ucontact", "blocked"],
                        "block_reason" => ["ucontact", "block_reason"],
-                       "subhub" => ["ucontact", "subhub"],
                        "hub-verify" => ["ucontact", "hub-verify"],
                        "reason" => ["ucontact", "reason"],
                        "dfrn-notify" => ["contact", "notify"],
index 369753e616f5323c95e2a95cd99e37c104070002..f9680216e2cd5c48c4a046e50ff538bc8329853e 100644 (file)
@@ -412,7 +412,7 @@ return [
        '/credits'                  => [Module\Credits::class,          [R::GET]],
        '/delegation'               => [Module\User\Delegation::class,  [R::GET, R::POST]],
        '/dfrn_notify[/{nickname}]' => [Module\DFRN\Notify::class,      [        R::POST]],
-       '/dfrn_poll/{nickname}'     => [Module\DFRN\Poll::class,        [R::GET]],
+       '/dfrn_poll/{nickname}'     => [Module\Feed::class,            [R::GET]],
        '/dirfind'                  => [Module\Search\Directory::class, [R::GET]],
        '/directory'                => [Module\Directory::class,        [R::GET]],
 
@@ -510,7 +510,6 @@ return [
                '/users/deleted'                  => [Module\Moderation\Users\Deleted::class, [R::GET         ]],
                '/users/create'                   => [Module\Moderation\Users\Create::class,  [R::GET, R::POST]],
        ],
-       '/modexp/{nick}'      => [Module\PublicRSAKey::class,    [R::GET]],
        '/newmember'          => [Module\Welcome::class,         [R::GET]],
        '/nodeinfo/1.0'       => [Module\NodeInfo110::class,     [R::GET]],
        '/nodeinfo/2.0'       => [Module\NodeInfo120::class,     [R::GET]],
@@ -587,14 +586,8 @@ return [
        '/u/{nickname}'       => $profileRoutes,
        '/~{nickname}'        => $profileRoutes,
 
-       // OStatus stack modules
-       '/ostatus/repair'                => [Module\OStatus\Repair::class,           [R::GET         ]],
        '/ostatus/subscribe'             => [Module\OStatus\Subscribe::class,        [R::GET         ]],
        '/poco'                          => [Module\User\PortableContacts::class,    [R::GET         ]],
-       '/pubsub'                        => [Module\OStatus\PubSub::class,           [R::GET, R::POST]],
-       '/pubsub/{nickname}[/{cid:\d+}]' => [Module\OStatus\PubSub::class,           [R::GET, R::POST]],
-       '/pubsubhubbub[/{nickname}]'     => [Module\OStatus\PubSubHubBub::class,     [        R::POST]],
-       '/salmon[/{nickname}]'           => [Module\OStatus\Salmon::class,           [        R::POST]],
 
        '/search' => [
                '[/]'                  => [Module\Search\Index::class, [R::GET         ]],
index 5e1c1990140c4cebe1a16f20d2bc63252ae667fe..493c095809d80e47969d50fc490d1e29e2db7cee 100644 (file)
@@ -452,7 +452,7 @@ function pre_update_1364()
                return Update::FAILED;
        }
 
-       if (!DBA::e("DELETE FROM `push_subscriber` WHERE NOT `uid` IN (SELECT `uid` FROM `user`)")) {
+       if (DBStructure::existsTable('push_subscriber') && !DBA::e("DELETE FROM `push_subscriber` WHERE NOT `uid` IN (SELECT `uid` FROM `user`)")) {
                return Update::FAILED;
        }
 
index 6cfafcbcd23274227164b02558c6a19d81fe0747..7924546ce7872b5dd1e5c24053734e3fcc4be117 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: 2024.09-dev\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-08-30 05:35+0000\n"
+"POT-Creation-Date: 2024-09-02 05:44+0000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -45,30 +45,30 @@ msgid "Item not found."
 msgstr ""
 
 #: mod/item.php:449 mod/message.php:54 mod/message.php:100 mod/notes.php:33
-#: mod/photos.php:135 mod/photos.php:651 src/Model/Event.php:506
+#: mod/photos.php:135 mod/photos.php:627 src/Model/Event.php:506
 #: src/Module/Attach.php:41 src/Module/BaseApi.php:89
 #: src/Module/BaseNotifications.php:84 src/Module/BaseSettings.php:36
 #: src/Module/Calendar/Event/API.php:74 src/Module/Calendar/Event/Form.php:70
 #: src/Module/Calendar/Export.php:68 src/Module/Calendar/Show.php:68
 #: src/Module/Circle.php:27 src/Module/Circle.php:70
 #: src/Module/Contact/Advanced.php:46 src/Module/Contact/Follow.php:73
-#: src/Module/Contact/Follow.php:146 src/Module/Contact/MatchInterests.php:73
+#: src/Module/Contact/Follow.php:141 src/Module/Contact/MatchInterests.php:73
 #: src/Module/Contact/Suggestions.php:40 src/Module/Contact/Unfollow.php:52
 #: src/Module/Contact/Unfollow.php:66 src/Module/Contact/Unfollow.php:98
 #: src/Module/FollowConfirm.php:24 src/Module/FriendSuggest.php:43
 #: src/Module/Invite.php:28 src/Module/Invite.php:117
 #: src/Module/Notifications/Notification.php:62
 #: src/Module/Notifications/Notification.php:93
-#: src/Module/OStatus/Repair.php:46 src/Module/OStatus/Subscribe.php:54
-#: src/Module/Post/Edit.php:62 src/Module/Profile/Common.php:61
-#: src/Module/Profile/Contacts.php:64 src/Module/Profile/Photos.php:78
-#: src/Module/Profile/Schedule.php:25 src/Module/Profile/Schedule.php:42
-#: src/Module/Register.php:70 src/Module/Register.php:83
-#: src/Module/Register.php:199 src/Module/Register.php:238
-#: src/Module/Search/Directory.php:23 src/Module/Settings/Account.php:36
-#: src/Module/Settings/Account.php:377 src/Module/Settings/Channels.php:52
-#: src/Module/Settings/Channels.php:127 src/Module/Settings/Delegation.php:76
-#: src/Module/Settings/Display.php:76 src/Module/Settings/Display.php:183
+#: src/Module/OStatus/Subscribe.php:54 src/Module/Post/Edit.php:62
+#: src/Module/Profile/Common.php:61 src/Module/Profile/Contacts.php:64
+#: src/Module/Profile/Photos.php:78 src/Module/Profile/Schedule.php:25
+#: src/Module/Profile/Schedule.php:42 src/Module/Register.php:70
+#: src/Module/Register.php:83 src/Module/Register.php:199
+#: src/Module/Register.php:238 src/Module/Search/Directory.php:23
+#: src/Module/Settings/Account.php:36 src/Module/Settings/Account.php:377
+#: src/Module/Settings/Channels.php:52 src/Module/Settings/Channels.php:127
+#: src/Module/Settings/Delegation.php:76 src/Module/Settings/Display.php:76
+#: src/Module/Settings/Display.php:183
 #: src/Module/Settings/Profile/Photo/Crop.php:151
 #: src/Module/Settings/Profile/Photo/Index.php:96
 #: src/Module/Settings/RemoveMe.php:105 src/Module/Settings/UserExport.php:64
@@ -280,16 +280,16 @@ msgstr ""
 msgid "Insert web link"
 msgstr ""
 
-#: mod/message.php:188 mod/message.php:344 mod/photos.php:1279
+#: mod/message.php:188 mod/message.php:344 mod/photos.php:1255
 #: src/Content/Conversation.php:386 src/Content/Conversation.php:1562
 #: src/Module/Item/Compose.php:199 src/Module/Post/Edit.php:131
 #: src/Object/Post.php:604
 msgid "Please wait"
 msgstr ""
 
-#: mod/message.php:189 mod/message.php:343 mod/photos.php:682
-#: mod/photos.php:802 mod/photos.php:1079 mod/photos.php:1120
-#: mod/photos.php:1176 mod/photos.php:1256
+#: mod/message.php:189 mod/message.php:343 mod/photos.php:658
+#: mod/photos.php:778 mod/photos.php:1055 mod/photos.php:1096
+#: mod/photos.php:1152 mod/photos.php:1232
 #: src/Module/Calendar/Event/Form.php:236 src/Module/Contact/Advanced.php:118
 #: src/Module/Contact/Profile.php:370
 #: src/Module/Debug/ActivityPubConversion.php:132
@@ -375,10 +375,10 @@ msgstr ""
 msgid "Save"
 msgstr ""
 
-#: mod/photos.php:54 mod/photos.php:117 mod/photos.php:561
+#: mod/photos.php:54 mod/photos.php:117 mod/photos.php:537
 #: src/Model/Event.php:498 src/Model/Profile.php:213
 #: src/Module/Calendar/Export.php:60 src/Module/Calendar/Show.php:60
-#: src/Module/DFRN/Poll.php:29 src/Module/Feed.php:52 src/Module/HCard.php:37
+#: src/Module/Feed.php:52 src/Module/HCard.php:37
 #: src/Module/Profile/Common.php:48 src/Module/Profile/Common.php:57
 #: src/Module/Profile/Contacts.php:50 src/Module/Profile/Contacts.php:58
 #: src/Module/Profile/Conversations.php:77 src/Module/Profile/Media.php:42
@@ -397,7 +397,7 @@ msgstr ""
 msgid "Recent Photos"
 msgstr ""
 
-#: mod/photos.php:94 mod/photos.php:850 src/Module/Profile/Photos.php:364
+#: mod/photos.php:94 mod/photos.php:826 src/Module/Profile/Photos.php:364
 #: src/Module/Profile/Photos.php:384
 msgid "Upload New Photos"
 msgstr ""
@@ -427,61 +427,61 @@ msgstr ""
 msgid "Failed to delete the photo."
 msgstr ""
 
-#: mod/photos.php:528
+#: mod/photos.php:504
 msgid "a photo"
 msgstr ""
 
-#: mod/photos.php:528
+#: mod/photos.php:504
 #, php-format
 msgid "%1$s was tagged in %2$s by %3$s"
 msgstr ""
 
-#: mod/photos.php:565 src/Module/Conversation/Community.php:148
+#: mod/photos.php:541 src/Module/Conversation/Community.php:148
 #: src/Module/Directory.php:35 src/Module/Profile/Photos.php:279
 #: src/Module/Search/Index.php:51
 msgid "Public access denied."
 msgstr ""
 
-#: mod/photos.php:570
+#: mod/photos.php:546
 msgid "No photos selected"
 msgstr ""
 
-#: mod/photos.php:698
+#: mod/photos.php:674
 #, php-format
 msgid "The maximum accepted image size is %s"
 msgstr ""
 
-#: mod/photos.php:705
+#: mod/photos.php:681
 msgid "Upload Photos"
 msgstr ""
 
-#: mod/photos.php:709 mod/photos.php:798
+#: mod/photos.php:685 mod/photos.php:774
 msgid "New album name: "
 msgstr ""
 
-#: mod/photos.php:710
+#: mod/photos.php:686
 msgid "or select existing album:"
 msgstr ""
 
-#: mod/photos.php:711
+#: mod/photos.php:687
 msgid "Do not show a status post for this upload"
 msgstr ""
 
-#: mod/photos.php:714 mod/photos.php:1075 src/Content/Conversation.php:388
+#: mod/photos.php:690 mod/photos.php:1051 src/Content/Conversation.php:388
 #: src/Module/Calendar/Event/Form.php:239 src/Module/Post/Edit.php:169
 msgid "Permissions"
 msgstr ""
 
-#: mod/photos.php:779
+#: mod/photos.php:755
 msgid "Do you really want to delete this photo album and all its photos?"
 msgstr ""
 
-#: mod/photos.php:780 mod/photos.php:803
+#: mod/photos.php:756 mod/photos.php:779
 msgid "Delete Album"
 msgstr ""
 
-#: mod/photos.php:781 mod/photos.php:881 src/Content/Conversation.php:403
-#: src/Module/Contact/Follow.php:159 src/Module/Contact/Revoke.php:92
+#: mod/photos.php:757 mod/photos.php:857 src/Content/Conversation.php:403
+#: src/Module/Contact/Follow.php:154 src/Module/Contact/Revoke.php:92
 #: src/Module/Contact/Unfollow.php:112
 #: src/Module/Media/Attachment/Browser.php:63
 #: src/Module/Media/Photo/Browser.php:74 src/Module/Post/Edit.php:153
@@ -490,157 +490,157 @@ msgstr ""
 msgid "Cancel"
 msgstr ""
 
-#: mod/photos.php:807
+#: mod/photos.php:783
 msgid "Edit Album"
 msgstr ""
 
-#: mod/photos.php:808
+#: mod/photos.php:784
 msgid "Drop Album"
 msgstr ""
 
-#: mod/photos.php:812
+#: mod/photos.php:788
 msgid "Show Newest First"
 msgstr ""
 
-#: mod/photos.php:814
+#: mod/photos.php:790
 msgid "Show Oldest First"
 msgstr ""
 
-#: mod/photos.php:835 src/Module/Profile/Photos.php:332
+#: mod/photos.php:811 src/Module/Profile/Photos.php:332
 msgid "View Photo"
 msgstr ""
 
-#: mod/photos.php:867
+#: mod/photos.php:843
 msgid "Permission denied. Access to this item may be restricted."
 msgstr ""
 
-#: mod/photos.php:869
+#: mod/photos.php:845
 msgid "Photo not available"
 msgstr ""
 
-#: mod/photos.php:879
+#: mod/photos.php:855
 msgid "Do you really want to delete this photo?"
 msgstr ""
 
-#: mod/photos.php:880 mod/photos.php:1080
+#: mod/photos.php:856 mod/photos.php:1056
 msgid "Delete Photo"
 msgstr ""
 
-#: mod/photos.php:978
+#: mod/photos.php:954
 msgid "View photo"
 msgstr ""
 
-#: mod/photos.php:980
+#: mod/photos.php:956
 msgid "Edit photo"
 msgstr ""
 
-#: mod/photos.php:981
+#: mod/photos.php:957
 msgid "Delete photo"
 msgstr ""
 
-#: mod/photos.php:982
+#: mod/photos.php:958
 msgid "Use as profile photo"
 msgstr ""
 
-#: mod/photos.php:989
+#: mod/photos.php:965
 msgid "Private Photo"
 msgstr ""
 
-#: mod/photos.php:995
+#: mod/photos.php:971
 msgid "View Full Size"
 msgstr ""
 
-#: mod/photos.php:1048
+#: mod/photos.php:1024
 msgid "Tags: "
 msgstr ""
 
-#: mod/photos.php:1051
+#: mod/photos.php:1027
 msgid "[Select tags to remove]"
 msgstr ""
 
-#: mod/photos.php:1066
+#: mod/photos.php:1042
 msgid "New album name"
 msgstr ""
 
-#: mod/photos.php:1067
+#: mod/photos.php:1043
 msgid "Caption"
 msgstr ""
 
-#: mod/photos.php:1068
+#: mod/photos.php:1044
 msgid "Add a Tag"
 msgstr ""
 
-#: mod/photos.php:1068
+#: mod/photos.php:1044
 msgid "Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping"
 msgstr ""
 
-#: mod/photos.php:1069
+#: mod/photos.php:1045
 msgid "Do not rotate"
 msgstr ""
 
-#: mod/photos.php:1070
+#: mod/photos.php:1046
 msgid "Rotate CW (right)"
 msgstr ""
 
-#: mod/photos.php:1071
+#: mod/photos.php:1047
 msgid "Rotate CCW (left)"
 msgstr ""
 
-#: mod/photos.php:1117 mod/photos.php:1173 mod/photos.php:1253
-#: src/Module/Contact.php:611 src/Module/Item/Compose.php:181
+#: mod/photos.php:1093 mod/photos.php:1149 mod/photos.php:1229
+#: src/Module/Contact.php:600 src/Module/Item/Compose.php:181
 #: src/Object/Post.php:1142
 msgid "This is you"
 msgstr ""
 
-#: mod/photos.php:1119 mod/photos.php:1175 mod/photos.php:1255
+#: mod/photos.php:1095 mod/photos.php:1151 mod/photos.php:1231
 #: src/Module/Moderation/Reports.php:102 src/Object/Post.php:598
 #: src/Object/Post.php:1144
 msgid "Comment"
 msgstr ""
 
-#: mod/photos.php:1121 mod/photos.php:1177 mod/photos.php:1257
+#: mod/photos.php:1097 mod/photos.php:1153 mod/photos.php:1233
 #: src/Content/Conversation.php:400 src/Module/Calendar/Event/Form.php:234
 #: src/Module/Item/Compose.php:194 src/Module/Post/Edit.php:151
 #: src/Object/Post.php:1158
 msgid "Preview"
 msgstr ""
 
-#: mod/photos.php:1122 src/Content/Conversation.php:354
+#: mod/photos.php:1098 src/Content/Conversation.php:354
 #: src/Module/Post/Edit.php:116 src/Object/Post.php:1146
 msgid "Loading..."
 msgstr ""
 
-#: mod/photos.php:1214 src/Content/Conversation.php:1484
+#: mod/photos.php:1190 src/Content/Conversation.php:1484
 #: src/Object/Post.php:260
 msgid "Select"
 msgstr ""
 
-#: mod/photos.php:1215 src/Content/Conversation.php:1485
+#: mod/photos.php:1191 src/Content/Conversation.php:1485
 #: src/Module/Moderation/Users/Active.php:122
 #: src/Module/Moderation/Users/Blocked.php:122
 #: src/Module/Moderation/Users/Index.php:137
-#: src/Module/Settings/Connectors.php:240
+#: src/Module/Settings/Connectors.php:233
 #: src/Module/Settings/Server/Index.php:95
 msgid "Delete"
 msgstr ""
 
-#: mod/photos.php:1276 src/Object/Post.php:426
+#: mod/photos.php:1252 src/Object/Post.php:426
 msgid "Like"
 msgstr ""
 
-#: mod/photos.php:1277 src/Object/Post.php:426
+#: mod/photos.php:1253 src/Object/Post.php:426
 msgid "I like this (toggle)"
 msgstr ""
 
-#: mod/photos.php:1278 src/Object/Post.php:427
+#: mod/photos.php:1254 src/Object/Post.php:427
 msgid "Dislike"
 msgstr ""
 
-#: mod/photos.php:1280 src/Object/Post.php:427
+#: mod/photos.php:1256 src/Object/Post.php:427
 msgid "I don't like this (toggle)"
 msgstr ""
 
-#: mod/photos.php:1302
+#: mod/photos.php:1278
 msgid "Map"
 msgstr ""
 
@@ -772,19 +772,19 @@ msgid "All contacts"
 msgstr ""
 
 #: src/BaseModule.php:425 src/Content/Conversation/Factory/Channel.php:32
-#: src/Content/Widget.php:226 src/Core/ACL.php:181 src/Module/Contact.php:406
+#: src/Content/Widget.php:218 src/Core/ACL.php:181 src/Module/Contact.php:395
 #: src/Module/Privacy/PermissionTooltip.php:150
 #: src/Module/Privacy/PermissionTooltip.php:172
 #: src/Module/Settings/Channels.php:146
 msgid "Followers"
 msgstr ""
 
-#: src/BaseModule.php:430 src/Content/Widget.php:227 src/Module/Contact.php:409
+#: src/BaseModule.php:430 src/Content/Widget.php:219 src/Module/Contact.php:398
 #: src/Module/Settings/Channels.php:145
 msgid "Following"
 msgstr ""
 
-#: src/BaseModule.php:435 src/Content/Widget.php:228 src/Module/Contact.php:412
+#: src/BaseModule.php:435 src/Content/Widget.php:220 src/Module/Contact.php:401
 msgid "Mutual friends"
 msgstr ""
 
@@ -942,7 +942,7 @@ msgstr ""
 msgid "Enter user nickname: "
 msgstr ""
 
-#: src/Console/User.php:168 src/Model/User.php:833
+#: src/Console/User.php:168 src/Model/User.php:831
 #: src/Module/Api/Twitter/ContactEndpoint.php:60
 #: src/Module/Moderation/Users/Active.php:57
 #: src/Module/Moderation/Users/Blocked.php:57
@@ -1694,8 +1694,8 @@ msgstr ""
 msgid "Network Widgets"
 msgstr ""
 
-#: src/Content/Feature.php:115 src/Content/Widget.php:202
-#: src/Model/Circle.php:587 src/Module/Contact.php:392
+#: src/Content/Feature.php:115 src/Content/Widget.php:194
+#: src/Model/Circle.php:587 src/Module/Contact.php:381
 #: src/Module/Welcome.php:62
 msgid "Circles"
 msgstr ""
@@ -1706,7 +1706,7 @@ msgstr ""
 
 #: src/Content/Feature.php:116 src/Content/GroupManager.php:133
 #: src/Content/Nav.php:264 src/Content/Text/HTML.php:868
-#: src/Content/Widget.php:524 src/Model/User.php:1399
+#: src/Content/Widget.php:516 src/Model/User.php:1390
 msgid "Groups"
 msgstr ""
 
@@ -1714,7 +1714,7 @@ msgstr ""
 msgid "Display posts that have been distributed by the selected group."
 msgstr ""
 
-#: src/Content/Feature.php:117 src/Content/Widget.php:493
+#: src/Content/Feature.php:117 src/Content/Widget.php:485
 msgid "Archives"
 msgstr ""
 
@@ -1722,7 +1722,7 @@ msgstr ""
 msgid "Display an archive where posts can be selected by month and year."
 msgstr ""
 
-#: src/Content/Feature.php:118 src/Content/Widget.php:275
+#: src/Content/Feature.php:118 src/Content/Widget.php:267
 msgid "Protocols"
 msgstr ""
 
@@ -1730,7 +1730,7 @@ msgstr ""
 msgid "Display posts with the selected protocols."
 msgstr ""
 
-#: src/Content/Feature.php:119 src/Content/Widget.php:530
+#: src/Content/Feature.php:119 src/Content/Widget.php:522
 #: src/Module/Settings/Account.php:433
 msgid "Account Types"
 msgstr ""
@@ -1739,8 +1739,8 @@ msgstr ""
 msgid "Display posts done by accounts with the selected account type."
 msgstr ""
 
-#: src/Content/Feature.php:120 src/Content/Widget.php:579
-#: src/Module/Admin/Site.php:466 src/Module/BaseSettings.php:111
+#: src/Content/Feature.php:120 src/Content/Widget.php:571
+#: src/Module/Admin/Site.php:464 src/Module/BaseSettings.php:111
 #: src/Module/Settings/Channels.php:211 src/Module/Settings/Display.php:301
 msgid "Channels"
 msgstr ""
@@ -1757,7 +1757,7 @@ msgstr ""
 msgid "Display posts that contain subscribed hashtags."
 msgstr ""
 
-#: src/Content/Feature.php:122 src/Content/Widget.php:305
+#: src/Content/Feature.php:122 src/Content/Widget.php:297
 msgid "Saved Folders"
 msgstr ""
 
@@ -1817,12 +1817,12 @@ msgstr ""
 msgid "External link to group"
 msgstr ""
 
-#: src/Content/GroupManager.php:139 src/Content/Widget.php:499
+#: src/Content/GroupManager.php:139 src/Content/Widget.php:491
 msgid "show less"
 msgstr ""
 
-#: src/Content/GroupManager.php:140 src/Content/Widget.php:397
-#: src/Content/Widget.php:500
+#: src/Content/GroupManager.php:140 src/Content/Widget.php:389
+#: src/Content/Widget.php:492
 msgid "show more"
 msgstr ""
 
@@ -1830,7 +1830,7 @@ msgstr ""
 msgid "Create new group"
 msgstr ""
 
-#: src/Content/Item.php:317 src/Model/Item.php:3282
+#: src/Content/Item.php:317 src/Model/Item.php:3271
 msgid "event"
 msgstr ""
 
@@ -1838,7 +1838,7 @@ msgstr ""
 msgid "status"
 msgstr ""
 
-#: src/Content/Item.php:326 src/Model/Item.php:3284
+#: src/Content/Item.php:326 src/Model/Item.php:3273
 #: src/Module/Post/Tag/Add.php:109
 msgid "photo"
 msgstr ""
@@ -1852,35 +1852,35 @@ msgstr ""
 msgid "Follow Thread"
 msgstr ""
 
-#: src/Content/Item.php:415 src/Model/Contact.php:1253
+#: src/Content/Item.php:415 src/Model/Contact.php:1249
 msgid "View Status"
 msgstr ""
 
-#: src/Content/Item.php:416 src/Content/Item.php:439 src/Model/Contact.php:1188
-#: src/Model/Contact.php:1244 src/Model/Contact.php:1254
+#: src/Content/Item.php:416 src/Content/Item.php:439 src/Model/Contact.php:1184
+#: src/Model/Contact.php:1240 src/Model/Contact.php:1250
 #: src/Module/Directory.php:144 src/Module/Settings/Profile/Index.php:250
 msgid "View Profile"
 msgstr ""
 
-#: src/Content/Item.php:417 src/Model/Contact.php:1255
+#: src/Content/Item.php:417 src/Model/Contact.php:1251
 msgid "View Photos"
 msgstr ""
 
-#: src/Content/Item.php:418 src/Model/Contact.php:1222
+#: src/Content/Item.php:418 src/Model/Contact.php:1218
 #: src/Model/Profile.php:447
 msgid "Network Posts"
 msgstr ""
 
-#: src/Content/Item.php:419 src/Model/Contact.php:1246
-#: src/Model/Contact.php:1257
+#: src/Content/Item.php:419 src/Model/Contact.php:1242
+#: src/Model/Contact.php:1253
 msgid "View Contact"
 msgstr ""
 
-#: src/Content/Item.php:420 src/Model/Contact.php:1258
+#: src/Content/Item.php:420 src/Model/Contact.php:1254
 msgid "Send PM"
 msgstr ""
 
-#: src/Content/Item.php:421 src/Module/Contact.php:460
+#: src/Content/Item.php:421 src/Module/Contact.php:449
 #: src/Module/Contact/Profile.php:518
 #: src/Module/Moderation/Blocklist/Contact.php:102
 #: src/Module/Moderation/Users/Active.php:123
@@ -1888,7 +1888,7 @@ msgstr ""
 msgid "Block"
 msgstr ""
 
-#: src/Content/Item.php:422 src/Module/Contact.php:461
+#: src/Content/Item.php:422 src/Module/Contact.php:450
 #: src/Module/Contact/Profile.php:526
 #: src/Module/Notifications/Introductions.php:126
 #: src/Module/Notifications/Introductions.php:198
@@ -1896,7 +1896,7 @@ msgstr ""
 msgid "Ignore"
 msgstr ""
 
-#: src/Content/Item.php:423 src/Module/Contact.php:462
+#: src/Content/Item.php:423 src/Module/Contact.php:451
 #: src/Module/Contact/Profile.php:534
 msgid "Collapse"
 msgstr ""
@@ -1916,8 +1916,8 @@ msgid "Search Text"
 msgstr ""
 
 #: src/Content/Item.php:436 src/Content/Widget.php:66
-#: src/Model/Contact.php:1247 src/Model/Contact.php:1259
-#: src/Module/Contact/Follow.php:153 view/theme/vier/theme.php:183
+#: src/Model/Contact.php:1243 src/Model/Contact.php:1255
+#: src/Module/Contact/Follow.php:148 view/theme/vier/theme.php:183
 msgid "Connect/Follow"
 msgstr ""
 
@@ -1959,7 +1959,7 @@ msgid "Sign in"
 msgstr ""
 
 #: src/Content/Nav.php:215 src/Module/BaseProfile.php:43
-#: src/Module/Contact.php:504
+#: src/Module/Contact.php:493
 msgid "Conversations"
 msgstr ""
 
@@ -1968,7 +1968,7 @@ msgid "Conversations you started"
 msgstr ""
 
 #: src/Content/Nav.php:216 src/Module/BaseProfile.php:35
-#: src/Module/BaseSettings.php:84 src/Module/Contact.php:496
+#: src/Module/BaseSettings.php:84 src/Module/Contact.php:485
 #: src/Module/Contact/Profile.php:425 src/Module/Profile/Profile.php:256
 #: src/Module/Welcome.php:43 view/theme/frio/theme.php:221
 msgid "Profile"
@@ -1988,7 +1988,7 @@ msgid "Your photos"
 msgstr ""
 
 #: src/Content/Nav.php:218 src/Module/BaseProfile.php:59
-#: src/Module/BaseProfile.php:62 src/Module/Contact.php:520
+#: src/Module/BaseProfile.php:62 src/Module/Contact.php:509
 #: view/theme/frio/theme.php:226
 msgid "Media"
 msgstr ""
@@ -2074,8 +2074,8 @@ msgstr ""
 
 #: src/Content/Nav.php:260 src/Content/Nav.php:315
 #: src/Content/Text/HTML.php:864 src/Module/BaseProfile.php:113
-#: src/Module/BaseProfile.php:116 src/Module/Contact.php:418
-#: src/Module/Contact.php:528 view/theme/frio/theme.php:234
+#: src/Module/BaseProfile.php:116 src/Module/Contact.php:407
+#: src/Module/Contact.php:517 view/theme/frio/theme.php:234
 msgid "Contacts"
 msgstr ""
 
@@ -2143,7 +2143,7 @@ msgstr ""
 msgid "See all notifications"
 msgstr ""
 
-#: src/Content/Nav.php:301 src/Module/Settings/Connectors.php:240
+#: src/Content/Nav.php:301 src/Module/Settings/Connectors.php:233
 msgid "Mark as seen"
 msgstr ""
 
@@ -2235,38 +2235,38 @@ msgstr ""
 msgid "last"
 msgstr ""
 
-#: src/Content/Text/BBCode.php:690 src/Content/Text/BBCode.php:1866
-#: src/Content/Text/BBCode.php:1867
+#: src/Content/Text/BBCode.php:689 src/Content/Text/BBCode.php:1862
+#: src/Content/Text/BBCode.php:1863
 msgid "Image/photo"
 msgstr ""
 
-#: src/Content/Text/BBCode.php:908
+#: src/Content/Text/BBCode.php:907
 #, php-format
 msgid "<a href=\"%1$s\" target=\"_blank\" rel=\"noopener noreferrer\">%2$s</a> %3$s"
 msgstr ""
 
-#: src/Content/Text/BBCode.php:933 src/Model/Item.php:4038
-#: src/Model/Item.php:4044 src/Model/Item.php:4045
+#: src/Content/Text/BBCode.php:929 src/Model/Item.php:4027
+#: src/Model/Item.php:4033 src/Model/Item.php:4034
 msgid "Link to source"
 msgstr ""
 
-#: src/Content/Text/BBCode.php:1747 src/Content/Text/HTML.php:892
+#: src/Content/Text/BBCode.php:1743 src/Content/Text/HTML.php:892
 msgid "Click to open/close"
 msgstr ""
 
-#: src/Content/Text/BBCode.php:1802
+#: src/Content/Text/BBCode.php:1798
 msgid "$1 wrote:"
 msgstr ""
 
-#: src/Content/Text/BBCode.php:1876 src/Content/Text/BBCode.php:1877
+#: src/Content/Text/BBCode.php:1872 src/Content/Text/BBCode.php:1873
 msgid "Encrypted content"
 msgstr ""
 
-#: src/Content/Text/BBCode.php:2209
+#: src/Content/Text/BBCode.php:2205
 msgid "Invalid source protocol"
 msgstr ""
 
-#: src/Content/Text/BBCode.php:2228
+#: src/Content/Text/BBCode.php:2224
 msgid "Invalid link protocol"
 msgstr ""
 
@@ -2318,7 +2318,7 @@ msgstr ""
 msgid "Examples: Robert Morgenstein, Fishing"
 msgstr ""
 
-#: src/Content/Widget.php:68 src/Module/Contact.php:452
+#: src/Content/Widget.php:68 src/Module/Contact.php:441
 #: src/Module/Directory.php:83 view/theme/vier/theme.php:185
 msgid "Find"
 msgstr ""
@@ -2349,63 +2349,63 @@ msgstr ""
 msgid "Local Directory"
 msgstr ""
 
-#: src/Content/Widget.php:204
+#: src/Content/Widget.php:196
 msgid "Everyone"
 msgstr ""
 
-#: src/Content/Widget.php:229 src/Module/Contact.php:415
+#: src/Content/Widget.php:221 src/Module/Contact.php:404
 msgid "No relationship"
 msgstr ""
 
-#: src/Content/Widget.php:234
+#: src/Content/Widget.php:226
 msgid "Relationships"
 msgstr ""
 
-#: src/Content/Widget.php:236 src/Module/Circle.php:280
-#: src/Module/Contact.php:336
+#: src/Content/Widget.php:228 src/Module/Circle.php:280
+#: src/Module/Contact.php:325
 msgid "All Contacts"
 msgstr ""
 
-#: src/Content/Widget.php:277
+#: src/Content/Widget.php:269
 msgid "All Protocols"
 msgstr ""
 
-#: src/Content/Widget.php:307 src/Content/Widget.php:338
+#: src/Content/Widget.php:299 src/Content/Widget.php:330
 msgid "Everything"
 msgstr ""
 
-#: src/Content/Widget.php:336
+#: src/Content/Widget.php:328
 msgid "Categories"
 msgstr ""
 
-#: src/Content/Widget.php:393
+#: src/Content/Widget.php:385
 #, php-format
 msgid "%d contact in common"
 msgid_plural "%d contacts in common"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/Content/Widget.php:501
+#: src/Content/Widget.php:493
 msgid "On this date"
 msgstr ""
 
-#: src/Content/Widget.php:521
+#: src/Content/Widget.php:513
 msgid "Persons"
 msgstr ""
 
-#: src/Content/Widget.php:522
+#: src/Content/Widget.php:514
 msgid "Organisations"
 msgstr ""
 
-#: src/Content/Widget.php:523 src/Model/Contact.php:1751
+#: src/Content/Widget.php:515 src/Model/Contact.php:1747
 msgid "News"
 msgstr ""
 
-#: src/Content/Widget.php:525
+#: src/Content/Widget.php:517
 msgid "Relays"
 msgstr ""
 
-#: src/Content/Widget.php:532 src/Module/Moderation/BaseUsers.php:56
+#: src/Content/Widget.php:524 src/Module/Moderation/BaseUsers.php:56
 msgid "All"
 msgstr ""
 
@@ -2451,12 +2451,12 @@ msgstr[1] ""
 msgid "More Trending Tags"
 msgstr ""
 
-#: src/Content/Widget/VCard.php:91 src/Model/Contact.php:1216
+#: src/Content/Widget/VCard.php:91 src/Model/Contact.php:1212
 #: src/Model/Profile.php:441
 msgid "Post to group"
 msgstr ""
 
-#: src/Content/Widget/VCard.php:96 src/Model/Contact.php:1220
+#: src/Content/Widget/VCard.php:96 src/Model/Contact.php:1216
 #: src/Model/Profile.php:445 src/Module/Moderation/Item/Source.php:77
 msgid "Mention"
 msgstr ""
@@ -2484,13 +2484,13 @@ msgstr ""
 msgid "Network:"
 msgstr ""
 
-#: src/Content/Widget/VCard.php:115 src/Model/Contact.php:1248
-#: src/Model/Contact.php:1260 src/Model/Profile.php:458
+#: src/Content/Widget/VCard.php:115 src/Model/Contact.php:1244
+#: src/Model/Contact.php:1256 src/Model/Profile.php:458
 #: src/Module/Contact/Profile.php:470
 msgid "Unfollow"
 msgstr ""
 
-#: src/Content/Widget/VCard.php:121 src/Model/Contact.php:1218
+#: src/Content/Widget/VCard.php:121 src/Model/Contact.php:1214
 #: src/Model/Profile.php:443
 msgid "View group"
 msgstr ""
@@ -2834,7 +2834,7 @@ msgstr ""
 msgid "Could not connect to database."
 msgstr ""
 
-#: src/Core/L10n.php:430 src/Model/Item.php:2326
+#: src/Core/L10n.php:430 src/Model/Item.php:2315
 msgid "Undetermined"
 msgstr ""
 
@@ -3194,82 +3194,78 @@ msgstr ""
 msgid "Edit circles"
 msgstr ""
 
-#: src/Model/Contact.php:1267 src/Module/Moderation/Users/Pending.php:88
+#: src/Model/Contact.php:1263 src/Module/Moderation/Users/Pending.php:88
 #: src/Module/Notifications/Introductions.php:124
 #: src/Module/Notifications/Introductions.php:196
 msgid "Approve"
 msgstr ""
 
-#: src/Model/Contact.php:1747
+#: src/Model/Contact.php:1743
 msgid "Organisation"
 msgstr ""
 
-#: src/Model/Contact.php:1755
+#: src/Model/Contact.php:1751
 msgid "Group"
 msgstr ""
 
-#: src/Model/Contact.php:1759 src/Module/Moderation/BaseUsers.php:120
+#: src/Model/Contact.php:1755 src/Module/Moderation/BaseUsers.php:120
 msgid "Relay"
 msgstr ""
 
-#: src/Model/Contact.php:3095
+#: src/Model/Contact.php:3070
 msgid "Disallowed profile URL."
 msgstr ""
 
-#: src/Model/Contact.php:3100 src/Module/Friendica.php:86
+#: src/Model/Contact.php:3075 src/Module/Friendica.php:86
 msgid "Blocked domain"
 msgstr ""
 
-#: src/Model/Contact.php:3105
+#: src/Model/Contact.php:3080
 msgid "Connect URL missing."
 msgstr ""
 
-#: src/Model/Contact.php:3114
+#: src/Model/Contact.php:3089
 msgid "The contact could not be added. Please check the relevant network credentials in your Settings -> Social Networks page."
 msgstr ""
 
-#: src/Model/Contact.php:3132
+#: src/Model/Contact.php:3107
 #, php-format
 msgid "Expected network %s does not match actual network %s"
 msgstr ""
 
-#: src/Model/Contact.php:3149
+#: src/Model/Contact.php:3124
 msgid "This seems to be a relay account. They can't be followed by users."
 msgstr ""
 
-#: src/Model/Contact.php:3156
+#: src/Model/Contact.php:3131
 msgid "The profile address specified does not provide adequate information."
 msgstr ""
 
-#: src/Model/Contact.php:3158
+#: src/Model/Contact.php:3133
 msgid "No compatible communication protocols or feeds were discovered."
 msgstr ""
 
-#: src/Model/Contact.php:3161
+#: src/Model/Contact.php:3136
 msgid "An author or name was not found."
 msgstr ""
 
-#: src/Model/Contact.php:3164
+#: src/Model/Contact.php:3139
 msgid "No browser URL could be matched to this address."
 msgstr ""
 
-#: src/Model/Contact.php:3167
+#: src/Model/Contact.php:3142
 msgid "Unable to match @-style Identity Address with a known protocol or email contact."
 msgstr ""
 
-#: src/Model/Contact.php:3168
+#: src/Model/Contact.php:3143
 msgid "Use mailto: in front of address to force email check."
 msgstr ""
 
-#: src/Model/Contact.php:3174
-msgid "The profile address specified belongs to a network which has been disabled on this site."
-msgstr ""
-
-#: src/Model/Contact.php:3179
+#: src/Model/Contact.php:3149
 msgid "Limited profile. This person will be unable to receive direct/personal notifications from you."
 msgstr ""
 
-#: src/Model/Contact.php:3245
+#: src/Model/Contact.php:3208
 msgid "Unable to retrieve contact information."
 msgstr ""
 
@@ -3319,7 +3315,7 @@ msgstr ""
 msgid "No events to display"
 msgstr ""
 
-#: src/Model/Event.php:502 src/Module/DFRN/Poll.php:33 src/Module/Feed.php:56
+#: src/Model/Event.php:502 src/Module/Feed.php:56
 #: src/Module/Update/Profile.php:42
 msgid "Access to this profile has been restricted."
 msgstr ""
@@ -3374,90 +3370,90 @@ msgstr ""
 msgid "Happy Birthday %s"
 msgstr ""
 
-#: src/Model/Item.php:2333
+#: src/Model/Item.php:2322
 #, php-format
 msgid "%s (%s - %s): %s"
 msgstr ""
 
-#: src/Model/Item.php:2335
+#: src/Model/Item.php:2324
 #, php-format
 msgid "%s (%s): %s"
 msgstr ""
 
-#: src/Model/Item.php:2338
+#: src/Model/Item.php:2327
 #, php-format
 msgid "Detected languages in this post:\\n%s"
 msgstr ""
 
-#: src/Model/Item.php:3286
+#: src/Model/Item.php:3275
 msgid "activity"
 msgstr ""
 
-#: src/Model/Item.php:3288
+#: src/Model/Item.php:3277
 msgid "comment"
 msgstr ""
 
-#: src/Model/Item.php:3291 src/Module/Post/Tag/Add.php:109
+#: src/Model/Item.php:3280 src/Module/Post/Tag/Add.php:109
 msgid "post"
 msgstr ""
 
-#: src/Model/Item.php:3461
+#: src/Model/Item.php:3450
 #, php-format
 msgid "%s is blocked"
 msgstr ""
 
-#: src/Model/Item.php:3463
+#: src/Model/Item.php:3452
 #, php-format
 msgid "%s is ignored"
 msgstr ""
 
-#: src/Model/Item.php:3465
+#: src/Model/Item.php:3454
 #, php-format
 msgid "Content from %s is collapsed"
 msgstr ""
 
-#: src/Model/Item.php:3469
+#: src/Model/Item.php:3458
 msgid "Sensitive content"
 msgstr ""
 
-#: src/Model/Item.php:3938
+#: src/Model/Item.php:3927
 msgid "bytes"
 msgstr ""
 
-#: src/Model/Item.php:3969
+#: src/Model/Item.php:3958
 #, php-format
 msgid "%2$s (%3$d%%, %1$d vote)"
 msgid_plural "%2$s (%3$d%%, %1$d votes)"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/Model/Item.php:3971
+#: src/Model/Item.php:3960
 #, php-format
 msgid "%2$s (%1$d vote)"
 msgid_plural "%2$s (%1$d votes)"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/Model/Item.php:3976
+#: src/Model/Item.php:3965
 #, php-format
 msgid "%d voter. Poll end: %s"
 msgid_plural "%d voters. Poll end: %s"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/Model/Item.php:3978
+#: src/Model/Item.php:3967
 #, php-format
 msgid "%d voter."
 msgid_plural "%d voters."
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/Model/Item.php:3980
+#: src/Model/Item.php:3969
 #, php-format
 msgid "Poll end: %s"
 msgstr ""
 
-#: src/Model/Item.php:4021 src/Model/Item.php:4022
+#: src/Model/Item.php:4010 src/Model/Item.php:4011
 msgid "View on separate page"
 msgstr ""
 
@@ -3615,138 +3611,138 @@ msgstr ""
 msgid "Responsible account: %s"
 msgstr ""
 
-#: src/Model/User.php:219 src/Model/User.php:1312
+#: src/Model/User.php:217 src/Model/User.php:1310
 msgid "SERIOUS ERROR: Generation of security keys failed."
 msgstr ""
 
-#: src/Model/User.php:742 src/Model/User.php:775
+#: src/Model/User.php:740 src/Model/User.php:773
 msgid "Login failed"
 msgstr ""
 
-#: src/Model/User.php:807
+#: src/Model/User.php:805
 msgid "Not enough information to authenticate"
 msgstr ""
 
-#: src/Model/User.php:932
+#: src/Model/User.php:930
 msgid "Password can't be empty"
 msgstr ""
 
-#: src/Model/User.php:974
+#: src/Model/User.php:972
 msgid "Empty passwords are not allowed."
 msgstr ""
 
-#: src/Model/User.php:978
+#: src/Model/User.php:976
 msgid "The new password has been exposed in a public data dump, please choose another."
 msgstr ""
 
-#: src/Model/User.php:982
+#: src/Model/User.php:980
 msgid "The password length is limited to 72 characters."
 msgstr ""
 
-#: src/Model/User.php:986
+#: src/Model/User.php:984
 msgid "The password can't contain white spaces nor accentuated letters"
 msgstr ""
 
-#: src/Model/User.php:1195
+#: src/Model/User.php:1193
 msgid "Passwords do not match. Password unchanged."
 msgstr ""
 
-#: src/Model/User.php:1202
+#: src/Model/User.php:1200
 msgid "An invitation is required."
 msgstr ""
 
-#: src/Model/User.php:1206
+#: src/Model/User.php:1204
 msgid "Invitation could not be verified."
 msgstr ""
 
-#: src/Model/User.php:1214
+#: src/Model/User.php:1212
 msgid "Invalid OpenID url"
 msgstr ""
 
-#: src/Model/User.php:1227 src/Security/Authentication.php:214
+#: src/Model/User.php:1225 src/Security/Authentication.php:214
 msgid "We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID."
 msgstr ""
 
-#: src/Model/User.php:1227 src/Security/Authentication.php:214
+#: src/Model/User.php:1225 src/Security/Authentication.php:214
 msgid "The error message was:"
 msgstr ""
 
-#: src/Model/User.php:1233
+#: src/Model/User.php:1231
 msgid "Please enter the required information."
 msgstr ""
 
-#: src/Model/User.php:1247
+#: src/Model/User.php:1245
 #, php-format
 msgid "system.username_min_length (%s) and system.username_max_length (%s) are excluding each other, swapping values."
 msgstr ""
 
-#: src/Model/User.php:1254
+#: src/Model/User.php:1252
 #, php-format
 msgid "Username should be at least %s character."
 msgid_plural "Username should be at least %s characters."
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/Model/User.php:1258
+#: src/Model/User.php:1256
 #, php-format
 msgid "Username should be at most %s character."
 msgid_plural "Username should be at most %s characters."
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/Model/User.php:1266
+#: src/Model/User.php:1264
 msgid "That doesn't appear to be your full (First Last) name."
 msgstr ""
 
-#: src/Model/User.php:1271
+#: src/Model/User.php:1269
 msgid "Your email domain is not among those allowed on this site."
 msgstr ""
 
-#: src/Model/User.php:1275
+#: src/Model/User.php:1273
 msgid "Not a valid email address."
 msgstr ""
 
-#: src/Model/User.php:1278
+#: src/Model/User.php:1276
 msgid "The nickname was blocked from registration by the nodes admin."
 msgstr ""
 
-#: src/Model/User.php:1282 src/Model/User.php:1288
+#: src/Model/User.php:1280 src/Model/User.php:1286
 msgid "Cannot use that email."
 msgstr ""
 
-#: src/Model/User.php:1294
+#: src/Model/User.php:1292
 msgid "Your nickname can only contain a-z, 0-9 and _."
 msgstr ""
 
-#: src/Model/User.php:1302 src/Model/User.php:1359
+#: src/Model/User.php:1300 src/Model/User.php:1350
 msgid "Nickname is already registered. Please choose another."
 msgstr ""
 
-#: src/Model/User.php:1346 src/Model/User.php:1350
+#: src/Model/User.php:1337 src/Model/User.php:1341
 msgid "An error occurred during registration. Please try again."
 msgstr ""
 
-#: src/Model/User.php:1373
+#: src/Model/User.php:1364
 msgid "An error occurred creating your default profile. Please try again."
 msgstr ""
 
-#: src/Model/User.php:1380
+#: src/Model/User.php:1371
 msgid "An error occurred creating your self contact. Please try again."
 msgstr ""
 
-#: src/Model/User.php:1385
+#: src/Model/User.php:1376
 msgid "Friends"
 msgstr ""
 
-#: src/Model/User.php:1389
+#: src/Model/User.php:1380
 msgid "An error occurred creating your default contact circle. Please try again."
 msgstr ""
 
-#: src/Model/User.php:1437
+#: src/Model/User.php:1428
 msgid "Profile Photos"
 msgstr ""
 
-#: src/Model/User.php:1625
+#: src/Model/User.php:1616
 #, php-format
 msgid ""
 "\n"
@@ -3754,7 +3750,7 @@ msgid ""
 "\t\t\tthe administrator of %2$s has set up an account for you."
 msgstr ""
 
-#: src/Model/User.php:1628
+#: src/Model/User.php:1619
 #, php-format
 msgid ""
 "\n"
@@ -3785,12 +3781,12 @@ msgid ""
 "\t\tThank you and welcome to %4$s."
 msgstr ""
 
-#: src/Model/User.php:1660 src/Model/User.php:1766
+#: src/Model/User.php:1651 src/Model/User.php:1757
 #, php-format
 msgid "Registration details for %s"
 msgstr ""
 
-#: src/Model/User.php:1680
+#: src/Model/User.php:1671
 #, php-format
 msgid ""
 "\n"
@@ -3805,12 +3801,12 @@ msgid ""
 "\t\t"
 msgstr ""
 
-#: src/Model/User.php:1699
+#: src/Model/User.php:1690
 #, php-format
 msgid "Registration at %s"
 msgstr ""
 
-#: src/Model/User.php:1723
+#: src/Model/User.php:1714
 #, php-format
 msgid ""
 "\n"
@@ -3819,7 +3815,7 @@ msgid ""
 "\t\t\t"
 msgstr ""
 
-#: src/Model/User.php:1731
+#: src/Model/User.php:1722
 #, php-format
 msgid ""
 "\n"
@@ -3850,7 +3846,7 @@ msgid ""
 "\t\t\tThank you and welcome to %2$s."
 msgstr ""
 
-#: src/Model/User.php:1793
+#: src/Model/User.php:1784
 msgid "User with delegates can't be removed, please remove delegate users first"
 msgstr ""
 
@@ -3881,7 +3877,7 @@ msgstr ""
 #: src/Module/Admin/Addons/Details.php:97 src/Module/Admin/Addons/Index.php:59
 #: src/Module/Admin/Federation.php:206 src/Module/Admin/Logs/Settings.php:74
 #: src/Module/Admin/Logs/View.php:71 src/Module/Admin/Queue.php:59
-#: src/Module/Admin/Site.php:449 src/Module/Admin/Storage.php:124
+#: src/Module/Admin/Site.php:447 src/Module/Admin/Storage.php:124
 #: src/Module/Admin/Summary.php:182 src/Module/Admin/Themes/Details.php:82
 #: src/Module/Admin/Themes/Index.php:103 src/Module/Admin/Tos.php:63
 #: src/Module/Moderation/Users/Create.php:47
@@ -3919,11 +3915,11 @@ msgid "Addon %s failed to install."
 msgstr ""
 
 #: src/Module/Admin/Addons/Index.php:61 src/Module/Admin/Features.php:69
-#: src/Module/Admin/Logs/Settings.php:76 src/Module/Admin/Site.php:452
+#: src/Module/Admin/Logs/Settings.php:76 src/Module/Admin/Site.php:450
 #: src/Module/Admin/Themes/Index.php:105 src/Module/Admin/Tos.php:72
 #: src/Module/Settings/Account.php:549 src/Module/Settings/Addons.php:64
 #: src/Module/Settings/Connectors.php:149
-#: src/Module/Settings/Connectors.php:242
+#: src/Module/Settings/Connectors.php:235
 #: src/Module/Settings/Delegation.php:179 src/Module/Settings/Display.php:295
 #: src/Module/Settings/Features.php:61
 msgid "Save Settings"
@@ -4119,8 +4115,8 @@ msgid "Enable Debugging"
 msgstr ""
 
 #: src/Module/Admin/Logs/Settings.php:80 src/Module/Admin/Logs/Settings.php:81
-#: src/Module/Admin/Logs/Settings.php:82 src/Module/Admin/Site.php:472
-#: src/Module/Admin/Site.php:480
+#: src/Module/Admin/Logs/Settings.php:82 src/Module/Admin/Site.php:470
+#: src/Module/Admin/Site.php:478
 msgid "<strong>Read-only</strong> because it is set by an environment variable"
 msgstr ""
 
@@ -4269,257 +4265,257 @@ msgstr ""
 msgid "Priority"
 msgstr ""
 
-#: src/Module/Admin/Site.php:231
+#: src/Module/Admin/Site.php:230
 #, php-format
 msgid "%s is no valid input for maximum media size"
 msgstr ""
 
-#: src/Module/Admin/Site.php:236
+#: src/Module/Admin/Site.php:235
 #, php-format
 msgid "%s is no valid input for maximum image size"
 msgstr ""
 
-#: src/Module/Admin/Site.php:364 src/Module/Settings/Display.php:201
+#: src/Module/Admin/Site.php:362 src/Module/Settings/Display.php:201
 msgid "No special theme for mobile devices"
 msgstr ""
 
-#: src/Module/Admin/Site.php:381 src/Module/Settings/Display.php:211
+#: src/Module/Admin/Site.php:379 src/Module/Settings/Display.php:211
 #, php-format
 msgid "%s - (Experimental)"
 msgstr ""
 
-#: src/Module/Admin/Site.php:393
+#: src/Module/Admin/Site.php:391
 msgid "No community page"
 msgstr ""
 
-#: src/Module/Admin/Site.php:394
+#: src/Module/Admin/Site.php:392
 msgid "No community page for visitors"
 msgstr ""
 
-#: src/Module/Admin/Site.php:395
+#: src/Module/Admin/Site.php:393
 msgid "Public postings from users of this site"
 msgstr ""
 
-#: src/Module/Admin/Site.php:396
+#: src/Module/Admin/Site.php:394
 msgid "Public postings from the federated network"
 msgstr ""
 
-#: src/Module/Admin/Site.php:397
+#: src/Module/Admin/Site.php:395
 msgid "Public postings from local users and the federated network"
 msgstr ""
 
-#: src/Module/Admin/Site.php:403
+#: src/Module/Admin/Site.php:401
 msgid "Multi user instance"
 msgstr ""
 
-#: src/Module/Admin/Site.php:426
+#: src/Module/Admin/Site.php:424
 msgid "Closed"
 msgstr ""
 
-#: src/Module/Admin/Site.php:427
+#: src/Module/Admin/Site.php:425
 msgid "Requires approval"
 msgstr ""
 
-#: src/Module/Admin/Site.php:428
+#: src/Module/Admin/Site.php:426
 msgid "Open"
 msgstr ""
 
-#: src/Module/Admin/Site.php:432
+#: src/Module/Admin/Site.php:430
 msgid "Don't check"
 msgstr ""
 
-#: src/Module/Admin/Site.php:433
+#: src/Module/Admin/Site.php:431
 msgid "check the stable version"
 msgstr ""
 
-#: src/Module/Admin/Site.php:434
+#: src/Module/Admin/Site.php:432
 msgid "check the development version"
 msgstr ""
 
-#: src/Module/Admin/Site.php:438
+#: src/Module/Admin/Site.php:436
 msgid "none"
 msgstr ""
 
-#: src/Module/Admin/Site.php:439
+#: src/Module/Admin/Site.php:437
 msgid "Local contacts"
 msgstr ""
 
-#: src/Module/Admin/Site.php:440
+#: src/Module/Admin/Site.php:438
 msgid "Interactors"
 msgstr ""
 
-#: src/Module/Admin/Site.php:450 src/Module/BaseAdmin.php:76
+#: src/Module/Admin/Site.php:448 src/Module/BaseAdmin.php:76
 msgid "Site"
 msgstr ""
 
-#: src/Module/Admin/Site.php:451
+#: src/Module/Admin/Site.php:449
 msgid "General Information"
 msgstr ""
 
-#: src/Module/Admin/Site.php:453
+#: src/Module/Admin/Site.php:451
 msgid "Republish users to directory"
 msgstr ""
 
-#: src/Module/Admin/Site.php:454 src/Module/Register.php:145
+#: src/Module/Admin/Site.php:452 src/Module/Register.php:145
 msgid "Registration"
 msgstr ""
 
-#: src/Module/Admin/Site.php:455
+#: src/Module/Admin/Site.php:453
 msgid "File upload"
 msgstr ""
 
-#: src/Module/Admin/Site.php:456
+#: src/Module/Admin/Site.php:454
 msgid "Policies"
 msgstr ""
 
-#: src/Module/Admin/Site.php:457 src/Module/Calendar/Event/Form.php:238
-#: src/Module/Contact.php:539 src/Module/Profile/Profile.php:264
+#: src/Module/Admin/Site.php:455 src/Module/Calendar/Event/Form.php:238
+#: src/Module/Contact.php:528 src/Module/Profile/Profile.php:264
 msgid "Advanced"
 msgstr ""
 
-#: src/Module/Admin/Site.php:458
+#: src/Module/Admin/Site.php:456
 msgid "Auto Discovered Contact Directory"
 msgstr ""
 
-#: src/Module/Admin/Site.php:459
+#: src/Module/Admin/Site.php:457
 msgid "Performance"
 msgstr ""
 
-#: src/Module/Admin/Site.php:460
+#: src/Module/Admin/Site.php:458
 msgid "Worker"
 msgstr ""
 
-#: src/Module/Admin/Site.php:461
+#: src/Module/Admin/Site.php:459
 msgid "Message Relay"
 msgstr ""
 
-#: src/Module/Admin/Site.php:462
+#: src/Module/Admin/Site.php:460
 msgid "Use the command \"console relay\" in the command line to add or remove relays."
 msgstr ""
 
-#: src/Module/Admin/Site.php:463
+#: src/Module/Admin/Site.php:461
 msgid "The system is not subscribed to any relays at the moment."
 msgstr ""
 
-#: src/Module/Admin/Site.php:464
+#: src/Module/Admin/Site.php:462
 msgid "The system is currently subscribed to the following relays:"
 msgstr ""
 
-#: src/Module/Admin/Site.php:467
+#: src/Module/Admin/Site.php:465
 msgid "Relocate Node"
 msgstr ""
 
-#: src/Module/Admin/Site.php:468
+#: src/Module/Admin/Site.php:466
 msgid "Relocating your node enables you to change the DNS domain of this node and keep all the existing users and posts. This process takes a while and can only be started from the relocate console command like this:"
 msgstr ""
 
-#: src/Module/Admin/Site.php:469
+#: src/Module/Admin/Site.php:467
 msgid "(Friendica directory)# bin/console relocate https://newdomain.com"
 msgstr ""
 
-#: src/Module/Admin/Site.php:472
+#: src/Module/Admin/Site.php:470
 msgid "Site name"
 msgstr ""
 
-#: src/Module/Admin/Site.php:473
+#: src/Module/Admin/Site.php:471
 msgid "Sender Email"
 msgstr ""
 
-#: src/Module/Admin/Site.php:473
+#: src/Module/Admin/Site.php:471
 msgid "The email address your server shall use to send notification emails from."
 msgstr ""
 
-#: src/Module/Admin/Site.php:474
+#: src/Module/Admin/Site.php:472
 msgid "Name of the system actor"
 msgstr ""
 
-#: src/Module/Admin/Site.php:474
+#: src/Module/Admin/Site.php:472
 msgid "Name of the internal system account that is used to perform ActivityPub requests. This must be an unused username. If set, this can't be changed again."
 msgstr ""
 
-#: src/Module/Admin/Site.php:475
+#: src/Module/Admin/Site.php:473
 msgid "Banner/Logo"
 msgstr ""
 
-#: src/Module/Admin/Site.php:476
+#: src/Module/Admin/Site.php:474
 msgid "Email Banner/Logo"
 msgstr ""
 
-#: src/Module/Admin/Site.php:477
+#: src/Module/Admin/Site.php:475
 msgid "Shortcut icon"
 msgstr ""
 
-#: src/Module/Admin/Site.php:477
+#: src/Module/Admin/Site.php:475
 msgid "Link to an icon that will be used for browsers."
 msgstr ""
 
-#: src/Module/Admin/Site.php:478
+#: src/Module/Admin/Site.php:476
 msgid "Touch icon"
 msgstr ""
 
-#: src/Module/Admin/Site.php:478
+#: src/Module/Admin/Site.php:476
 msgid "Link to an icon that will be used for tablets and mobiles."
 msgstr ""
 
-#: src/Module/Admin/Site.php:479
+#: src/Module/Admin/Site.php:477
 msgid "Additional Info"
 msgstr ""
 
-#: src/Module/Admin/Site.php:479
+#: src/Module/Admin/Site.php:477
 #, php-format
 msgid "For public servers: you can add additional information here that will be listed at %s/servers."
 msgstr ""
 
-#: src/Module/Admin/Site.php:480
+#: src/Module/Admin/Site.php:478
 msgid "System language"
 msgstr ""
 
-#: src/Module/Admin/Site.php:481
+#: src/Module/Admin/Site.php:479
 msgid "System theme"
 msgstr ""
 
-#: src/Module/Admin/Site.php:481
+#: src/Module/Admin/Site.php:479
 #, php-format
 msgid "Default system theme - may be over-ridden by user profiles - <a href=\"%s\" id=\"cnftheme\">Change default theme settings</a>"
 msgstr ""
 
-#: src/Module/Admin/Site.php:482
+#: src/Module/Admin/Site.php:480
 msgid "Mobile system theme"
 msgstr ""
 
-#: src/Module/Admin/Site.php:482
+#: src/Module/Admin/Site.php:480
 msgid "Theme for mobile devices"
 msgstr ""
 
-#: src/Module/Admin/Site.php:483
+#: src/Module/Admin/Site.php:481
 msgid "Force SSL"
 msgstr ""
 
-#: src/Module/Admin/Site.php:483
+#: src/Module/Admin/Site.php:481
 msgid "Force all Non-SSL requests to SSL - Attention: on some systems it could lead to endless loops."
 msgstr ""
 
-#: src/Module/Admin/Site.php:484
+#: src/Module/Admin/Site.php:482
 msgid "Show help entry from navigation menu"
 msgstr ""
 
-#: src/Module/Admin/Site.php:484
+#: src/Module/Admin/Site.php:482
 msgid "Displays the menu entry for the Help pages from the navigation menu. It is always accessible by calling /help directly."
 msgstr ""
 
-#: src/Module/Admin/Site.php:485
+#: src/Module/Admin/Site.php:483
 msgid "Single user instance"
 msgstr ""
 
-#: src/Module/Admin/Site.php:485
+#: src/Module/Admin/Site.php:483
 msgid "Make this instance multi-user or single-user for the named user"
 msgstr ""
 
-#: src/Module/Admin/Site.php:487
+#: src/Module/Admin/Site.php:485
 msgid "Maximum image size"
 msgstr ""
 
-#: src/Module/Admin/Site.php:487
+#: src/Module/Admin/Site.php:485
 #, php-format
 msgid ""
 "Maximum size in bytes of uploaded images. Default is 0, which means no limits. You can put k, m, or g behind the desired value for KiB, MiB, GiB, respectively.\n"
@@ -4527,27 +4523,27 @@ msgid ""
 "\t\t\t\t\t\t\t\t\t\t\t\t\tCurrently <code>upload_max_filesize</code> is set to %s (%s byte)"
 msgstr ""
 
-#: src/Module/Admin/Site.php:491
+#: src/Module/Admin/Site.php:489
 msgid "Maximum image length"
 msgstr ""
 
-#: src/Module/Admin/Site.php:491
+#: src/Module/Admin/Site.php:489
 msgid "Maximum length in pixels of the longest side of uploaded images. Default is -1, which means no limits."
 msgstr ""
 
-#: src/Module/Admin/Site.php:492
+#: src/Module/Admin/Site.php:490
 msgid "JPEG image quality"
 msgstr ""
 
-#: src/Module/Admin/Site.php:492
+#: src/Module/Admin/Site.php:490
 msgid "Uploaded JPEGS will be saved at this quality setting [0-100]. Default is 100, which is full quality."
 msgstr ""
 
-#: src/Module/Admin/Site.php:493
+#: src/Module/Admin/Site.php:491
 msgid "Maximum media file size"
 msgstr ""
 
-#: src/Module/Admin/Site.php:493
+#: src/Module/Admin/Site.php:491
 #, php-format
 msgid ""
 "Maximum size in bytes of uploaded media files. Default is 0, which means no limits. You can put k, m, or g behind the desired value for KiB, MiB, GiB, respectively.\n"
@@ -4555,746 +4551,738 @@ msgid ""
 "\t\t\t\t\t\t\t\t\t\t\t\t\tCurrently <code>upload_max_filesize</code> is set to %s (%s byte)"
 msgstr ""
 
-#: src/Module/Admin/Site.php:498
+#: src/Module/Admin/Site.php:496
 msgid "Register policy"
 msgstr ""
 
-#: src/Module/Admin/Site.php:499
+#: src/Module/Admin/Site.php:497
 msgid "Maximum Users"
 msgstr ""
 
-#: src/Module/Admin/Site.php:499
+#: src/Module/Admin/Site.php:497
 msgid "If defined, the register policy is automatically closed when the given number of users is reached and reopens the registry when the number drops below the limit. It only works when the policy is set to open or close, but not when the policy is set to approval."
 msgstr ""
 
-#: src/Module/Admin/Site.php:500
+#: src/Module/Admin/Site.php:498
 msgid "Maximum Daily Registrations"
 msgstr ""
 
-#: src/Module/Admin/Site.php:500
+#: src/Module/Admin/Site.php:498
 msgid "If registration is permitted above, this sets the maximum number of new user registrations to accept per day.  If register is set to closed, this setting has no effect."
 msgstr ""
 
-#: src/Module/Admin/Site.php:501
+#: src/Module/Admin/Site.php:499
 msgid "Register text"
 msgstr ""
 
-#: src/Module/Admin/Site.php:501
+#: src/Module/Admin/Site.php:499
 msgid "Will be displayed prominently on the registration page. You can use BBCode here."
 msgstr ""
 
-#: src/Module/Admin/Site.php:502
+#: src/Module/Admin/Site.php:500
 msgid "Forbidden Nicknames"
 msgstr ""
 
-#: src/Module/Admin/Site.php:502
+#: src/Module/Admin/Site.php:500
 msgid "Comma separated list of nicknames that are forbidden from registration. Preset is a list of role names according RFC 2142."
 msgstr ""
 
-#: src/Module/Admin/Site.php:503
+#: src/Module/Admin/Site.php:501
 msgid "Accounts abandoned after x days"
 msgstr ""
 
-#: src/Module/Admin/Site.php:503
+#: src/Module/Admin/Site.php:501
 msgid "Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit."
 msgstr ""
 
-#: src/Module/Admin/Site.php:504
+#: src/Module/Admin/Site.php:502
 msgid "Allowed friend domains"
 msgstr ""
 
-#: src/Module/Admin/Site.php:504
+#: src/Module/Admin/Site.php:502
 msgid "Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains"
 msgstr ""
 
-#: src/Module/Admin/Site.php:505
+#: src/Module/Admin/Site.php:503
 msgid "Allowed email domains"
 msgstr ""
 
-#: src/Module/Admin/Site.php:505
+#: src/Module/Admin/Site.php:503
 msgid "Comma separated list of domains which are allowed in email addresses for registrations to this site. Wildcards are accepted. Empty to allow any domains"
 msgstr ""
 
-#: src/Module/Admin/Site.php:506
+#: src/Module/Admin/Site.php:504
 msgid "Disallowed email domains"
 msgstr ""
 
-#: src/Module/Admin/Site.php:506
+#: src/Module/Admin/Site.php:504
 msgid "Comma separated list of domains which are rejected as email addresses for registrations to this site. Wildcards are accepted."
 msgstr ""
 
-#: src/Module/Admin/Site.php:507
+#: src/Module/Admin/Site.php:505
 msgid "No OEmbed rich content"
 msgstr ""
 
-#: src/Module/Admin/Site.php:507
+#: src/Module/Admin/Site.php:505
 msgid "Don't show the rich content (e.g. embedded PDF), except from the domains listed below."
 msgstr ""
 
-#: src/Module/Admin/Site.php:508
+#: src/Module/Admin/Site.php:506
 msgid "Trusted third-party domains"
 msgstr ""
 
-#: src/Module/Admin/Site.php:508
+#: src/Module/Admin/Site.php:506
 msgid "Comma separated list of domains from which content is allowed to be embedded in posts like with OEmbed. All sub-domains of the listed domains are allowed as well."
 msgstr ""
 
-#: src/Module/Admin/Site.php:509
+#: src/Module/Admin/Site.php:507
 msgid "Block public"
 msgstr ""
 
-#: src/Module/Admin/Site.php:509
+#: src/Module/Admin/Site.php:507
 msgid "Check to block public access to all otherwise public personal pages on this site unless you are currently logged in."
 msgstr ""
 
-#: src/Module/Admin/Site.php:510
+#: src/Module/Admin/Site.php:508
 msgid "Force publish"
 msgstr ""
 
-#: src/Module/Admin/Site.php:510
+#: src/Module/Admin/Site.php:508
 msgid "Check to force all profiles on this site to be listed in the site directory."
 msgstr ""
 
-#: src/Module/Admin/Site.php:510
+#: src/Module/Admin/Site.php:508
 msgid "Enabling this may violate privacy laws like the GDPR"
 msgstr ""
 
-#: src/Module/Admin/Site.php:511
+#: src/Module/Admin/Site.php:509
 msgid "Global directory URL"
 msgstr ""
 
-#: src/Module/Admin/Site.php:511
+#: src/Module/Admin/Site.php:509
 msgid "URL to the global directory. If this is not set, the global directory is completely unavailable to the application."
 msgstr ""
 
-#: src/Module/Admin/Site.php:512
+#: src/Module/Admin/Site.php:510
 msgid "Private posts by default for new users"
 msgstr ""
 
-#: src/Module/Admin/Site.php:512
+#: src/Module/Admin/Site.php:510
 msgid "Set default post permissions for all new members to the default privacy circle rather than public."
 msgstr ""
 
-#: src/Module/Admin/Site.php:513
+#: src/Module/Admin/Site.php:511
 msgid "Don't include post content in email notifications"
 msgstr ""
 
-#: src/Module/Admin/Site.php:513
+#: src/Module/Admin/Site.php:511
 msgid "Don't include the content of a post/comment/private message/etc. in the email notifications that are sent out from this site, as a privacy measure."
 msgstr ""
 
-#: src/Module/Admin/Site.php:514
+#: src/Module/Admin/Site.php:512
 msgid "Disallow public access to addons listed in the apps menu."
 msgstr ""
 
-#: src/Module/Admin/Site.php:514
+#: src/Module/Admin/Site.php:512
 msgid "Checking this box will restrict addons listed in the apps menu to members only."
 msgstr ""
 
-#: src/Module/Admin/Site.php:515
+#: src/Module/Admin/Site.php:513
 msgid "Don't embed private images in posts"
 msgstr ""
 
-#: src/Module/Admin/Site.php:515
+#: src/Module/Admin/Site.php:513
 msgid "Don't replace locally-hosted private photos in posts with an embedded copy of the image. This means that contacts who receive posts containing private photos will have to authenticate and load each image, which may take a while."
 msgstr ""
 
-#: src/Module/Admin/Site.php:516
+#: src/Module/Admin/Site.php:514
 msgid "Explicit Content"
 msgstr ""
 
-#: src/Module/Admin/Site.php:516
+#: src/Module/Admin/Site.php:514
 msgid "Set this to announce that your node is used mostly for explicit content that might not be suited for minors. This information will be published in the node information and might be used, e.g. by the global directory, to filter your node from listings of nodes to join. Additionally a note about this will be shown at the user registration page."
 msgstr ""
 
-#: src/Module/Admin/Site.php:517
+#: src/Module/Admin/Site.php:515
 msgid "Only local search"
 msgstr ""
 
-#: src/Module/Admin/Site.php:517
+#: src/Module/Admin/Site.php:515
 msgid "Blocks search for users who are not logged in to prevent crawlers from blocking your system."
 msgstr ""
 
-#: src/Module/Admin/Site.php:518
+#: src/Module/Admin/Site.php:516
 msgid "Blocked tags for trending tags"
 msgstr ""
 
-#: src/Module/Admin/Site.php:518
+#: src/Module/Admin/Site.php:516
 msgid "Comma separated list of hashtags that shouldn't be displayed in the trending tags."
 msgstr ""
 
-#: src/Module/Admin/Site.php:519
+#: src/Module/Admin/Site.php:517
 msgid "Cache contact avatars"
 msgstr ""
 
-#: src/Module/Admin/Site.php:519
+#: src/Module/Admin/Site.php:517
 msgid "Locally store the avatar pictures of the contacts. This uses a lot of storage space but it increases the performance."
 msgstr ""
 
-#: src/Module/Admin/Site.php:520
+#: src/Module/Admin/Site.php:518
 msgid "Allow Users to set remote_self"
 msgstr ""
 
-#: src/Module/Admin/Site.php:520
+#: src/Module/Admin/Site.php:518
 msgid "With checking this, every user is allowed to mark every contact as a remote_self in the repair contact dialog. Setting this flag on a contact causes mirroring every posting of that contact in the users stream."
 msgstr ""
 
-#: src/Module/Admin/Site.php:521
+#: src/Module/Admin/Site.php:519
 msgid "Allow Users to set up relay channels"
 msgstr ""
 
-#: src/Module/Admin/Site.php:521
+#: src/Module/Admin/Site.php:519
 msgid "If enabled, it is possible to create relay users that are used to reshare content based on user defined channels."
 msgstr ""
 
-#: src/Module/Admin/Site.php:522
+#: src/Module/Admin/Site.php:520
 msgid "Adjust the feed poll frequency"
 msgstr ""
 
-#: src/Module/Admin/Site.php:522
+#: src/Module/Admin/Site.php:520
 msgid "Automatically detect and set the best feed poll frequency."
 msgstr ""
 
-#: src/Module/Admin/Site.php:523
+#: src/Module/Admin/Site.php:521
 msgid "Minimum poll interval"
 msgstr ""
 
-#: src/Module/Admin/Site.php:523
+#: src/Module/Admin/Site.php:521
 msgid "Minimal distance in minutes between two polls for mail and feed contacts. Reasonable values are between 1 and 59."
 msgstr ""
 
-#: src/Module/Admin/Site.php:524
+#: src/Module/Admin/Site.php:522
 msgid "Enable multiple registrations"
 msgstr ""
 
-#: src/Module/Admin/Site.php:524
+#: src/Module/Admin/Site.php:522
 msgid "Enable users to register additional accounts for use as pages."
 msgstr ""
 
-#: src/Module/Admin/Site.php:525
+#: src/Module/Admin/Site.php:523
 msgid "Enable OpenID"
 msgstr ""
 
-#: src/Module/Admin/Site.php:525
+#: src/Module/Admin/Site.php:523
 msgid "Enable OpenID support for registration and logins."
 msgstr ""
 
-#: src/Module/Admin/Site.php:526
+#: src/Module/Admin/Site.php:524
 msgid "Enable full name check"
 msgstr ""
 
-#: src/Module/Admin/Site.php:526
+#: src/Module/Admin/Site.php:524
 msgid "Prevents users from registering with a display name with fewer than two parts separated by spaces."
 msgstr ""
 
-#: src/Module/Admin/Site.php:527
+#: src/Module/Admin/Site.php:525
 msgid "Email administrators on new registration"
 msgstr ""
 
-#: src/Module/Admin/Site.php:527
+#: src/Module/Admin/Site.php:525
 msgid "If enabled and the system is set to an open registration, an email for each new registration is sent to the administrators."
 msgstr ""
 
-#: src/Module/Admin/Site.php:528
+#: src/Module/Admin/Site.php:526
 msgid "Community pages for visitors"
 msgstr ""
 
-#: src/Module/Admin/Site.php:528
+#: src/Module/Admin/Site.php:526
 msgid "Which community pages should be available for visitors. Local users always see both pages."
 msgstr ""
 
-#: src/Module/Admin/Site.php:529
+#: src/Module/Admin/Site.php:527
 msgid "Posts per user on community page"
 msgstr ""
 
-#: src/Module/Admin/Site.php:529
+#: src/Module/Admin/Site.php:527
 msgid "The maximum number of posts per user on the local community page. This is useful, when a single user floods the local community page."
 msgstr ""
 
-#: src/Module/Admin/Site.php:530
+#: src/Module/Admin/Site.php:528
 msgid "Posts per server on community page"
 msgstr ""
 
-#: src/Module/Admin/Site.php:530
+#: src/Module/Admin/Site.php:528
 msgid "The maximum number of posts per server on the global community page. This is useful, when posts from a single server flood the global community page."
 msgstr ""
 
-#: src/Module/Admin/Site.php:532
+#: src/Module/Admin/Site.php:530
 msgid "Enable Mail support"
 msgstr ""
 
-#: src/Module/Admin/Site.php:532
+#: src/Module/Admin/Site.php:530
 msgid "Enable built-in mail support to poll IMAP folders and to reply via mail."
 msgstr ""
 
-#: src/Module/Admin/Site.php:533
+#: src/Module/Admin/Site.php:531
 msgid "Mail support can't be enabled because the PHP IMAP module is not installed."
 msgstr ""
 
-#: src/Module/Admin/Site.php:534
-msgid "Enable OStatus support"
-msgstr ""
-
-#: src/Module/Admin/Site.php:534
-msgid "Enable built-in OStatus (StatusNet, GNU Social etc.) compatibility. All communications in OStatus are public."
-msgstr ""
-
-#: src/Module/Admin/Site.php:536
+#: src/Module/Admin/Site.php:533
 msgid "Diaspora support can't be enabled because Friendica was installed into a sub directory."
 msgstr ""
 
-#: src/Module/Admin/Site.php:537
+#: src/Module/Admin/Site.php:534
 msgid "Enable Diaspora support"
 msgstr ""
 
-#: src/Module/Admin/Site.php:537
+#: src/Module/Admin/Site.php:534
 msgid "Enable built-in Diaspora network compatibility for communicating with diaspora servers."
 msgstr ""
 
-#: src/Module/Admin/Site.php:538
+#: src/Module/Admin/Site.php:535
 msgid "Verify SSL"
 msgstr ""
 
-#: src/Module/Admin/Site.php:538
+#: src/Module/Admin/Site.php:535
 msgid "If you wish, you can turn on strict certificate checking. This will mean you cannot connect (at all) to self-signed SSL sites."
 msgstr ""
 
-#: src/Module/Admin/Site.php:539
+#: src/Module/Admin/Site.php:536
 msgid "Proxy user"
 msgstr ""
 
-#: src/Module/Admin/Site.php:539
+#: src/Module/Admin/Site.php:536
 msgid "User name for the proxy server."
 msgstr ""
 
-#: src/Module/Admin/Site.php:540
+#: src/Module/Admin/Site.php:537
 msgid "Proxy URL"
 msgstr ""
 
-#: src/Module/Admin/Site.php:540
+#: src/Module/Admin/Site.php:537
 msgid "If you want to use a proxy server that Friendica should use to connect to the network, put the URL of the proxy here."
 msgstr ""
 
-#: src/Module/Admin/Site.php:541
+#: src/Module/Admin/Site.php:538
 msgid "Network timeout"
 msgstr ""
 
-#: src/Module/Admin/Site.php:541
+#: src/Module/Admin/Site.php:538
 msgid "Value is in seconds. Set to 0 for unlimited (not recommended)."
 msgstr ""
 
-#: src/Module/Admin/Site.php:542
+#: src/Module/Admin/Site.php:539
 msgid "Maximum Load Average"
 msgstr ""
 
-#: src/Module/Admin/Site.php:542
+#: src/Module/Admin/Site.php:539
 #, php-format
 msgid "Maximum system load before delivery and poll processes are deferred - default %d."
 msgstr ""
 
-#: src/Module/Admin/Site.php:543
+#: src/Module/Admin/Site.php:540
 msgid "Minimal Memory"
 msgstr ""
 
-#: src/Module/Admin/Site.php:543
+#: src/Module/Admin/Site.php:540
 msgid "Minimal free memory in MB for the worker. Needs access to /proc/meminfo - default 0 (deactivated)."
 msgstr ""
 
-#: src/Module/Admin/Site.php:544
+#: src/Module/Admin/Site.php:541
 msgid "Periodically optimize tables"
 msgstr ""
 
-#: src/Module/Admin/Site.php:544
+#: src/Module/Admin/Site.php:541
 msgid "Periodically optimize tables like the cache and the workerqueue"
 msgstr ""
 
-#: src/Module/Admin/Site.php:546
+#: src/Module/Admin/Site.php:543
 msgid "Discover followers/followings from contacts"
 msgstr ""
 
-#: src/Module/Admin/Site.php:546
+#: src/Module/Admin/Site.php:543
 msgid "If enabled, contacts are checked for their followers and following contacts."
 msgstr ""
 
-#: src/Module/Admin/Site.php:547
+#: src/Module/Admin/Site.php:544
 msgid "None - deactivated"
 msgstr ""
 
-#: src/Module/Admin/Site.php:548
+#: src/Module/Admin/Site.php:545
 msgid "Local contacts - contacts of our local contacts are discovered for their followers/followings."
 msgstr ""
 
-#: src/Module/Admin/Site.php:549
+#: src/Module/Admin/Site.php:546
 msgid "Interactors - contacts of our local contacts and contacts who interacted on locally visible postings are discovered for their followers/followings."
 msgstr ""
 
-#: src/Module/Admin/Site.php:551
+#: src/Module/Admin/Site.php:548
 msgid "Only update contacts/servers with local data"
 msgstr ""
 
-#: src/Module/Admin/Site.php:551
+#: src/Module/Admin/Site.php:548
 msgid "If enabled, the system will only look for changes in contacts and servers that engaged on this system by either being in a contact list of a user or when posts or comments exists from the contact on this system."
 msgstr ""
 
-#: src/Module/Admin/Site.php:552
+#: src/Module/Admin/Site.php:549
 msgid "Synchronize the contacts with the directory server"
 msgstr ""
 
-#: src/Module/Admin/Site.php:552
+#: src/Module/Admin/Site.php:549
 msgid "if enabled, the system will check periodically for new contacts on the defined directory server."
 msgstr ""
 
-#: src/Module/Admin/Site.php:554
+#: src/Module/Admin/Site.php:551
 msgid "Discover contacts from other servers"
 msgstr ""
 
-#: src/Module/Admin/Site.php:554
+#: src/Module/Admin/Site.php:551
 msgid "Periodically query other servers for contacts and servers that they know of. The system queries Friendica, Mastodon and Hubzilla servers. Keep it deactivated on small machines to decrease the database size and load."
 msgstr ""
 
-#: src/Module/Admin/Site.php:555
+#: src/Module/Admin/Site.php:552
 msgid "Days between requery"
 msgstr ""
 
-#: src/Module/Admin/Site.php:555
+#: src/Module/Admin/Site.php:552
 msgid "Number of days after which a server is requeried for their contacts and servers it knows of. This is only used when the discovery is activated."
 msgstr ""
 
-#: src/Module/Admin/Site.php:556
+#: src/Module/Admin/Site.php:553
 msgid "Search the local directory"
 msgstr ""
 
-#: src/Module/Admin/Site.php:556
+#: src/Module/Admin/Site.php:553
 msgid "Search the local directory instead of the global directory. When searching locally, every search will be executed on the global directory in the background. This improves the search results when the search is repeated."
 msgstr ""
 
-#: src/Module/Admin/Site.php:558
+#: src/Module/Admin/Site.php:555
 msgid "Publish server information"
 msgstr ""
 
-#: src/Module/Admin/Site.php:558
+#: src/Module/Admin/Site.php:555
 msgid "If enabled, general server and usage data will be published. The data contains the name and version of the server, number of users with public profiles, number of posts and the activated protocols and connectors. See <a href=\"http://the-federation.info/\">the-federation.info</a> for details."
 msgstr ""
 
-#: src/Module/Admin/Site.php:560
+#: src/Module/Admin/Site.php:557
 msgid "Check upstream version"
 msgstr ""
 
-#: src/Module/Admin/Site.php:560
+#: src/Module/Admin/Site.php:557
 msgid "Enables checking for new Friendica versions at github. If there is a new version, you will be informed in the admin panel overview."
 msgstr ""
 
-#: src/Module/Admin/Site.php:561
+#: src/Module/Admin/Site.php:558
 msgid "Suppress Tags"
 msgstr ""
 
-#: src/Module/Admin/Site.php:561
+#: src/Module/Admin/Site.php:558
 msgid "Suppress showing a list of hashtags at the end of the posting."
 msgstr ""
 
-#: src/Module/Admin/Site.php:562
+#: src/Module/Admin/Site.php:559
 msgid "Clean database"
 msgstr ""
 
-#: src/Module/Admin/Site.php:562
+#: src/Module/Admin/Site.php:559
 msgid "Remove old remote items, orphaned database records and old content from some other helper tables."
 msgstr ""
 
-#: src/Module/Admin/Site.php:563
+#: src/Module/Admin/Site.php:560
 msgid "Lifespan of remote items"
 msgstr ""
 
-#: src/Module/Admin/Site.php:563
+#: src/Module/Admin/Site.php:560
 msgid "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."
 msgstr ""
 
-#: src/Module/Admin/Site.php:564
+#: src/Module/Admin/Site.php:561
 msgid "Lifespan of unclaimed items"
 msgstr ""
 
-#: src/Module/Admin/Site.php:564
+#: src/Module/Admin/Site.php:561
 msgid "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."
 msgstr ""
 
-#: src/Module/Admin/Site.php:565
+#: src/Module/Admin/Site.php:562
 msgid "Lifespan of raw conversation data"
 msgstr ""
 
-#: src/Module/Admin/Site.php:565
-msgid "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."
+#: src/Module/Admin/Site.php:562
+msgid "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."
 msgstr ""
 
-#: src/Module/Admin/Site.php:566
+#: src/Module/Admin/Site.php:563
 msgid "Maximum numbers of comments per post"
 msgstr ""
 
-#: src/Module/Admin/Site.php:566
+#: src/Module/Admin/Site.php:563
 msgid "How much comments should be shown for each post? Default value is 100."
 msgstr ""
 
-#: src/Module/Admin/Site.php:567
+#: src/Module/Admin/Site.php:564
 msgid "Maximum numbers of comments per post on the display page"
 msgstr ""
 
-#: src/Module/Admin/Site.php:567
+#: src/Module/Admin/Site.php:564
 msgid "How many comments should be shown on the single view for each post? Default value is 1000."
 msgstr ""
 
-#: src/Module/Admin/Site.php:568
+#: src/Module/Admin/Site.php:565
 msgid "Items per page"
 msgstr ""
 
-#: src/Module/Admin/Site.php:568
+#: src/Module/Admin/Site.php:565
 msgid "Number of items per page in stream pages (network, community, profile/contact statuses, search)."
 msgstr ""
 
-#: src/Module/Admin/Site.php:569
+#: src/Module/Admin/Site.php:566
 msgid "Items per page for mobile devices"
 msgstr ""
 
-#: src/Module/Admin/Site.php:569
+#: src/Module/Admin/Site.php:566
 msgid "Number of items per page in stream pages (network, community, profile/contact statuses, search) for mobile devices."
 msgstr ""
 
-#: src/Module/Admin/Site.php:570
+#: src/Module/Admin/Site.php:567
 msgid "Temp path"
 msgstr ""
 
-#: src/Module/Admin/Site.php:570
+#: src/Module/Admin/Site.php:567
 msgid "If you have a restricted system where the webserver can't access the system temp path, enter another path here."
 msgstr ""
 
-#: src/Module/Admin/Site.php:571
+#: src/Module/Admin/Site.php:568
 msgid "Only search in tags"
 msgstr ""
 
-#: src/Module/Admin/Site.php:571
+#: src/Module/Admin/Site.php:568
 msgid "On large systems the text search can slow down the system extremely."
 msgstr ""
 
-#: src/Module/Admin/Site.php:572
+#: src/Module/Admin/Site.php:569
 msgid "Limited search scope"
 msgstr ""
 
-#: src/Module/Admin/Site.php:572
+#: src/Module/Admin/Site.php:569
 msgid "If enabled, searches will only be performed in the data used for the channels and not in all posts."
 msgstr ""
 
-#: src/Module/Admin/Site.php:573
+#: src/Module/Admin/Site.php:570
 msgid "Maximum age of items in the search table"
 msgstr ""
 
-#: src/Module/Admin/Site.php:573
+#: src/Module/Admin/Site.php:570
 msgid "Maximum age of items in the search table in days. Lower values will increase the performance and reduce disk usage. 0 means no age restriction."
 msgstr ""
 
-#: src/Module/Admin/Site.php:574
+#: src/Module/Admin/Site.php:571
 msgid "Generate counts per contact circle when calculating network count"
 msgstr ""
 
-#: src/Module/Admin/Site.php:574
+#: src/Module/Admin/Site.php:571
 msgid "On systems with users that heavily use contact circles the query can be very expensive."
 msgstr ""
 
-#: src/Module/Admin/Site.php:575
+#: src/Module/Admin/Site.php:572
 msgid "Process \"view\" activities"
 msgstr ""
 
-#: src/Module/Admin/Site.php:575
+#: src/Module/Admin/Site.php:572
 msgid "\"view\" activities are mostly geberated by Peertube systems. Per default they are not processed for performance reasons. Only activate this option on performant system."
 msgstr ""
 
-#: src/Module/Admin/Site.php:576
+#: src/Module/Admin/Site.php:573
 msgid "Days, after which a contact is archived"
 msgstr ""
 
-#: src/Module/Admin/Site.php:576
+#: src/Module/Admin/Site.php:573
 msgid "Number of days that we try to deliver content or to update the contact data before we archive a contact."
 msgstr ""
 
-#: src/Module/Admin/Site.php:578
+#: src/Module/Admin/Site.php:575
 msgid "Maximum number of parallel workers"
 msgstr ""
 
-#: src/Module/Admin/Site.php:578
+#: src/Module/Admin/Site.php:575
 #, php-format
 msgid "On shared hosters set this to %d. On larger systems, values of %d are great. Default value is %d."
 msgstr ""
 
-#: src/Module/Admin/Site.php:579
+#: src/Module/Admin/Site.php:576
 msgid "Maximum load for workers"
 msgstr ""
 
-#: src/Module/Admin/Site.php:579
+#: src/Module/Admin/Site.php:576
 msgid "Maximum load that causes a cooldown before each worker function call."
 msgstr ""
 
-#: src/Module/Admin/Site.php:580
+#: src/Module/Admin/Site.php:577
 msgid "Enable fastlane"
 msgstr ""
 
-#: src/Module/Admin/Site.php:580
+#: src/Module/Admin/Site.php:577
 msgid "When enabed, the fastlane mechanism starts an additional worker if processes with higher priority are blocked by processes of lower priority."
 msgstr ""
 
-#: src/Module/Admin/Site.php:581
+#: src/Module/Admin/Site.php:578
 msgid "Decoupled receiver"
 msgstr ""
 
-#: src/Module/Admin/Site.php:581
+#: src/Module/Admin/Site.php:578
 msgid "Decouple incoming ActivityPub posts by processing them in the background via a worker process. Only enable this on fast systems."
 msgstr ""
 
-#: src/Module/Admin/Site.php:582
+#: src/Module/Admin/Site.php:579
 msgid "Cron interval"
 msgstr ""
 
-#: src/Module/Admin/Site.php:582
+#: src/Module/Admin/Site.php:579
 msgid "Minimal period in minutes between two calls of the \"Cron\" worker job."
 msgstr ""
 
-#: src/Module/Admin/Site.php:583
+#: src/Module/Admin/Site.php:580
 msgid "Worker defer limit"
 msgstr ""
 
-#: src/Module/Admin/Site.php:583
+#: src/Module/Admin/Site.php:580
 msgid "Per default the systems tries delivering for 15 times before dropping it."
 msgstr ""
 
-#: src/Module/Admin/Site.php:584
+#: src/Module/Admin/Site.php:581
 msgid "Worker fetch limit"
 msgstr ""
 
-#: src/Module/Admin/Site.php:584
+#: src/Module/Admin/Site.php:581
 msgid "Number of worker tasks that are fetched in a single query. Higher values should increase the performance, too high values will mostly likely decrease it. Only change it, when you know how to measure the performance of your system."
 msgstr ""
 
-#: src/Module/Admin/Site.php:586
+#: src/Module/Admin/Site.php:583
 msgid "Direct relay transfer"
 msgstr ""
 
-#: src/Module/Admin/Site.php:586
+#: src/Module/Admin/Site.php:583
 msgid "Enables the direct transfer to other servers without using the relay servers"
 msgstr ""
 
-#: src/Module/Admin/Site.php:587
+#: src/Module/Admin/Site.php:584
 msgid "Relay scope"
 msgstr ""
 
-#: src/Module/Admin/Site.php:587
+#: src/Module/Admin/Site.php:584
 msgid "Can be \"all\" or \"tags\". \"all\" means that every public post should be received. \"tags\" means that only posts with selected tags should be received."
 msgstr ""
 
-#: src/Module/Admin/Site.php:587 src/Module/Contact/Profile.php:314
+#: src/Module/Admin/Site.php:584 src/Module/Contact/Profile.php:314
 #: src/Module/Settings/TwoFactor/Index.php:132
 msgid "Disabled"
 msgstr ""
 
-#: src/Module/Admin/Site.php:587
+#: src/Module/Admin/Site.php:584
 msgid "all"
 msgstr ""
 
-#: src/Module/Admin/Site.php:587
+#: src/Module/Admin/Site.php:584
 msgid "tags"
 msgstr ""
 
-#: src/Module/Admin/Site.php:588
+#: src/Module/Admin/Site.php:585
 msgid "Server tags"
 msgstr ""
 
-#: src/Module/Admin/Site.php:588
+#: src/Module/Admin/Site.php:585
 msgid "Comma separated list of tags for the \"tags\" subscription."
 msgstr ""
 
-#: src/Module/Admin/Site.php:589
+#: src/Module/Admin/Site.php:586
 msgid "Deny Server tags"
 msgstr ""
 
-#: src/Module/Admin/Site.php:589
+#: src/Module/Admin/Site.php:586
 msgid "Comma separated list of tags that are rejected."
 msgstr ""
 
-#: src/Module/Admin/Site.php:590
+#: src/Module/Admin/Site.php:587
 msgid "Maximum amount of tags"
 msgstr ""
 
-#: src/Module/Admin/Site.php:590
+#: src/Module/Admin/Site.php:587
 msgid "Maximum amount of tags in a post before it is rejected as spam. The post has to contain at least one link. Posts from subscribed accounts will not be rejected."
 msgstr ""
 
-#: src/Module/Admin/Site.php:591
+#: src/Module/Admin/Site.php:588
 msgid "Allow user tags"
 msgstr ""
 
-#: src/Module/Admin/Site.php:591
+#: src/Module/Admin/Site.php:588
 msgid "If enabled, the tags from the saved searches will used for the \"tags\" subscription in addition to the \"relay_server_tags\"."
 msgstr ""
 
-#: src/Module/Admin/Site.php:592
+#: src/Module/Admin/Site.php:589
 msgid "Deny undetected languages"
 msgstr ""
 
-#: src/Module/Admin/Site.php:592
+#: src/Module/Admin/Site.php:589
 msgid "If enabled, posts with undetected languages will be rejected."
 msgstr ""
 
-#: src/Module/Admin/Site.php:593
+#: src/Module/Admin/Site.php:590
 msgid "Language Quality"
 msgstr ""
 
-#: src/Module/Admin/Site.php:593
+#: src/Module/Admin/Site.php:590
 msgid "The minimum language quality that is required to accept the post."
 msgstr ""
 
-#: src/Module/Admin/Site.php:594
+#: src/Module/Admin/Site.php:591
 msgid "Number of languages for the language detection"
 msgstr ""
 
-#: src/Module/Admin/Site.php:594
+#: src/Module/Admin/Site.php:591
 msgid "The system detects a list of languages per post. Only if the desired languages are in the list, the message will be accepted. The higher the number, the more posts will be falsely detected."
 msgstr ""
 
-#: src/Module/Admin/Site.php:596
+#: src/Module/Admin/Site.php:593
 msgid "Maximum age of channel"
 msgstr ""
 
-#: src/Module/Admin/Site.php:596
+#: src/Module/Admin/Site.php:593
 msgid "This defines the maximum age in hours of items that should be displayed in channels. This affects the channel performance."
 msgstr ""
 
-#: src/Module/Admin/Site.php:597
+#: src/Module/Admin/Site.php:594
 msgid "Maximum number of channel posts"
 msgstr ""
 
-#: src/Module/Admin/Site.php:597
+#: src/Module/Admin/Site.php:594
 msgid "For performance reasons, the channels use a dedicated table to store content. The higher the value the slower the channels."
 msgstr ""
 
-#: src/Module/Admin/Site.php:598
+#: src/Module/Admin/Site.php:595
 msgid "Interaction score days"
 msgstr ""
 
-#: src/Module/Admin/Site.php:598
+#: src/Module/Admin/Site.php:595
 msgid "Number of days that are used to calculate the interaction score."
 msgstr ""
 
-#: src/Module/Admin/Site.php:599
+#: src/Module/Admin/Site.php:596
 msgid "Maximum number of posts per author"
 msgstr ""
 
-#: src/Module/Admin/Site.php:599
+#: src/Module/Admin/Site.php:596
 msgid "Maximum number of posts per page by author if the contact frequency is set to \"Display only few posts\". If there are more posts, then the post with the most interactions will be displayed."
 msgstr ""
 
-#: src/Module/Admin/Site.php:600
+#: src/Module/Admin/Site.php:597
 msgid "Sharer interaction days"
 msgstr ""
 
-#: src/Module/Admin/Site.php:600
+#: src/Module/Admin/Site.php:597
 msgid "Number of days of the last interaction that are used to define which sharers are used for the \"sharers of sharers\" channel."
 msgstr ""
 
-#: src/Module/Admin/Site.php:603
+#: src/Module/Admin/Site.php:600
 msgid "Start Relocation"
 msgstr ""
 
@@ -5713,7 +5701,7 @@ msgstr ""
 msgid "Item Source"
 msgstr ""
 
-#: src/Module/BaseProfile.php:38 src/Module/Contact.php:499
+#: src/Module/BaseProfile.php:38 src/Module/Contact.php:488
 msgid "Profile Details"
 msgstr ""
 
@@ -5771,7 +5759,7 @@ msgstr ""
 msgid "Display"
 msgstr ""
 
-#: src/Module/BaseSettings.php:118 src/Module/Settings/Connectors.php:199
+#: src/Module/BaseSettings.php:118 src/Module/Settings/Connectors.php:195
 msgid "Social Networks"
 msgstr ""
 
@@ -6024,142 +6012,142 @@ msgid_plural "%d contacts edited."
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/Module/Contact.php:339
+#: src/Module/Contact.php:328
 msgid "Show all contacts"
 msgstr ""
 
-#: src/Module/Contact.php:344 src/Module/Contact.php:423
+#: src/Module/Contact.php:333 src/Module/Contact.php:412
 #: src/Module/Moderation/BaseUsers.php:72
 msgid "Pending"
 msgstr ""
 
-#: src/Module/Contact.php:347
+#: src/Module/Contact.php:336
 msgid "Only show pending contacts"
 msgstr ""
 
-#: src/Module/Contact.php:352 src/Module/Contact.php:426
+#: src/Module/Contact.php:341 src/Module/Contact.php:415
 #: src/Module/Moderation/BaseUsers.php:80
 msgid "Blocked"
 msgstr ""
 
-#: src/Module/Contact.php:355
+#: src/Module/Contact.php:344
 msgid "Only show blocked contacts"
 msgstr ""
 
-#: src/Module/Contact.php:360 src/Module/Contact.php:432
+#: src/Module/Contact.php:349 src/Module/Contact.php:421
 #: src/Module/Settings/Server/Index.php:93 src/Object/Post.php:385
 msgid "Ignored"
 msgstr ""
 
-#: src/Module/Contact.php:363
+#: src/Module/Contact.php:352
 msgid "Only show ignored contacts"
 msgstr ""
 
-#: src/Module/Contact.php:368 src/Module/Contact.php:435
+#: src/Module/Contact.php:357 src/Module/Contact.php:424
 msgid "Collapsed"
 msgstr ""
 
-#: src/Module/Contact.php:371
+#: src/Module/Contact.php:360
 msgid "Only show collapsed contacts"
 msgstr ""
 
-#: src/Module/Contact.php:376 src/Module/Contact.php:438
+#: src/Module/Contact.php:365 src/Module/Contact.php:427
 msgid "Archived"
 msgstr ""
 
-#: src/Module/Contact.php:379
+#: src/Module/Contact.php:368
 msgid "Only show archived contacts"
 msgstr ""
 
-#: src/Module/Contact.php:384 src/Module/Contact.php:429
+#: src/Module/Contact.php:373 src/Module/Contact.php:418
 msgid "Hidden"
 msgstr ""
 
-#: src/Module/Contact.php:387
+#: src/Module/Contact.php:376
 msgid "Only show hidden contacts"
 msgstr ""
 
-#: src/Module/Contact.php:395
+#: src/Module/Contact.php:384
 msgid "Organize your contact circles"
 msgstr ""
 
-#: src/Module/Contact.php:450
+#: src/Module/Contact.php:439
 msgid "Search your contacts"
 msgstr ""
 
-#: src/Module/Contact.php:451 src/Module/Search/Index.php:193
+#: src/Module/Contact.php:440 src/Module/Search/Index.php:193
 #, php-format
 msgid "Results for: %s"
 msgstr ""
 
-#: src/Module/Contact.php:459
+#: src/Module/Contact.php:448
 msgid "Update"
 msgstr ""
 
-#: src/Module/Contact.php:460 src/Module/Contact/Profile.php:518
+#: src/Module/Contact.php:449 src/Module/Contact/Profile.php:518
 #: src/Module/Moderation/Blocklist/Contact.php:103
 #: src/Module/Moderation/Users/Blocked.php:124
 #: src/Module/Moderation/Users/Index.php:140
 msgid "Unblock"
 msgstr ""
 
-#: src/Module/Contact.php:461 src/Module/Contact/Profile.php:526
+#: src/Module/Contact.php:450 src/Module/Contact/Profile.php:526
 msgid "Unignore"
 msgstr ""
 
-#: src/Module/Contact.php:462 src/Module/Contact/Profile.php:534
+#: src/Module/Contact.php:451 src/Module/Contact/Profile.php:534
 msgid "Uncollapse"
 msgstr ""
 
-#: src/Module/Contact.php:464
+#: src/Module/Contact.php:453
 msgid "Batch Actions"
 msgstr ""
 
-#: src/Module/Contact.php:507
+#: src/Module/Contact.php:496
 msgid "Conversations started by this contact"
 msgstr ""
 
-#: src/Module/Contact.php:512
+#: src/Module/Contact.php:501
 msgid "Posts and Comments"
 msgstr ""
 
-#: src/Module/Contact.php:515
+#: src/Module/Contact.php:504
 msgid "Individual Posts and Replies"
 msgstr ""
 
-#: src/Module/Contact.php:523
+#: src/Module/Contact.php:512
 msgid "Posts containing media objects"
 msgstr ""
 
-#: src/Module/Contact.php:531
+#: src/Module/Contact.php:520
 msgid "View all known contacts"
 msgstr ""
 
-#: src/Module/Contact.php:542
+#: src/Module/Contact.php:531
 msgid "Advanced Contact Settings"
 msgstr ""
 
-#: src/Module/Contact.php:578
+#: src/Module/Contact.php:567
 msgid "Mutual Friendship"
 msgstr ""
 
-#: src/Module/Contact.php:582
+#: src/Module/Contact.php:571
 msgid "is a fan of yours"
 msgstr ""
 
-#: src/Module/Contact.php:586
+#: src/Module/Contact.php:575
 msgid "you are a fan of"
 msgstr ""
 
-#: src/Module/Contact.php:604
+#: src/Module/Contact.php:593
 msgid "Pending outgoing contact request"
 msgstr ""
 
-#: src/Module/Contact.php:606
+#: src/Module/Contact.php:595
 msgid "Pending incoming contact request"
 msgstr ""
 
-#: src/Module/Contact.php:619 src/Module/Contact/Profile.php:377
+#: src/Module/Contact.php:608 src/Module/Contact/Profile.php:377
 #, php-format
 msgid "Visit %s's profile [%s]"
 msgstr ""
@@ -6282,19 +6270,15 @@ msgstr ""
 msgid "Diaspora support isn't enabled. Contact can't be added."
 msgstr ""
 
-#: src/Module/Contact/Follow.php:129
-msgid "OStatus support is disabled. Contact can't be added."
-msgstr ""
-
-#: src/Module/Contact/Follow.php:154 src/Module/Profile/RemoteFollow.php:118
+#: src/Module/Contact/Follow.php:149 src/Module/Profile/RemoteFollow.php:118
 msgid "Please answer the following:"
 msgstr ""
 
-#: src/Module/Contact/Follow.php:155 src/Module/Contact/Unfollow.php:109
+#: src/Module/Contact/Follow.php:150 src/Module/Contact/Unfollow.php:109
 msgid "Your Identity Address:"
 msgstr ""
 
-#: src/Module/Contact/Follow.php:156 src/Module/Contact/Profile.php:408
+#: src/Module/Contact/Follow.php:151 src/Module/Contact/Profile.php:408
 #: src/Module/Contact/Unfollow.php:115
 #: src/Module/Moderation/Blocklist/Contact.php:117
 #: src/Module/Moderation/Reports.php:109
@@ -6303,26 +6287,26 @@ msgstr ""
 msgid "Profile URL"
 msgstr ""
 
-#: src/Module/Contact/Follow.php:157 src/Module/Contact/Profile.php:420
+#: src/Module/Contact/Follow.php:152 src/Module/Contact/Profile.php:420
 #: src/Module/Notifications/Introductions.php:183
 #: src/Module/Profile/Profile.php:222
 msgid "Tags:"
 msgstr ""
 
-#: src/Module/Contact/Follow.php:168
+#: src/Module/Contact/Follow.php:163
 #, php-format
 msgid "%s knows you"
 msgstr ""
 
-#: src/Module/Contact/Follow.php:169
+#: src/Module/Contact/Follow.php:164
 msgid "Add a personal note:"
 msgstr ""
 
-#: src/Module/Contact/Follow.php:178 src/Module/Contact/Unfollow.php:124
+#: src/Module/Contact/Follow.php:173 src/Module/Contact/Unfollow.php:124
 msgid "Posts and Replies"
 msgstr ""
 
-#: src/Module/Contact/Follow.php:207
+#: src/Module/Contact/Follow.php:202
 msgid "The contact could not be added."
 msgstr ""
 
@@ -8397,22 +8381,6 @@ msgstr ""
 msgid "Unsupported or missing grant type"
 msgstr ""
 
-#: src/Module/OStatus/Repair.php:69
-msgid "Resubscribing to OStatus contacts"
-msgstr ""
-
-#: src/Module/OStatus/Repair.php:70 src/Module/OStatus/Subscribe.php:146
-msgid "Keep this window open until done."
-msgstr ""
-
-#: src/Module/OStatus/Repair.php:71
-msgid "✔ Done"
-msgstr ""
-
-#: src/Module/OStatus/Repair.php:72
-msgid "No OStatus contacts to resubscribe to."
-msgstr ""
-
 #: src/Module/OStatus/Subscribe.php:58
 msgid "Subscribing to contacts"
 msgstr ""
@@ -8457,6 +8425,10 @@ msgstr ""
 msgid "ignored"
 msgstr ""
 
+#: src/Module/OStatus/Subscribe.php:146
+msgid "Keep this window open until done."
+msgstr ""
+
 #: src/Module/Photo.php:108
 msgid "The Photo is not available."
 msgstr ""
@@ -8573,24 +8545,22 @@ msgstr ""
 msgid "No contacts."
 msgstr ""
 
-#: src/Module/Profile/Conversations.php:92
-#: src/Module/Profile/Conversations.php:95 src/Module/Profile/Profile.php:339
-#: src/Module/Profile/Profile.php:342 src/Protocol/Feed.php:1100
-#: src/Protocol/OStatus.php:997
+#: src/Module/Profile/Conversations.php:92 src/Module/Profile/Profile.php:339
+#: src/Protocol/Feed.php:1097
 #, php-format
-msgid "%s's timeline"
+msgid "%s's posts"
 msgstr ""
 
 #: src/Module/Profile/Conversations.php:93 src/Module/Profile/Profile.php:340
-#: src/Protocol/Feed.php:1104 src/Protocol/OStatus.php:1002
+#: src/Protocol/Feed.php:1100
 #, php-format
-msgid "%s's posts"
+msgid "%s's comments"
 msgstr ""
 
 #: src/Module/Profile/Conversations.php:94 src/Module/Profile/Profile.php:341
-#: src/Protocol/Feed.php:1107 src/Protocol/OStatus.php:1006
+#: src/Protocol/Feed.php:1093
 #, php-format
-msgid "%s's comments"
+msgid "%s's timeline"
 msgstr ""
 
 #: src/Module/Profile/Photos.php:150 src/Module/Profile/Photos.php:153
@@ -9710,184 +9680,173 @@ msgid "Diaspora (Socialhome, Hubzilla)"
 msgstr ""
 
 #: src/Module/Settings/Connectors.php:155
-#: src/Module/Settings/Connectors.php:159
 #, php-format
 msgid "Built-in support for %s connectivity is enabled"
 msgstr ""
 
 #: src/Module/Settings/Connectors.php:156
-#: src/Module/Settings/Connectors.php:158
 #, php-format
 msgid "Built-in support for %s connectivity is disabled"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:158
-#: src/Module/Settings/Connectors.php:159
-msgid "OStatus (GNU Social)"
-msgstr ""
-
-#: src/Module/Settings/Connectors.php:171
+#: src/Module/Settings/Connectors.php:167
 msgid "Email access is disabled on this site."
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:186
-#: src/Module/Settings/Connectors.php:240
+#: src/Module/Settings/Connectors.php:182
+#: src/Module/Settings/Connectors.php:233
 msgid "None"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:190
+#: src/Module/Settings/Connectors.php:186
 msgid "Default (Mastodon will display the title and a link to the post)"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:191
+#: src/Module/Settings/Connectors.php:187
 msgid "Use the summary (Mastodon and some others will treat it as content warning)"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:192
+#: src/Module/Settings/Connectors.php:188
 msgid "Embed the title in the body"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:204
+#: src/Module/Settings/Connectors.php:199
 msgid "General Social Media Settings"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:207
+#: src/Module/Settings/Connectors.php:202
 msgid "Followed content scope"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:209
+#: src/Module/Settings/Connectors.php:204
 msgid "By default, conversations in which your follows participated but didn't start will be shown in your timeline. You can turn this behavior off, or expand it to the conversations in which your follows liked a post."
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:211
+#: src/Module/Settings/Connectors.php:206
 msgid "Only conversations my follows started"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:212
+#: src/Module/Settings/Connectors.php:207
 msgid "Conversations my follows started or commented on (default)"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:213
+#: src/Module/Settings/Connectors.php:208
 msgid "Any conversation my follows interacted with, including likes"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:216
+#: src/Module/Settings/Connectors.php:211
 msgid "Collapse sensitive posts"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:216
+#: src/Module/Settings/Connectors.php:211
 msgid "If a post is marked as \"sensitive\", it will be displayed in a collapsed state, if this option is enabled."
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:217
+#: src/Module/Settings/Connectors.php:212
 msgid "Enable intelligent shortening"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:217
+#: src/Module/Settings/Connectors.php:212
 msgid "Normally the system tries to find the best link to add to shortened posts. If disabled, every shortened post will always point to the original friendica post."
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:218
+#: src/Module/Settings/Connectors.php:213
 msgid "Enable simple text shortening"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:218
+#: src/Module/Settings/Connectors.php:213
 msgid "Normally the system shortens posts at the next line feed. If this option is enabled then the system will shorten the text at the maximum character limit."
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:219
+#: src/Module/Settings/Connectors.php:214
 msgid "Attach the link title"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:219
+#: src/Module/Settings/Connectors.php:214
 msgid "When activated, the title of the attached link will be added as a title on posts to Diaspora. This is mostly helpful with \"remote-self\" contacts that share feed content."
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:220
+#: src/Module/Settings/Connectors.php:215
 msgid "API: Use spoiler field as title"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:220
+#: src/Module/Settings/Connectors.php:215
 msgid "When activated, the \"spoiler_text\" field in the API will be used for the title on standalone posts. When deactivated it will be used for spoiler text. For comments it will always be used for spoiler text."
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:221
+#: src/Module/Settings/Connectors.php:216
 msgid "API: Automatically links at the end of the post as attached posts"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:221
+#: src/Module/Settings/Connectors.php:216
 msgid "When activated, added links at the end of the post react the same way as added links in the web interface."
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:222
+#: src/Module/Settings/Connectors.php:217
 msgid "Article Mode"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:222
+#: src/Module/Settings/Connectors.php:217
 msgid "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."
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:223
+#: src/Module/Settings/Connectors.php:218
 msgid "Your legacy ActivityPub/GNU Social account"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:223
+#: src/Module/Settings/Connectors.php:218
 msgid "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."
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:225
-msgid "Repair OStatus subscriptions"
-msgstr ""
-
-#: src/Module/Settings/Connectors.php:229
+#: src/Module/Settings/Connectors.php:222
 msgid "Email/Mailbox Setup"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:230
+#: src/Module/Settings/Connectors.php:223
 msgid "If you wish to communicate with email contacts using this service (optional), please specify how to connect to your mailbox."
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:231
+#: src/Module/Settings/Connectors.php:224
 msgid "Last successful email check:"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:233
+#: src/Module/Settings/Connectors.php:226
 msgid "IMAP server name:"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:234
+#: src/Module/Settings/Connectors.php:227
 msgid "IMAP port:"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:235
+#: src/Module/Settings/Connectors.php:228
 msgid "Security:"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:236
+#: src/Module/Settings/Connectors.php:229
 msgid "Email login name:"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:237
+#: src/Module/Settings/Connectors.php:230
 msgid "Email password:"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:238
+#: src/Module/Settings/Connectors.php:231
 msgid "Reply-to address:"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:239
+#: src/Module/Settings/Connectors.php:232
 msgid "Send public posts to all email contacts:"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:240
+#: src/Module/Settings/Connectors.php:233
 msgid "Action after import:"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:240
+#: src/Module/Settings/Connectors.php:233
 msgid "Move to folder"
 msgstr ""
 
-#: src/Module/Settings/Connectors.php:241
+#: src/Module/Settings/Connectors.php:234
 msgid "Move to folder:"
 msgstr ""
 
@@ -11036,10 +10995,6 @@ msgstr ""
 msgid "Friend/Connect Request"
 msgstr ""
 
-#: src/Navigation/Notifications/Factory/Introduction.php:144
-msgid "New Follower"
-msgstr ""
-
 #: src/Navigation/Notifications/Factory/Notification.php:120
 #, php-format
 msgid "%1$s wants to follow you"
@@ -11738,24 +11693,6 @@ msgstr ""
 msgid "(no subject)"
 msgstr ""
 
-#: src/Protocol/OStatus.php:1378
-#, php-format
-msgid "%s is now following %s."
-msgstr ""
-
-#: src/Protocol/OStatus.php:1379
-msgid "following"
-msgstr ""
-
-#: src/Protocol/OStatus.php:1382
-#, php-format
-msgid "%s stopped following %s."
-msgstr ""
-
-#: src/Protocol/OStatus.php:1383
-msgid "stopped following"
-msgstr ""
-
 #: src/Render/FriendicaSmartyEngine.php:42
 #, php-format
 msgid "The folder %s must be writable by webserver."
index 3a86d35254ebe4d214013041ad8f1f5bf0fba2df..35e46dd712bda59f52072788843e9bfd8d3dbafe 100644 (file)
@@ -75,8 +75,6 @@
                        </div>
                {{/if}}
 
-               {{include file="field_checkbox.tpl" field=$ostatus_enabled}}
-
                {{if $diaspora_able}}
                        {{include file="field_checkbox.tpl" field=$diaspora_enabled}}
                {{else}}
index 06c70e855c16bff6649460c9be1712f4ccbe32f6..7c92f54b41dcd5e65adbdf6a97b8e9e50a1b9c4f 100644 (file)
@@ -27,8 +27,6 @@
                {{include file="field_select.tpl" field=$article_mode}}
                {{include file="field_input.tpl" field=$legacy_contact}}
 
-               <p><a href="{{$repair_ostatus_url}}">{{$repair_ostatus_text}}</a></p>
-
                <div class="settings-submit-wrapper">
                        <input type="submit" id="general-submit" name="general-submit" class="settings-submit" value="{{$submit}}"/>
                </div>
index 12b8e1bc47e8a9cb0d292b64f2ad2b6b99d9b8f7..bc55ab9a625571007f388aa0f33cb111a6a25b8e 100644 (file)
                                                        </div>
                                                {{/if}}
 
-                                               {{include file="field_checkbox.tpl" field=$ostatus_enabled}}
-
                                                {{if $diaspora_able}}
                                                        {{include file="field_checkbox.tpl" field=$diaspora_enabled}}
                                                {{else}}
index 41d8cb8e9d262f819f786cd3a727d532f2c2f638..aa1e0e7dbdf02fdbe1a3419bcfe1f03baed94ba1 100644 (file)
@@ -41,8 +41,6 @@
                                        {{include file="field_select.tpl" field=$article_mode}}
 
                                        {{include file="field_input.tpl" field=$legacy_contact}}                                        
-
-                                       <p><a href="{{$repair_ostatus_url}}">{{$repair_ostatus_text}}</a></p>
                                </div>
                                <div class="panel-footer">
                                        <button type="submit" id="general-submit" name="general-submit" class="btn btn-primary" value="{{$submit}}">{{$submit}}</button>