]> git.mxchange.org Git - friendica.git/commitdiff
The legacy OAuth server is removed
authorMichael <heluecht@pirati.ca>
Tue, 20 Jul 2021 17:41:04 +0000 (17:41 +0000)
committerMichael <heluecht@pirati.ca>
Tue, 20 Jul 2021 17:41:04 +0000 (17:41 +0000)
16 files changed:
database.sql
doc/database.md
doc/database/db_auth_codes.md [deleted file]
doc/database/db_clients.md [deleted file]
doc/database/db_tokens.md [deleted file]
include/api.php
mod/api.php
mod/settings.php
src/Database/DBStructure.php
src/Security/FKOAuth1.php [deleted file]
src/Security/FKOAuthDataStore.php [deleted file]
src/Security/OAuth1/OAuthServer.php [deleted file]
src/Worker/OptimizeTables.php
static/dbstructure.config.php
update.php
view/lang/C/messages.po

index 95e96a135a6733013f45145a8f976005aaee960a..3b9cceb069a02ba9668af7c595a1aab56c384620 100644 (file)
@@ -231,21 +231,6 @@ CREATE TABLE IF NOT EXISTS `tag` (
         INDEX `url` (`url`)
 ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='tags and mentions';
 
---
--- TABLE clients
---
-CREATE TABLE IF NOT EXISTS `clients` (
-       `client_id` varchar(20) NOT NULL COMMENT '',
-       `pw` varchar(20) NOT NULL DEFAULT '' COMMENT '',
-       `redirect_uri` varchar(200) NOT NULL DEFAULT '' COMMENT '',
-       `name` text COMMENT '',
-       `icon` text COMMENT '',
-       `uid` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'User id',
-        PRIMARY KEY(`client_id`),
-        INDEX `uid` (`uid`),
-       FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE
-) DEFAULT COLLATE utf8mb4_general_ci COMMENT='OAuth usage';
-
 --
 -- TABLE permissionset
 --
@@ -434,20 +419,6 @@ CREATE TABLE IF NOT EXISTS `attach` (
        FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE
 ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='file attachments';
 
---
--- TABLE auth_codes
---
-CREATE TABLE IF NOT EXISTS `auth_codes` (
-       `id` varchar(40) NOT NULL COMMENT '',
-       `client_id` varchar(20) NOT NULL DEFAULT '' COMMENT '',
-       `redirect_uri` varchar(200) NOT NULL DEFAULT '' COMMENT '',
-       `expires` int NOT NULL DEFAULT 0 COMMENT '',
-       `scope` varchar(250) NOT NULL DEFAULT '' COMMENT '',
-        PRIMARY KEY(`id`),
-        INDEX `client_id` (`client_id`),
-       FOREIGN KEY (`client_id`) REFERENCES `clients` (`client_id`) ON UPDATE RESTRICT ON DELETE CASCADE
-) DEFAULT COLLATE utf8mb4_general_ci COMMENT='OAuth usage';
-
 --
 -- TABLE cache
 --
@@ -1486,23 +1457,6 @@ CREATE TABLE IF NOT EXISTS `storage` (
         PRIMARY KEY(`id`)
 ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Data stored by Database storage backend';
 
---
--- TABLE tokens
---
-CREATE TABLE IF NOT EXISTS `tokens` (
-       `id` varchar(40) NOT NULL COMMENT '',
-       `secret` text COMMENT '',
-       `client_id` varchar(20) NOT NULL DEFAULT '',
-       `expires` int NOT NULL DEFAULT 0 COMMENT '',
-       `scope` varchar(200) NOT NULL DEFAULT '' COMMENT '',
-       `uid` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'User id',
-        PRIMARY KEY(`id`),
-        INDEX `client_id` (`client_id`),
-        INDEX `uid` (`uid`),
-       FOREIGN KEY (`client_id`) REFERENCES `clients` (`client_id`) ON UPDATE RESTRICT ON DELETE CASCADE,
-       FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE
-) DEFAULT COLLATE utf8mb4_general_ci COMMENT='OAuth usage';
-
 --
 -- TABLE userd
 --
index b2f4e4322511b872738c36b9dbac570a72f236b7..b1274ed327ab7dfc9ade474abc4690205ea666d2 100644 (file)
@@ -13,9 +13,7 @@ Database Tables
 | [application](help/database/db_application) | OAuth application |
 | [application-token](help/database/db_application-token) | OAuth user token |
 | [attach](help/database/db_attach) | file attachments |
-| [auth_codes](help/database/db_auth_codes) | OAuth usage |
 | [cache](help/database/db_cache) | Stores temporary data |
-| [clients](help/database/db_clients) | OAuth usage |
 | [config](help/database/db_config) | main configuration storage |
 | [contact](help/database/db_contact) | contact table |
 | [contact-relation](help/database/db_contact-relation) | Contact relations |
@@ -69,7 +67,6 @@ Database Tables
 | [session](help/database/db_session) | web session storage |
 | [storage](help/database/db_storage) | Data stored by Database storage backend |
 | [tag](help/database/db_tag) | tags and mentions |
-| [tokens](help/database/db_tokens) | OAuth usage |
 | [user](help/database/db_user) | The local users |
 | [user-contact](help/database/db_user-contact) | User specific public contact data |
 | [userd](help/database/db_userd) | Deleted usernames |
diff --git a/doc/database/db_auth_codes.md b/doc/database/db_auth_codes.md
deleted file mode 100644 (file)
index a1d28e0..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-Table auth_codes
-===========
-
-OAuth usage
-
-Fields
-------
-
-| Field        | Description | Type         | Null | Key | Default | Extra |
-| ------------ | ----------- | ------------ | ---- | --- | ------- | ----- |
-| id           |             | varchar(40)  | NO   | PRI | NULL    |       |
-| client_id    |             | varchar(20)  | NO   |     |         |       |
-| redirect_uri |             | varchar(200) | NO   |     |         |       |
-| expires      |             | int          | NO   |     | 0       |       |
-| scope        |             | varchar(250) | NO   |     |         |       |
-
-Indexes
-------------
-
-| Name      | Fields    |
-| --------- | --------- |
-| PRIMARY   | id        |
-| client_id | client_id |
-
-Foreign Keys
-------------
-
-| Field | Target Table | Target Field |
-|-------|--------------|--------------|
-| client_id | [clients](help/database/db_clients) | client_id |
-
-Return to [database documentation](help/database)
diff --git a/doc/database/db_clients.md b/doc/database/db_clients.md
deleted file mode 100644 (file)
index a97e796..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-Table clients
-===========
-
-OAuth usage
-
-Fields
-------
-
-| Field        | Description | Type               | Null | Key | Default | Extra |
-| ------------ | ----------- | ------------------ | ---- | --- | ------- | ----- |
-| client_id    |             | varchar(20)        | NO   | PRI | NULL    |       |
-| pw           |             | varchar(20)        | NO   |     |         |       |
-| redirect_uri |             | varchar(200)       | NO   |     |         |       |
-| name         |             | text               | YES  |     | NULL    |       |
-| icon         |             | text               | YES  |     | NULL    |       |
-| uid          | User id     | mediumint unsigned | NO   |     | 0       |       |
-
-Indexes
-------------
-
-| Name    | Fields    |
-| ------- | --------- |
-| PRIMARY | client_id |
-| uid     | uid       |
-
-Foreign Keys
-------------
-
-| Field | Target Table | Target Field |
-|-------|--------------|--------------|
-| uid | [user](help/database/db_user) | uid |
-
-Return to [database documentation](help/database)
diff --git a/doc/database/db_tokens.md b/doc/database/db_tokens.md
deleted file mode 100644 (file)
index 7cf9bba..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-Table tokens
-===========
-
-OAuth usage
-
-Fields
-------
-
-| Field     | Description | Type               | Null | Key | Default | Extra |
-| --------- | ----------- | ------------------ | ---- | --- | ------- | ----- |
-| id        |             | varchar(40)        | NO   | PRI | NULL    |       |
-| secret    |             | text               | YES  |     | NULL    |       |
-| client_id |             | varchar(20)        | NO   |     |         |       |
-| expires   |             | int                | NO   |     | 0       |       |
-| scope     |             | varchar(200)       | NO   |     |         |       |
-| uid       | User id     | mediumint unsigned | NO   |     | 0       |       |
-
-Indexes
-------------
-
-| Name      | Fields    |
-| --------- | --------- |
-| PRIMARY   | id        |
-| client_id | client_id |
-| uid       | uid       |
-
-Foreign Keys
-------------
-
-| Field | Target Table | Target Field |
-|-------|--------------|--------------|
-| client_id | [clients](help/database/db_clients) | client_id |
-| uid | [user](help/database/db_user) | uid |
-
-Return to [database documentation](help/database)
index 1d1cdc8f64074d3c15ef11cbce38b03d026d8376..b823b93df5fb9d7e3e958390a6edeb04a96c953e 100644 (file)
@@ -57,10 +57,7 @@ use Friendica\Network\HTTPException\UnauthorizedException;
 use Friendica\Object\Image;
 use Friendica\Protocol\Activity;
 use Friendica\Protocol\Diaspora;
-use Friendica\Security\FKOAuth1;
 use Friendica\Security\OAuth;
-use Friendica\Security\OAuth1\OAuthRequest;
-use Friendica\Security\OAuth1\OAuthUtil;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Images;
 use Friendica\Util\Network;
@@ -206,24 +203,6 @@ function api_login(App $a)
        }
 
        if (empty($_SERVER['PHP_AUTH_USER'])) {
-               // Try OAuth when no user is provided
-               $oauth1 = new FKOAuth1();
-               // login with oauth
-               try {
-                       $request = OAuthRequest::from_request();
-                       list($consumer, $token) = $oauth1->verify_request($request);
-                       if (!is_null($token)) {
-                               $oauth1->loginUser($token->uid);
-                               Session::set('allow_api', true);
-                               return;
-                       }
-                       echo __FILE__.__LINE__.__FUNCTION__ . "<pre>";
-                       var_dump($consumer, $token);
-                       die();
-               } catch (Exception $e) {
-                       Logger::warning(API_LOG_PREFIX . 'OAuth error', ['module' => 'api', 'action' => 'login', 'exception' => $e->getMessage()]);
-               }
-
                Logger::debug(API_LOG_PREFIX . 'failed', ['module' => 'api', 'action' => 'login', 'parameters' => $_SERVER]);
                header('WWW-Authenticate: Basic realm="Friendica"');
                throw new UnauthorizedException("This API requires login");
@@ -4057,48 +4036,6 @@ api_register_func('api/direct_messages/all', 'api_direct_messages_all', true);
 api_register_func('api/direct_messages/sent', 'api_direct_messages_sentbox', true);
 api_register_func('api/direct_messages', 'api_direct_messages_inbox', true);
 
-/**
- * Returns an OAuth Request Token.
- *
- * @see https://oauth.net/core/1.0/#auth_step1
- */
-function api_oauth_request_token()
-{
-       $oauth1 = new FKOAuth1();
-       try {
-               $r = $oauth1->fetch_request_token(OAuthRequest::from_request());
-       } catch (Exception $e) {
-               echo "error=" . OAuthUtil::urlencode_rfc3986($e->getMessage());
-               exit();
-       }
-       echo $r;
-       exit();
-}
-
-/**
- * Returns an OAuth Access Token.
- *
- * @return array|string
- * @see https://oauth.net/core/1.0/#auth_step3
- */
-function api_oauth_access_token()
-{
-       $oauth1 = new FKOAuth1();
-       try {
-               $r = $oauth1->fetch_access_token(OAuthRequest::from_request());
-       } catch (Exception $e) {
-               echo "error=". OAuthUtil::urlencode_rfc3986($e->getMessage());
-               exit();
-       }
-       echo $r;
-       exit();
-}
-
-/// @TODO move to top of file or somewhere better
-api_register_func('api/oauth/request_token', 'api_oauth_request_token', false);
-api_register_func('api/oauth/access_token', 'api_oauth_access_token', false);
-
-
 /**
  * delete a complete photoalbum with all containing photos from database through api
  *
index 79ffecd25d8c61af2f0a895d0978846289455f84..decbe40e9bb1de5d28ddf7e1d43bb438b7c9eb82 100644 (file)
  */
 
 use Friendica\App;
-use Friendica\Core\Renderer;
-use Friendica\Database\DBA;
 use Friendica\DI;
-use Friendica\Module\Security\Login;
-use Friendica\Security\OAuth1\OAuthRequest;
-use Friendica\Security\OAuth1\OAuthUtil;
 
 require_once __DIR__ . '/../include/api.php';
 
-function oauth_get_client(OAuthRequest $request)
-{
-       $params = $request->get_parameters();
-       $token = $params['oauth_token'];
-
-       $r = q("SELECT `clients`.*
-                       FROM `clients`, `tokens`
-                       WHERE `clients`.`client_id`=`tokens`.`client_id`
-                       AND `tokens`.`id`='%s' AND `tokens`.`scope`='request'", DBA::escape($token));
-
-       if (!DBA::isResult($r)) {
-               return null;
-       }
-
-       return $r[0];
-}
-
 function api_post(App $a)
 {
        if (!local_user()) {
@@ -61,76 +39,6 @@ function api_post(App $a)
 
 function api_content(App $a)
 {
-       if (DI::args()->getCommand() == 'api/oauth/authorize') {
-               /*
-                * api/oauth/authorize interact with the user. return a standard page
-                */
-
-               DI::page()['template'] = "minimal";
-
-               // get consumer/client from request token
-               try {
-                       $request = OAuthRequest::from_request();
-               } catch (Exception $e) {
-                       echo "<pre>";
-                       var_dump($e);
-                       exit();
-               }
-
-               if (!empty($_POST['oauth_yes'])) {
-                       $app = oauth_get_client($request);
-                       if (is_null($app)) {
-                               return "Invalid request. Unknown token.";
-                       }
-                       $consumer = new OAuthConsumer($app['client_id'], $app['pw'], $app['redirect_uri']);
-
-                       $verifier = md5($app['secret'] . local_user());
-                       DI::config()->set("oauth", $verifier, local_user());
-
-                       if ($consumer->callback_url != null) {
-                               $params = $request->get_parameters();
-                               $glue = "?";
-                               if (strstr($consumer->callback_url, $glue)) {
-                                       $glue = "?";
-                               }
-                               DI::baseUrl()->redirect($consumer->callback_url . $glue . 'oauth_token=' . OAuthUtil::urlencode_rfc3986($params['oauth_token']) . '&oauth_verifier=' . OAuthUtil::urlencode_rfc3986($verifier));
-                               exit();
-                       }
-
-                       $tpl = Renderer::getMarkupTemplate("oauth_authorize_done.tpl");
-                       $o = Renderer::replaceMacros($tpl, [
-                               '$title' => DI::l10n()->t('Authorize application connection'),
-                               '$info' => DI::l10n()->t('Return to your app and insert this Securty Code:'),
-                               '$code' => $verifier,
-                       ]);
-
-                       return $o;
-               }
-
-               if (!local_user()) {
-                       /// @TODO We need login form to redirect to this page
-                       notice(DI::l10n()->t('Please login to continue.'));
-                       return Login::form(DI::args()->getQueryString(), false, $request->get_parameters());
-               }
-               //FKOAuth1::loginUser(4);
-
-               $app = oauth_get_client($request);
-               if (is_null($app)) {
-                       return "Invalid request. Unknown token.";
-               }
-
-               $tpl = Renderer::getMarkupTemplate('oauth_authorize.tpl');
-               $o = Renderer::replaceMacros($tpl, [
-                       '$title' => DI::l10n()->t('Authorize application connection'),
-                       '$app' => $app,
-                       '$authorize' => DI::l10n()->t('Do you want to authorize this application to access your posts and contacts, and/or create new posts for you?'),
-                       '$yes' => DI::l10n()->t('Yes'),
-                       '$no' => DI::l10n()->t('No'),
-               ]);
-
-               return $o;
-       }
-
        echo api_call($a);
        exit();
 }
index 7e0b2d53b68bfafe755a2bfe1bff798985906680..cdff38a787ea821b00feb1cf4c0465ff38dd1e54 100644 (file)
@@ -66,63 +66,6 @@ function settings_post(App $a)
                return;
        }
 
-       $old_page_flags = $a->user['page-flags'];
-
-       if (($a->argc > 1) && ($a->argv[1] === 'oauth') && !empty($_POST['remove'])) {
-               BaseModule::checkFormSecurityTokenRedirectOnError('/settings/oauth', 'settings_oauth');
-
-               $key = $_POST['remove'];
-               DBA::delete('tokens', ['id' => $key, 'uid' => local_user()]);
-               DI::baseUrl()->redirect('settings/oauth/', true);
-               return;
-       }
-
-       if (($a->argc > 2) && ($a->argv[1] === 'oauth')  && ($a->argv[2] === 'edit'||($a->argv[2] === 'add')) && !empty($_POST['submit'])) {
-               BaseModule::checkFormSecurityTokenRedirectOnError('/settings/oauth', 'settings_oauth');
-
-               $name     = $_POST['name']     ?? '';
-               $key      = $_POST['key']      ?? '';
-               $secret   = $_POST['secret']   ?? '';
-               $redirect = $_POST['redirect'] ?? '';
-               $icon     = $_POST['icon']     ?? '';
-
-               if ($name == "" || $key == "" || $secret == "") {
-                       notice(DI::l10n()->t("Missing some important data!"));
-               } else {
-                       if ($_POST['submit'] == DI::l10n()->t("Update")) {
-                               q("UPDATE clients SET
-                                                       client_id='%s',
-                                                       pw='%s',
-                                                       name='%s',
-                                                       redirect_uri='%s',
-                                                       icon='%s',
-                                                       uid=%d
-                                               WHERE client_id='%s'",
-                                       DBA::escape($key),
-                                       DBA::escape($secret),
-                                       DBA::escape($name),
-                                       DBA::escape($redirect),
-                                       DBA::escape($icon),
-                                       local_user(),
-                                       DBA::escape($key)
-                               );
-                       } else {
-                               q("INSERT INTO clients
-                                                       (client_id, pw, name, redirect_uri, icon, uid)
-                                               VALUES ('%s', '%s', '%s', '%s', '%s',%d)",
-                                       DBA::escape($key),
-                                       DBA::escape($secret),
-                                       DBA::escape($name),
-                                       DBA::escape($redirect),
-                                       DBA::escape($icon),
-                                       local_user()
-                               );
-                       }
-               }
-               DI::baseUrl()->redirect('settings/oauth/', true);
-               return;
-       }
-
        if (($a->argc > 1) && ($a->argv[1] == 'addon')) {
                BaseModule::checkFormSecurityTokenRedirectOnError('/settings/addon', 'settings_addon');
 
index a6d4061a7c54f3266afdbe89377be56bc27f0688..c002c277c23fb31840c86ecaa561b2114d40044c 100644 (file)
@@ -81,7 +81,8 @@ 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'];
+                       'deliverq', 'dsprphotoq', 'ffinder', 'sign', 'spam', 'term', 'user-item', 'thread', 'item', 'challenge',
+                       'auth_codes', 'clients', 'tokens'];
 
                $tables = DBA::selectToArray(['INFORMATION_SCHEMA' => 'TABLES'], ['TABLE_NAME'],
                        ['TABLE_SCHEMA' => DBA::databaseName(), 'TABLE_TYPE' => 'BASE TABLE']);
@@ -1369,7 +1370,7 @@ class DBStructure
                        echo "permissionset: Table not found\n";
                }
 
-               if (!self::existsForeignKeyForField('tokens', 'client_id')) {
+               if (self::existsTable('tokens') && self::existsTable('clients') && !self::existsForeignKeyForField('tokens', 'client_id')) {
                        $tokens = DBA::p("SELECT `tokens`.`id` FROM `tokens`
                                LEFT JOIN `clients` ON `clients`.`client_id` = `tokens`.`client_id`
                                WHERE `clients`.`client_id` IS NULL");
diff --git a/src/Security/FKOAuth1.php b/src/Security/FKOAuth1.php
deleted file mode 100644 (file)
index 0cd10af..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Security;
-
-use Friendica\Core\Logger;
-use Friendica\Database\DBA;
-use Friendica\DI;
-use Friendica\Security\OAuth1\OAuthServer;
-use Friendica\Security\OAuth1\Signature\OAuthSignatureMethod_HMAC_SHA1;
-use Friendica\Security\OAuth1\Signature\OAuthSignatureMethod_PLAINTEXT;
-
-/**
- * OAuth protocol
- */
-class FKOAuth1 extends OAuthServer
-{
-       /**
-        * Constructor
-        */
-       public function __construct()
-       {
-               parent::__construct(new FKOAuthDataStore());
-               $this->add_signature_method(new OAuthSignatureMethod_PLAINTEXT());
-               $this->add_signature_method(new OAuthSignatureMethod_HMAC_SHA1());
-       }
-
-       /**
-        * @param string $uid user id
-        * @return void
-        * @throws HTTPException\ForbiddenException
-        * @throws HTTPException\InternalServerErrorException
-        */
-       public function loginUser($uid)
-       {
-               Logger::notice("FKOAuth1::loginUser $uid");
-               $a = DI::app();
-               $record = DBA::selectFirst('user', [], ['uid' => $uid, 'blocked' => 0, 'account_expired' => 0, 'account_removed' => 0, 'verified' => 1]);
-
-               if (!DBA::isResult($record) || empty($uid)) {
-                       Logger::info('FKOAuth1::loginUser failure', ['server' => $_SERVER]);
-                       header('HTTP/1.0 401 Unauthorized');
-                       die('This api requires login');
-               }
-
-               DI::auth()->setForUser($a, $record, true);
-       }
-}
diff --git a/src/Security/FKOAuthDataStore.php b/src/Security/FKOAuthDataStore.php
deleted file mode 100644 (file)
index 358f462..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Security;
-
-use Friendica\Core\Logger;
-use Friendica\Database\DBA;
-use Friendica\DI;
-use Friendica\Util\Strings;
-use Friendica\Security\OAuth1\OAuthConsumer;
-use Friendica\Security\OAuth1\OAuthDataStore;
-use Friendica\Security\OAuth1\OAuthToken;
-
-define('REQUEST_TOKEN_DURATION', 300);
-define('ACCESS_TOKEN_DURATION', 31536000);
-
-/**
- * Friendica\Security\OAuth1\OAuthDataStore class
- */
-class FKOAuthDataStore extends OAuthDataStore
-{
-       /**
-        * @return string
-        * @throws \Exception
-        */
-       private static function genToken()
-       {
-               return Strings::getRandomHex(32);
-       }
-
-       /**
-        * @param string $consumer_key key
-        * @return OAuthConsumer|null
-        * @throws \Exception
-        */
-       public function lookup_consumer($consumer_key)
-       {
-               Logger::log(__function__ . ":" . $consumer_key);
-
-               $s = DBA::select('clients', ['client_id', 'pw', 'redirect_uri'], ['client_id' => $consumer_key]);
-               $r = DBA::toArray($s);
-
-               if (DBA::isResult($r)) {
-                       return new OAuthConsumer($r[0]['client_id'], $r[0]['pw'], $r[0]['redirect_uri']);
-               }
-
-               return null;
-       }
-
-       /**
-        * @param OAuthConsumer $consumer
-        * @param string        $token_type
-        * @param string        $token_id
-        * @return OAuthToken|null
-        * @throws \Exception
-        */
-       public function lookup_token(OAuthConsumer $consumer, $token_type, $token_id)
-       {
-               Logger::log(__function__ . ":" . $consumer . ", " . $token_type . ", " . $token_id);
-
-               $s = DBA::select('tokens', ['id', 'secret', 'scope', 'expires', 'uid'], ['client_id' => $consumer->key, 'scope' => $token_type, 'id' => $token_id]);
-               $r = DBA::toArray($s);
-
-               if (DBA::isResult($r)) {
-                       $ot = new OAuthToken($r[0]['id'], $r[0]['secret']);
-                       $ot->scope = $r[0]['scope'];
-                       $ot->expires = $r[0]['expires'];
-                       $ot->uid = $r[0]['uid'];
-                       return $ot;
-               }
-
-               return null;
-       }
-
-       /**
-        * @param OAuthConsumer $consumer
-        * @param OAuthToken    $token
-        * @param string        $nonce
-        * @param int           $timestamp
-        * @return mixed
-        * @throws \Exception
-        */
-       public function lookup_nonce(OAuthConsumer $consumer, OAuthToken $token, $nonce, int $timestamp)
-       {
-               $token = DBA::selectFirst('tokens', ['id', 'secret'], ['client_id' => $consumer->key, 'id' => $nonce, 'expires' => $timestamp]);
-               if (DBA::isResult($token)) {
-                       return new OAuthToken($token['id'], $token['secret']);
-               }
-
-               return null;
-       }
-
-       /**
-        * @param OAuthConsumer $consumer
-        * @param string        $callback
-        * @return OAuthToken|null
-        * @throws \Exception
-        */
-       public function new_request_token(OAuthConsumer $consumer, $callback = null)
-       {
-               Logger::log(__function__ . ":" . $consumer . ", " . $callback);
-               $key = self::genToken();
-               $sec = self::genToken();
-
-               if ($consumer->key) {
-                       $k = $consumer->key;
-               } else {
-                       $k = $consumer;
-               }
-
-               $r = DBA::insert(
-                       'tokens',
-                       [
-                               'id' => $key,
-                               'secret' => $sec,
-                               'client_id' => $k,
-                               'scope' => 'request',
-                               'expires' => time() + REQUEST_TOKEN_DURATION
-                       ]
-               );
-
-               if (!$r) {
-                       return null;
-               }
-
-               return new OAuthToken($key, $sec);
-       }
-
-       /**
-        * @param OAuthToken    $token    token
-        * @param OAuthConsumer $consumer consumer
-        * @param string        $verifier optional, defult null
-        * @return OAuthToken
-        * @throws \Exception
-        */
-       public function new_access_token(OAuthToken $token, OAuthConsumer $consumer, $verifier = null)
-       {
-               Logger::log(__function__ . ":" . $token . ", " . $consumer . ", " . $verifier);
-
-               // return a new access token attached to this consumer
-               // for the user associated with this token if the request token
-               // is authorized
-               // should also invalidate the request token
-
-               $ret = null;
-
-               // get user for this verifier
-               $uverifier = DI::config()->get("oauth", $verifier);
-               Logger::log(__function__ . ":" . $verifier . "," . $uverifier);
-
-               if (is_null($verifier) || ($uverifier !== false)) {
-                       $key = self::genToken();
-                       $sec = self::genToken();
-                       $r = DBA::insert(
-                               'tokens',
-                               [
-                                       'id' => $key,
-                                       'secret' => $sec,
-                                       'client_id' => $consumer->key,
-                                       'scope' => 'access',
-                                       'expires' => time() + ACCESS_TOKEN_DURATION,
-                                       'uid' => $uverifier
-                               ]
-                       );
-
-                       if ($r) {
-                               $ret = new OAuthToken($key, $sec);
-                       }
-               }
-
-               DBA::delete('tokens', ['id' => $token->key]);
-
-               if (!is_null($ret) && !is_null($uverifier)) {
-                       DI::config()->delete("oauth", $verifier);
-               }
-
-               return $ret;
-       }
-}
diff --git a/src/Security/OAuth1/OAuthServer.php b/src/Security/OAuth1/OAuthServer.php
deleted file mode 100644 (file)
index c8884f6..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-<?php
-
-namespace Friendica\Security\OAuth1;
-
-use Friendica\Security\FKOAuthDataStore;
-use Friendica\Security\OAuth1\Signature;
-
-class OAuthServer
-{
-       protected $timestamp_threshold = 300; // in seconds, five minutes
-       protected $version = '1.0';             // hi blaine
-       /** @var Signature\OAuthSignatureMethod[] */
-       protected $signature_methods = [];
-
-       /** @var FKOAuthDataStore */
-       protected $data_store;
-
-       function __construct(FKOAuthDataStore $data_store)
-       {
-               $this->data_store = $data_store;
-       }
-
-       public function add_signature_method(Signature\OAuthSignatureMethod $signature_method)
-       {
-               $this->signature_methods[$signature_method->get_name()] =
-                       $signature_method;
-       }
-
-       // high level functions
-
-       /**
-        * process a request_token request
-        * returns the request token on success
-        *
-        * @param OAuthRequest $request
-        *
-        * @return OAuthToken|null
-        * @throws OAuthException
-        */
-       public function fetch_request_token(OAuthRequest $request)
-       {
-               $this->get_version($request);
-
-               $consumer = $this->get_consumer($request);
-
-               // no token required for the initial token request
-               $token = null;
-
-               $this->check_signature($request, $consumer, $token);
-
-               // Rev A change
-               $callback  = $request->get_parameter('oauth_callback');
-               $new_token = $this->data_store->new_request_token($consumer, $callback);
-
-               return $new_token;
-       }
-
-       /**
-        * process an access_token request
-        * returns the access token on success
-        *
-        * @param OAuthRequest $request
-        *
-        * @return object
-        * @throws OAuthException
-        */
-       public function fetch_access_token(OAuthRequest $request)
-       {
-               $this->get_version($request);
-
-               $consumer = $this->get_consumer($request);
-
-               // requires authorized request token
-               $token = $this->get_token($request, $consumer, "request");
-
-               $this->check_signature($request, $consumer, $token);
-
-               // Rev A change
-               $verifier  = $request->get_parameter('oauth_verifier');
-               $new_token = $this->data_store->new_access_token($token, $consumer, $verifier);
-
-               return $new_token;
-       }
-
-       /**
-        * verify an api call, checks all the parameters
-        *
-        * @param OAuthRequest $request
-        *
-        * @return array
-        * @throws OAuthException
-        */
-       public function verify_request(OAuthRequest $request)
-       {
-               $this->get_version($request);
-               $consumer = $this->get_consumer($request);
-               $token    = $this->get_token($request, $consumer, "access");
-               $this->check_signature($request, $consumer, $token);
-               return [$consumer, $token];
-       }
-
-       // Internals from here
-
-       /**
-        * version 1
-        *
-        * @param OAuthRequest $request
-        *
-        * @return string
-        * @throws OAuthException
-        */
-       private function get_version(OAuthRequest $request)
-       {
-               $version = $request->get_parameter("oauth_version");
-               if (!$version) {
-                       // Service Providers MUST assume the protocol version to be 1.0 if this parameter is not present.
-                       // Chapter 7.0 ("Accessing Protected Ressources")
-                       $version = '1.0';
-               }
-               if ($version !== $this->version) {
-                       throw new OAuthException("OAuth version '$version' not supported");
-               }
-               return $version;
-       }
-
-       /**
-        * figure out the signature with some defaults
-        *
-        * @param OAuthRequest $request
-        *
-        * @return Signature\OAuthSignatureMethod
-        * @throws OAuthException
-        */
-       private function get_signature_method(OAuthRequest $request)
-       {
-               $signature_method =
-                       @$request->get_parameter("oauth_signature_method");
-
-               if (!$signature_method) {
-                       // According to chapter 7 ("Accessing Protected Ressources") the signature-method
-                       // parameter is required, and we can't just fallback to PLAINTEXT
-                       throw new OAuthException('No signature method parameter. This parameter is required');
-               }
-
-               if (!in_array(
-                       $signature_method,
-                       array_keys($this->signature_methods)
-               )) {
-                       throw new OAuthException(
-                               "Signature method '$signature_method' not supported " .
-                               "try one of the following: " .
-                               implode(", ", array_keys($this->signature_methods))
-                       );
-               }
-               return $this->signature_methods[$signature_method];
-       }
-
-       /**
-        * try to find the consumer for the provided request's consumer key
-        *
-        * @param OAuthRequest $request
-        *
-        * @return OAuthConsumer
-        * @throws OAuthException
-        */
-       private function get_consumer(OAuthRequest $request)
-       {
-               $consumer_key = @$request->get_parameter("oauth_consumer_key");
-               if (!$consumer_key) {
-                       throw new OAuthException("Invalid consumer key");
-               }
-
-               $consumer = $this->data_store->lookup_consumer($consumer_key);
-               if (!$consumer) {
-                       throw new OAuthException("Invalid consumer");
-               }
-
-               return $consumer;
-       }
-
-       /**
-        * try to find the token for the provided request's token key
-        *
-        * @param OAuthRequest                            $request
-        * @param                                         $consumer
-        * @param string                                  $token_type
-        *
-        * @return OAuthToken|null
-        * @throws OAuthException
-        */
-       private function get_token(OAuthRequest &$request, $consumer, $token_type = "access")
-       {
-               $token_field = @$request->get_parameter('oauth_token');
-               $token       = $this->data_store->lookup_token(
-                       $consumer,
-                       $token_type,
-                       $token_field
-               );
-               if (!$token) {
-                       throw new OAuthException("Invalid $token_type token: $token_field");
-               }
-               return $token;
-       }
-
-       /**
-        * all-in-one function to check the signature on a request
-        * should guess the signature method appropriately
-        *
-        * @param OAuthRequest    $request
-        * @param OAuthConsumer   $consumer
-        * @param OAuthToken|null $token
-        *
-        * @throws OAuthException
-        */
-       private function check_signature(OAuthRequest $request, OAuthConsumer $consumer, OAuthToken $token = null)
-       {
-               // this should probably be in a different method
-               $timestamp = @$request->get_parameter('oauth_timestamp');
-               $nonce     = @$request->get_parameter('oauth_nonce');
-
-               $this->check_timestamp($timestamp);
-               $this->check_nonce($consumer, $token, $nonce, $timestamp);
-
-               $signature_method = $this->get_signature_method($request);
-
-               $signature = $request->get_parameter('oauth_signature');
-               $valid_sig = $signature_method->check_signature(
-                       $request,
-                       $consumer,
-                       $signature,
-                       $token
-               );
-
-               if (!$valid_sig) {
-                       throw new OAuthException("Invalid signature");
-               }
-       }
-
-       /**
-        * check that the timestamp is new enough
-        *
-        * @param int $timestamp
-        *
-        * @throws OAuthException
-        */
-       private function check_timestamp($timestamp)
-       {
-               if (!$timestamp)
-                       throw new OAuthException(
-                               'Missing timestamp parameter. The parameter is required'
-                       );
-
-               // verify that timestamp is recentish
-               $now = time();
-               if (abs($now - $timestamp) > $this->timestamp_threshold) {
-                       throw new OAuthException(
-                               "Expired timestamp, yours $timestamp, ours $now"
-                       );
-               }
-       }
-
-       /**
-        * check that the nonce is not repeated
-        *
-        * @param OAuthConsumer $consumer
-        * @param OAuthToken    $token
-        * @param string        $nonce
-        * @param int           $timestamp
-        *
-        * @throws OAuthException
-        */
-       private function check_nonce(OAuthConsumer $consumer, OAuthToken $token, $nonce, int $timestamp)
-       {
-               if (!$nonce)
-                       throw new OAuthException(
-                               'Missing nonce parameter. The parameter is required'
-                       );
-
-               // verify that the nonce is uniqueish
-               $found = $this->data_store->lookup_nonce(
-                       $consumer,
-                       $token,
-                       $nonce,
-                       $timestamp
-               );
-               if ($found) {
-                       throw new OAuthException("Nonce already used: $nonce");
-               }
-       }
-}
index c24d991b567266c234a860c2bad3389a3d4938e0..41c5b4a756e51c5266eebd26864cab509e77ffe4 100644 (file)
@@ -40,14 +40,12 @@ class OptimizeTables
 
                Logger::info('Optimize start');
 
-               DBA::e("OPTIMIZE TABLE `auth_codes`");
                DBA::e("OPTIMIZE TABLE `cache`");
                DBA::e("OPTIMIZE TABLE `locks`");
                DBA::e("OPTIMIZE TABLE `oembed`");
                DBA::e("OPTIMIZE TABLE `parsed_url`");
                DBA::e("OPTIMIZE TABLE `profile_check`");
                DBA::e("OPTIMIZE TABLE `session`");
-               DBA::e("OPTIMIZE TABLE `tokens`");
 
                Logger::info('Optimize end');
 
index 8af6c16eb1b1ef96491c118b2d83342529dcb86e..24ae1bb05cc247b967807c6f2745bfee272fe13e 100644 (file)
@@ -289,21 +289,6 @@ return [
                        "url" => ["url"]
                ]
        ],
-       "clients" => [
-               "comment" => "OAuth usage",
-               "fields" => [
-                       "client_id" => ["type" => "varchar(20)", "not null" => "1", "primary" => "1", "comment" => ""],
-                       "pw" => ["type" => "varchar(20)", "not null" => "1", "default" => "", "comment" => ""],
-                       "redirect_uri" => ["type" => "varchar(200)", "not null" => "1", "default" => "", "comment" => ""],
-                       "name" => ["type" => "text", "comment" => ""],
-                       "icon" => ["type" => "text", "comment" => ""],
-                       "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id"],
-               ],
-               "indexes" => [
-                       "PRIMARY" => ["client_id"],
-                       "uid" => ["uid"],
-               ]
-       ],
        "permissionset" => [
                "comment" => "",
                "fields" => [
@@ -494,21 +479,6 @@ return [
                        "uid" => ["uid"],
                ]
        ],
-       "auth_codes" => [
-               "comment" => "OAuth usage",
-               "fields" => [
-                       "id" => ["type" => "varchar(40)", "not null" => "1", "primary" => "1", "comment" => ""],
-                       "client_id" => ["type" => "varchar(20)", "not null" => "1", "default" => "", "foreign" => ["clients" => "client_id"],
-                               "comment" => ""],
-                       "redirect_uri" => ["type" => "varchar(200)", "not null" => "1", "default" => "", "comment" => ""],
-                       "expires" => ["type" => "int", "not null" => "1", "default" => "0", "comment" => ""],
-                       "scope" => ["type" => "varchar(250)", "not null" => "1", "default" => "", "comment" => ""],
-               ],
-               "indexes" => [
-                       "PRIMARY" => ["id"],
-                       "client_id" => ["client_id"]
-               ]
-       ],
        "cache" => [
                "comment" => "Stores temporary data",
                "fields" => [
@@ -1506,22 +1476,6 @@ return [
                        "PRIMARY" => ["id"]
                ]
        ],
-       "tokens" => [
-               "comment" => "OAuth usage",
-               "fields" => [
-                       "id" => ["type" => "varchar(40)", "not null" => "1", "primary" => "1", "comment" => ""],
-                       "secret" => ["type" => "text", "comment" => ""],
-                       "client_id" => ["type" => "varchar(20)", "not null" => "1", "default" => "", "foreign" => ["clients" => "client_id"]],
-                       "expires" => ["type" => "int", "not null" => "1", "default" => "0", "comment" => ""],
-                       "scope" => ["type" => "varchar(200)", "not null" => "1", "default" => "", "comment" => ""],
-                       "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "User id"],
-               ],
-               "indexes" => [
-                       "PRIMARY" => ["id"],
-                       "client_id" => ["client_id"],
-                       "uid" => ["uid"]
-               ]
-       ],
        "userd" => [
                "comment" => "Deleted usernames",
                "fields" => [
index 1ff19ecdd3c105c3bdb281d75561c80afdd71293..84f895838b5ac6af2b94dcd02bcb02ada7192be7 100644 (file)
@@ -240,9 +240,12 @@ function pre_update_1348()
 
        update_1348();
 
-       DBA::e("DELETE FROM `auth_codes` WHERE NOT `client_id` IN (SELECT `client_id` FROM `clients`)");
-       DBA::e("DELETE FROM `tokens` WHERE NOT `client_id` IN (SELECT `client_id` FROM `clients`)");
-
+       if (DBStructure::existsTable('auth_codes') && DBStructure::existsTable('clients')) {
+               DBA::e("DELETE FROM `auth_codes` WHERE NOT `client_id` IN (SELECT `client_id` FROM `clients`)");
+       }
+       if (DBStructure::existsTable('tokens') && DBStructure::existsTable('clients')) {
+               DBA::e("DELETE FROM `tokens` WHERE NOT `client_id` IN (SELECT `client_id` FROM `clients`)");
+       }
        return Update::SUCCESS;
 }
 
@@ -391,7 +394,7 @@ function pre_update_1364()
                return Update::FAILED;
        }
 
-       if (!DBA::e("DELETE FROM `clients` WHERE NOT `uid` IN (SELECT `uid` FROM `user`)")) {
+       if (DBStructure::existsTable('clients') && !DBA::e("DELETE FROM `clients` WHERE NOT `uid` IN (SELECT `uid` FROM `user`)")) {
                return Update::FAILED;
        }
 
@@ -463,7 +466,7 @@ function pre_update_1364()
                return Update::FAILED;
        }
 
-       if (!DBA::e("DELETE FROM `tokens` WHERE NOT `uid` IN (SELECT `uid` FROM `user`)")) {
+       if (DBStructure::existsTable('tokens') && !DBA::e("DELETE FROM `tokens` WHERE NOT `uid` IN (SELECT `uid` FROM `user`)")) {
                return Update::FAILED;
        }
 
index 127423df4caf21fc909d668a8666d38af42ed90d..cf7eb4e35e4e5920defb2e82ee5b54eb1065dc8c 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: 2021.09-dev\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-07-15 08:57+0000\n"
+"POT-Creation-Date: 2021-07-20 17:39+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"
@@ -18,26 +18,26 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 
 
-#: include/api.php:1135 src/Module/BaseApi.php:302
+#: include/api.php:1114 src/Module/BaseApi.php:302
 #, php-format
 msgid "Daily posting limit of %d post reached. The post was rejected."
 msgid_plural "Daily posting limit of %d posts reached. The post was rejected."
 msgstr[0] ""
 msgstr[1] ""
 
-#: include/api.php:1149 src/Module/BaseApi.php:318
+#: include/api.php:1128 src/Module/BaseApi.php:318
 #, php-format
 msgid "Weekly posting limit of %d post reached. The post was rejected."
 msgid_plural "Weekly posting limit of %d posts reached. The post was rejected."
 msgstr[0] ""
 msgstr[1] ""
 
-#: include/api.php:1163 src/Module/BaseApi.php:334
+#: include/api.php:1142 src/Module/BaseApi.php:334
 #, php-format
 msgid "Monthly posting limit of %d post reached. The post was rejected."
 msgstr ""
 
-#: include/api.php:4500 mod/photos.php:106 mod/photos.php:210
+#: include/api.php:4437 mod/photos.php:106 mod/photos.php:210
 #: mod/photos.php:638 mod/photos.php:1042 mod/photos.php:1059
 #: mod/photos.php:1608 src/Model/User.php:1105 src/Model/User.php:1113
 #: src/Model/User.php:1121 src/Module/Settings/Profile/Photo/Crop.php:98
@@ -54,7 +54,7 @@ msgstr ""
 msgid "%1$s poked %2$s"
 msgstr ""
 
-#: include/conversation.php:138 src/Model/Item.php:2606
+#: include/conversation.php:138 src/Model/Item.php:2614
 msgid "event"
 msgstr ""
 
@@ -62,7 +62,7 @@ msgstr ""
 msgid "status"
 msgstr ""
 
-#: include/conversation.php:146 mod/tagger.php:90 src/Model/Item.php:2608
+#: include/conversation.php:146 mod/tagger.php:90 src/Model/Item.php:2616
 msgid "photo"
 msgstr ""
 
@@ -75,7 +75,7 @@ msgstr ""
 msgid "Select"
 msgstr ""
 
-#: include/conversation.php:469 mod/photos.php:1470 mod/settings.php:633
+#: include/conversation.php:469 mod/photos.php:1470 mod/settings.php:576
 #: src/Module/Admin/Users/Active.php:139 src/Module/Admin/Users/Blocked.php:140
 #: src/Module/Admin/Users/Index.php:153 src/Module/Contact.php:894
 #: src/Module/Contact.php:1198
@@ -184,32 +184,32 @@ msgstr ""
 msgid "Follow Thread"
 msgstr ""
 
-#: include/conversation.php:852 src/Model/Contact.php:1043
+#: include/conversation.php:852 src/Model/Contact.php:1047
 msgid "View Status"
 msgstr ""
 
 #: include/conversation.php:853 include/conversation.php:875
-#: src/Model/Contact.php:969 src/Model/Contact.php:1035
-#: src/Model/Contact.php:1044 src/Module/Directory.php:166
+#: src/Model/Contact.php:973 src/Model/Contact.php:1039
+#: src/Model/Contact.php:1048 src/Module/Directory.php:166
 #: src/Module/Settings/Profile/Index.php:224
 msgid "View Profile"
 msgstr ""
 
-#: include/conversation.php:854 src/Model/Contact.php:1045
+#: include/conversation.php:854 src/Model/Contact.php:1049
 msgid "View Photos"
 msgstr ""
 
-#: include/conversation.php:855 src/Model/Contact.php:1036
-#: src/Model/Contact.php:1046
+#: include/conversation.php:855 src/Model/Contact.php:1040
+#: src/Model/Contact.php:1050
 msgid "Network Posts"
 msgstr ""
 
-#: include/conversation.php:856 src/Model/Contact.php:1037
-#: src/Model/Contact.php:1047
+#: include/conversation.php:856 src/Model/Contact.php:1041
+#: src/Model/Contact.php:1051
 msgid "View Contact"
 msgstr ""
 
-#: include/conversation.php:857 src/Model/Contact.php:1049
+#: include/conversation.php:857 src/Model/Contact.php:1053
 msgid "Send PM"
 msgstr ""
 
@@ -232,12 +232,12 @@ msgstr ""
 msgid "Languages"
 msgstr ""
 
-#: include/conversation.php:867 src/Model/Contact.php:1050
+#: include/conversation.php:867 src/Model/Contact.php:1054
 msgid "Poke"
 msgstr ""
 
 #: include/conversation.php:872 mod/follow.php:138 src/Content/Widget.php:76
-#: src/Model/Contact.php:1038 src/Model/Contact.php:1051
+#: src/Model/Contact.php:1042 src/Model/Contact.php:1055
 #: view/theme/vier/theme.php:172
 msgid "Connect/Follow"
 msgstr ""
@@ -461,7 +461,7 @@ msgstr ""
 msgid "Permission settings"
 msgstr ""
 
-#: include/conversation.php:1128 mod/editpost.php:134 mod/events.php:578
+#: include/conversation.php:1128 mod/editpost.php:134 mod/events.php:583
 #: mod/photos.php:968 mod/photos.php:1334
 msgid "Permissions"
 msgstr ""
@@ -470,7 +470,7 @@ msgstr ""
 msgid "Public post"
 msgstr ""
 
-#: include/conversation.php:1141 mod/editpost.php:125 mod/events.php:573
+#: include/conversation.php:1141 mod/editpost.php:125 mod/events.php:578
 #: mod/photos.php:1380 mod/photos.php:1437 mod/photos.php:1512
 #: src/Module/Item/Compose.php:154 src/Object/Post.php:971
 msgid "Preview"
@@ -822,12 +822,12 @@ msgstr ""
 msgid "Please visit %s to approve or reject the request."
 msgstr ""
 
-#: mod/api.php:52 mod/api.php:57 mod/editpost.php:37 mod/events.php:231
+#: mod/api.php:30 mod/api.php:35 mod/editpost.php:37 mod/events.php:236
 #: mod/follow.php:55 mod/follow.php:130 mod/item.php:185 mod/item.php:190
 #: mod/item.php:917 mod/message.php:69 mod/message.php:112 mod/notes.php:44
 #: mod/ostatus_subscribe.php:32 mod/photos.php:175 mod/photos.php:921
 #: mod/repair_ostatus.php:31 mod/settings.php:47 mod/settings.php:65
-#: mod/settings.php:474 mod/suggest.php:34 mod/uimport.php:32
+#: mod/settings.php:417 mod/suggest.php:34 mod/uimport.php:32
 #: mod/unfollow.php:35 mod/unfollow.php:50 mod/unfollow.php:82
 #: mod/wall_attach.php:78 mod/wall_attach.php:81 mod/wall_upload.php:99
 #: mod/wall_upload.php:102 mod/wallmessage.php:35 mod/wallmessage.php:59
@@ -855,35 +855,6 @@ msgstr ""
 msgid "Permission denied."
 msgstr ""
 
-#: mod/api.php:102 mod/api.php:124 src/Module/OAuth/Acknowledge.php:44
-msgid "Authorize application connection"
-msgstr ""
-
-#: mod/api.php:103
-msgid "Return to your app and insert this Securty Code:"
-msgstr ""
-
-#: mod/api.php:112 src/Module/BaseAdmin.php:54 src/Module/BaseAdmin.php:58
-msgid "Please login to continue."
-msgstr ""
-
-#: mod/api.php:126 src/Module/OAuth/Acknowledge.php:46
-msgid ""
-"Do you want to authorize this application to access your posts and contacts, "
-"and/or create new posts for you?"
-msgstr ""
-
-#: mod/api.php:127 src/Module/Contact.php:464
-#: src/Module/Notifications/Introductions.php:123
-#: src/Module/OAuth/Acknowledge.php:47 src/Module/Register.php:115
-msgid "Yes"
-msgstr ""
-
-#: mod/api.php:128 src/Module/Notifications/Introductions.php:123
-#: src/Module/OAuth/Acknowledge.php:48 src/Module/Register.php:116
-msgid "No"
-msgstr ""
-
 #: mod/cal.php:46 mod/cal.php:50 mod/follow.php:38 mod/redir.php:34
 #: mod/redir.php:176 src/Module/Conversation/Community.php:194
 #: src/Module/Debug/ItemBody.php:38 src/Module/Diaspora/Receive.php:51
@@ -906,45 +877,45 @@ msgstr ""
 msgid "Access to this profile has been restricted."
 msgstr ""
 
-#: mod/cal.php:274 mod/events.php:417 src/Content/Nav.php:195
+#: mod/cal.php:274 mod/events.php:422 src/Content/Nav.php:195
 #: src/Content/Nav.php:262 src/Module/BaseProfile.php:88
 #: src/Module/BaseProfile.php:99 view/theme/frio/theme.php:230
 #: view/theme/frio/theme.php:234
 msgid "Events"
 msgstr ""
 
-#: mod/cal.php:275 mod/events.php:418
+#: mod/cal.php:275 mod/events.php:423
 msgid "View"
 msgstr ""
 
-#: mod/cal.php:276 mod/events.php:420
+#: mod/cal.php:276 mod/events.php:425
 msgid "Previous"
 msgstr ""
 
-#: mod/cal.php:277 mod/events.php:421 src/Module/Install.php:207
+#: mod/cal.php:277 mod/events.php:426 src/Module/Install.php:207
 msgid "Next"
 msgstr ""
 
-#: mod/cal.php:280 mod/events.php:426 src/Model/Event.php:466
+#: mod/cal.php:280 mod/events.php:431 src/Model/Event.php:450
 msgid "today"
 msgstr ""
 
-#: mod/cal.php:281 mod/events.php:427 src/Model/Event.php:467
+#: mod/cal.php:281 mod/events.php:432 src/Model/Event.php:451
 #: src/Util/Temporal.php:330
 msgid "month"
 msgstr ""
 
-#: mod/cal.php:282 mod/events.php:428 src/Model/Event.php:468
+#: mod/cal.php:282 mod/events.php:433 src/Model/Event.php:452
 #: src/Util/Temporal.php:331
 msgid "week"
 msgstr ""
 
-#: mod/cal.php:283 mod/events.php:429 src/Model/Event.php:469
+#: mod/cal.php:283 mod/events.php:434 src/Model/Event.php:453
 #: src/Util/Temporal.php:332
 msgid "day"
 msgstr ""
 
-#: mod/cal.php:284 mod/events.php:430
+#: mod/cal.php:284 mod/events.php:435
 msgid "list"
 msgstr ""
 
@@ -1036,23 +1007,23 @@ msgstr ""
 msgid "Event title and start time are required."
 msgstr ""
 
-#: mod/events.php:419
+#: mod/events.php:424
 msgid "Create New Event"
 msgstr ""
 
-#: mod/events.php:531
+#: mod/events.php:536
 msgid "Event details"
 msgstr ""
 
-#: mod/events.php:532
+#: mod/events.php:537
 msgid "Starting date and Title are required."
 msgstr ""
 
-#: mod/events.php:533 mod/events.php:538
+#: mod/events.php:538 mod/events.php:543
 msgid "Event Starts:"
 msgstr ""
 
-#: mod/events.php:533 mod/events.php:565
+#: mod/events.php:538 mod/events.php:570
 #: src/Module/Admin/Blocklist/Server.php:79
 #: src/Module/Admin/Blocklist/Server.php:80
 #: src/Module/Admin/Blocklist/Server.php:99
@@ -1070,40 +1041,40 @@ msgstr ""
 msgid "Required"
 msgstr ""
 
-#: mod/events.php:546 mod/events.php:571
+#: mod/events.php:551 mod/events.php:576
 msgid "Finish date/time is not known or not relevant"
 msgstr ""
 
-#: mod/events.php:548 mod/events.php:553
+#: mod/events.php:553 mod/events.php:558
 msgid "Event Finishes:"
 msgstr ""
 
-#: mod/events.php:559 mod/events.php:572
+#: mod/events.php:564 mod/events.php:577
 msgid "Adjust for viewer timezone"
 msgstr ""
 
-#: mod/events.php:561 src/Module/Profile/Profile.php:172
+#: mod/events.php:566 src/Module/Profile/Profile.php:172
 #: src/Module/Settings/Profile/Index.php:237
 msgid "Description:"
 msgstr ""
 
-#: mod/events.php:563 src/Model/Event.php:86 src/Model/Event.php:113
-#: src/Model/Event.php:475 src/Model/Event.php:962 src/Model/Profile.php:420
+#: mod/events.php:568 src/Model/Event.php:86 src/Model/Event.php:113
+#: src/Model/Event.php:459 src/Model/Event.php:945 src/Model/Profile.php:420
 #: src/Module/Contact.php:654 src/Module/Directory.php:156
 #: src/Module/Notifications/Introductions.php:166
 #: src/Module/Profile/Profile.php:190
 msgid "Location:"
 msgstr ""
 
-#: mod/events.php:565 mod/events.php:567
+#: mod/events.php:570 mod/events.php:572
 msgid "Title:"
 msgstr ""
 
-#: mod/events.php:568 mod/events.php:569
+#: mod/events.php:573 mod/events.php:574
 msgid "Share this event"
 msgstr ""
 
-#: mod/events.php:575 mod/message.php:205 mod/message.php:368
+#: mod/events.php:580 mod/message.php:205 mod/message.php:368
 #: mod/photos.php:950 mod/photos.php:1053 mod/photos.php:1338
 #: mod/photos.php:1379 mod/photos.php:1436 mod/photos.php:1511
 #: src/Module/Admin/Item/Source.php:65 src/Module/Contact.php:612
@@ -1121,16 +1092,16 @@ msgstr ""
 msgid "Submit"
 msgstr ""
 
-#: mod/events.php:576 src/Module/Profile/Profile.php:244
+#: mod/events.php:581 src/Module/Profile/Profile.php:244
 msgid "Basic"
 msgstr ""
 
-#: mod/events.php:577 src/Module/Admin/Site.php:573 src/Module/Contact.php:961
+#: mod/events.php:582 src/Module/Admin/Site.php:573 src/Module/Contact.php:961
 #: src/Module/Profile/Profile.php:245
 msgid "Advanced"
 msgstr ""
 
-#: mod/events.php:594
+#: mod/events.php:599
 msgid "Failed to remove event"
 msgstr ""
 
@@ -1860,83 +1831,75 @@ msgid_plural "Errors"
 msgstr[0] ""
 msgstr[1] ""
 
-#: mod/settings.php:90
-msgid "Missing some important data!"
-msgstr ""
-
-#: mod/settings.php:92 src/Module/Contact.php:890
-msgid "Update"
-msgstr ""
-
-#: mod/settings.php:199
+#: mod/settings.php:142
 msgid "Failed to connect with email account using the settings provided."
 msgstr ""
 
-#: mod/settings.php:228
+#: mod/settings.php:171
 msgid "Contact CSV file upload error"
 msgstr ""
 
-#: mod/settings.php:247
+#: mod/settings.php:190
 msgid "Importing Contacts done"
 msgstr ""
 
-#: mod/settings.php:260
+#: mod/settings.php:203
 msgid "Relocate message has been send to your contacts"
 msgstr ""
 
-#: mod/settings.php:272
+#: mod/settings.php:215
 msgid "Passwords do not match."
 msgstr ""
 
-#: mod/settings.php:280 src/Console/User.php:210
+#: mod/settings.php:223 src/Console/User.php:210
 msgid "Password update failed. Please try again."
 msgstr ""
 
-#: mod/settings.php:283 src/Console/User.php:213
+#: mod/settings.php:226 src/Console/User.php:213
 msgid "Password changed."
 msgstr ""
 
-#: mod/settings.php:286
+#: mod/settings.php:229
 msgid "Password unchanged."
 msgstr ""
 
-#: mod/settings.php:371
+#: mod/settings.php:314
 msgid "Please use a shorter name."
 msgstr ""
 
-#: mod/settings.php:374
+#: mod/settings.php:317
 msgid "Name too short."
 msgstr ""
 
-#: mod/settings.php:381
+#: mod/settings.php:324
 msgid "Wrong Password."
 msgstr ""
 
-#: mod/settings.php:386
+#: mod/settings.php:329
 msgid "Invalid email."
 msgstr ""
 
-#: mod/settings.php:392
+#: mod/settings.php:335
 msgid "Cannot change to that email."
 msgstr ""
 
-#: mod/settings.php:430
+#: mod/settings.php:373
 msgid "Private forum has no privacy permissions. Using default privacy group."
 msgstr ""
 
-#: mod/settings.php:433
+#: mod/settings.php:376
 msgid "Private forum has no privacy permissions and no default privacy group."
 msgstr ""
 
-#: mod/settings.php:452
+#: mod/settings.php:395
 msgid "Settings were not updated."
 msgstr ""
 
-#: mod/settings.php:493
+#: mod/settings.php:436
 msgid "Connected Apps"
 msgstr ""
 
-#: mod/settings.php:494 src/Module/Admin/Blocklist/Contact.php:90
+#: mod/settings.php:437 src/Module/Admin/Blocklist/Contact.php:90
 #: src/Module/Admin/Users/Active.php:129 src/Module/Admin/Users/Blocked.php:130
 #: src/Module/Admin/Users/Create.php:71 src/Module/Admin/Users/Deleted.php:88
 #: src/Module/Admin/Users/Index.php:142 src/Module/Admin/Users/Index.php:162
@@ -1944,31 +1907,31 @@ msgstr ""
 msgid "Name"
 msgstr ""
 
-#: mod/settings.php:495 src/Content/Nav.php:216
+#: mod/settings.php:438 src/Content/Nav.php:216
 msgid "Home Page"
 msgstr ""
 
-#: mod/settings.php:496 src/Module/Admin/Queue.php:78
+#: mod/settings.php:439 src/Module/Admin/Queue.php:78
 msgid "Created"
 msgstr ""
 
-#: mod/settings.php:497
+#: mod/settings.php:440
 msgid "Remove authorization"
 msgstr ""
 
-#: mod/settings.php:515
+#: mod/settings.php:458
 msgid "Addon Settings"
 msgstr ""
 
-#: mod/settings.php:516
+#: mod/settings.php:459
 msgid "No Addon settings configured"
 msgstr ""
 
-#: mod/settings.php:537
+#: mod/settings.php:480
 msgid "Additional Features"
 msgstr ""
 
-#: mod/settings.php:539 mod/settings.php:635 mod/settings.php:770
+#: mod/settings.php:482 mod/settings.php:578 mod/settings.php:713
 #: src/Module/Admin/Addons/Index.php:69 src/Module/Admin/Features.php:87
 #: src/Module/Admin/Logs/Settings.php:82 src/Module/Admin/Site.php:568
 #: src/Module/Admin/Themes/Index.php:113 src/Module/Admin/Tos.php:66
@@ -1976,48 +1939,48 @@ msgstr ""
 msgid "Save Settings"
 msgstr ""
 
-#: mod/settings.php:561
+#: mod/settings.php:504
 msgid "Diaspora (Socialhome, Hubzilla)"
 msgstr ""
 
-#: mod/settings.php:561 mod/settings.php:562
+#: mod/settings.php:504 mod/settings.php:505
 msgid "enabled"
 msgstr ""
 
-#: mod/settings.php:561 mod/settings.php:562
+#: mod/settings.php:504 mod/settings.php:505
 msgid "disabled"
 msgstr ""
 
-#: mod/settings.php:561 mod/settings.php:562
+#: mod/settings.php:504 mod/settings.php:505
 #, php-format
 msgid "Built-in support for %s connectivity is %s"
 msgstr ""
 
-#: mod/settings.php:562
+#: mod/settings.php:505
 msgid "OStatus (GNU Social)"
 msgstr ""
 
-#: mod/settings.php:593
+#: mod/settings.php:536
 msgid "Email access is disabled on this site."
 msgstr ""
 
-#: mod/settings.php:598 mod/settings.php:633
+#: mod/settings.php:541 mod/settings.php:576
 msgid "None"
 msgstr ""
 
-#: mod/settings.php:604 src/Module/BaseSettings.php:80
+#: mod/settings.php:547 src/Module/BaseSettings.php:80
 msgid "Social Networks"
 msgstr ""
 
-#: mod/settings.php:609
+#: mod/settings.php:552
 msgid "General Social Media Settings"
 msgstr ""
 
-#: mod/settings.php:610
+#: mod/settings.php:553
 msgid "Accept only top level posts by contacts you follow"
 msgstr ""
 
-#: mod/settings.php:610
+#: mod/settings.php:553
 msgid ""
 "The system does an auto completion of threads when a comment arrives. This "
 "has got the side effect that you can receive posts that had been started by "
@@ -2026,11 +1989,11 @@ msgid ""
 "posts from people you really do follow."
 msgstr ""
 
-#: mod/settings.php:611
+#: mod/settings.php:554
 msgid "Disable Content Warning"
 msgstr ""
 
-#: mod/settings.php:611
+#: mod/settings.php:554
 msgid ""
 "Users on networks like Mastodon or Pleroma are able to set a content warning "
 "field which collapse their post by default. This disables the automatic "
@@ -2038,222 +2001,222 @@ msgid ""
 "any other content filtering you eventually set up."
 msgstr ""
 
-#: mod/settings.php:612
+#: mod/settings.php:555
 msgid "Disable intelligent shortening"
 msgstr ""
 
-#: mod/settings.php:612
+#: mod/settings.php:555
 msgid ""
 "Normally the system tries to find the best link to add to shortened posts. "
 "If this option is enabled then every shortened post will always point to the "
 "original friendica post."
 msgstr ""
 
-#: mod/settings.php:613
+#: mod/settings.php:556
 msgid "Enable simple text shortening"
 msgstr ""
 
-#: mod/settings.php:613
+#: mod/settings.php:556
 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 ""
 
-#: mod/settings.php:614
+#: mod/settings.php:557
 msgid "Attach the link title"
 msgstr ""
 
-#: mod/settings.php:614
+#: mod/settings.php:557
 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 ""
 
-#: mod/settings.php:615
+#: mod/settings.php:558
 msgid "Your legacy ActivityPub/GNU Social account"
 msgstr ""
 
-#: mod/settings.php:615
+#: mod/settings.php:558
 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 ""
 
-#: mod/settings.php:618
+#: mod/settings.php:561
 msgid "Repair OStatus subscriptions"
 msgstr ""
 
-#: mod/settings.php:622
+#: mod/settings.php:565
 msgid "Email/Mailbox Setup"
 msgstr ""
 
-#: mod/settings.php:623
+#: mod/settings.php:566
 msgid ""
 "If you wish to communicate with email contacts using this service "
 "(optional), please specify how to connect to your mailbox."
 msgstr ""
 
-#: mod/settings.php:624
+#: mod/settings.php:567
 msgid "Last successful email check:"
 msgstr ""
 
-#: mod/settings.php:626
+#: mod/settings.php:569
 msgid "IMAP server name:"
 msgstr ""
 
-#: mod/settings.php:627
+#: mod/settings.php:570
 msgid "IMAP port:"
 msgstr ""
 
-#: mod/settings.php:628
+#: mod/settings.php:571
 msgid "Security:"
 msgstr ""
 
-#: mod/settings.php:629
+#: mod/settings.php:572
 msgid "Email login name:"
 msgstr ""
 
-#: mod/settings.php:630
+#: mod/settings.php:573
 msgid "Email password:"
 msgstr ""
 
-#: mod/settings.php:631
+#: mod/settings.php:574
 msgid "Reply-to address:"
 msgstr ""
 
-#: mod/settings.php:632
+#: mod/settings.php:575
 msgid "Send public posts to all email contacts:"
 msgstr ""
 
-#: mod/settings.php:633
+#: mod/settings.php:576
 msgid "Action after import:"
 msgstr ""
 
-#: mod/settings.php:633 src/Content/Nav.php:284
+#: mod/settings.php:576 src/Content/Nav.php:284
 msgid "Mark as seen"
 msgstr ""
 
-#: mod/settings.php:633
+#: mod/settings.php:576
 msgid "Move to folder"
 msgstr ""
 
-#: mod/settings.php:634
+#: mod/settings.php:577
 msgid "Move to folder:"
 msgstr ""
 
-#: mod/settings.php:648
+#: mod/settings.php:591
 msgid "Unable to find your profile. Please contact your admin."
 msgstr ""
 
-#: mod/settings.php:684 src/Content/Widget.php:536
+#: mod/settings.php:627 src/Content/Widget.php:536
 msgid "Account Types"
 msgstr ""
 
-#: mod/settings.php:685
+#: mod/settings.php:628
 msgid "Personal Page Subtypes"
 msgstr ""
 
-#: mod/settings.php:686
+#: mod/settings.php:629
 msgid "Community Forum Subtypes"
 msgstr ""
 
-#: mod/settings.php:693 src/Module/Admin/BaseUsers.php:106
+#: mod/settings.php:636 src/Module/Admin/BaseUsers.php:106
 msgid "Personal Page"
 msgstr ""
 
-#: mod/settings.php:694
+#: mod/settings.php:637
 msgid "Account for a personal profile."
 msgstr ""
 
-#: mod/settings.php:697 src/Module/Admin/BaseUsers.php:107
+#: mod/settings.php:640 src/Module/Admin/BaseUsers.php:107
 msgid "Organisation Page"
 msgstr ""
 
-#: mod/settings.php:698
+#: mod/settings.php:641
 msgid ""
 "Account for an organisation that automatically approves contact requests as "
 "\"Followers\"."
 msgstr ""
 
-#: mod/settings.php:701 src/Module/Admin/BaseUsers.php:108
+#: mod/settings.php:644 src/Module/Admin/BaseUsers.php:108
 msgid "News Page"
 msgstr ""
 
-#: mod/settings.php:702
+#: mod/settings.php:645
 msgid ""
 "Account for a news reflector that automatically approves contact requests as "
 "\"Followers\"."
 msgstr ""
 
-#: mod/settings.php:705 src/Module/Admin/BaseUsers.php:109
+#: mod/settings.php:648 src/Module/Admin/BaseUsers.php:109
 msgid "Community Forum"
 msgstr ""
 
-#: mod/settings.php:706
+#: mod/settings.php:649
 msgid "Account for community discussions."
 msgstr ""
 
-#: mod/settings.php:709 src/Module/Admin/BaseUsers.php:99
+#: mod/settings.php:652 src/Module/Admin/BaseUsers.php:99
 msgid "Normal Account Page"
 msgstr ""
 
-#: mod/settings.php:710
+#: mod/settings.php:653
 msgid ""
 "Account for a regular personal profile that requires manual approval of "
 "\"Friends\" and \"Followers\"."
 msgstr ""
 
-#: mod/settings.php:713 src/Module/Admin/BaseUsers.php:100
+#: mod/settings.php:656 src/Module/Admin/BaseUsers.php:100
 msgid "Soapbox Page"
 msgstr ""
 
-#: mod/settings.php:714
+#: mod/settings.php:657
 msgid ""
 "Account for a public profile that automatically approves contact requests as "
 "\"Followers\"."
 msgstr ""
 
-#: mod/settings.php:717 src/Module/Admin/BaseUsers.php:101
+#: mod/settings.php:660 src/Module/Admin/BaseUsers.php:101
 msgid "Public Forum"
 msgstr ""
 
-#: mod/settings.php:718
+#: mod/settings.php:661
 msgid "Automatically approves all contact requests."
 msgstr ""
 
-#: mod/settings.php:721 src/Module/Admin/BaseUsers.php:102
+#: mod/settings.php:664 src/Module/Admin/BaseUsers.php:102
 msgid "Automatic Friend Page"
 msgstr ""
 
-#: mod/settings.php:722
+#: mod/settings.php:665
 msgid ""
 "Account for a popular profile that automatically approves contact requests "
 "as \"Friends\"."
 msgstr ""
 
-#: mod/settings.php:725
+#: mod/settings.php:668
 msgid "Private Forum [Experimental]"
 msgstr ""
 
-#: mod/settings.php:726
+#: mod/settings.php:669
 msgid "Requires manual approval of contact requests."
 msgstr ""
 
-#: mod/settings.php:737
+#: mod/settings.php:680
 msgid "OpenID:"
 msgstr ""
 
-#: mod/settings.php:737
+#: mod/settings.php:680
 msgid "(Optional) Allow this OpenID to login to this account."
 msgstr ""
 
-#: mod/settings.php:745
+#: mod/settings.php:688
 msgid "Publish your profile in your local site directory?"
 msgstr ""
 
-#: mod/settings.php:745
+#: mod/settings.php:688
 #, php-format
 msgid ""
 "Your profile will be published in this node's <a href=\"%s\">local "
@@ -2261,115 +2224,115 @@ msgid ""
 "system settings."
 msgstr ""
 
-#: mod/settings.php:751
+#: mod/settings.php:694
 #, php-format
 msgid ""
 "Your profile will also be published in the global friendica directories (e."
 "g. <a href=\"%s\">%s</a>)."
 msgstr ""
 
-#: mod/settings.php:757
+#: mod/settings.php:700
 #, php-format
 msgid "Your Identity Address is <strong>'%s'</strong> or '%s'."
 msgstr ""
 
-#: mod/settings.php:768
+#: mod/settings.php:711
 msgid "Account Settings"
 msgstr ""
 
-#: mod/settings.php:776
+#: mod/settings.php:719
 msgid "Password Settings"
 msgstr ""
 
-#: mod/settings.php:777 src/Module/Register.php:149
+#: mod/settings.php:720 src/Module/Register.php:149
 msgid "New Password:"
 msgstr ""
 
-#: mod/settings.php:777
+#: mod/settings.php:720
 msgid ""
 "Allowed characters are a-z, A-Z, 0-9 and special characters except white "
 "spaces, accentuated letters and colon (:)."
 msgstr ""
 
-#: mod/settings.php:778 src/Module/Register.php:150
+#: mod/settings.php:721 src/Module/Register.php:150
 msgid "Confirm:"
 msgstr ""
 
-#: mod/settings.php:778
+#: mod/settings.php:721
 msgid "Leave password fields blank unless changing"
 msgstr ""
 
-#: mod/settings.php:779
+#: mod/settings.php:722
 msgid "Current Password:"
 msgstr ""
 
-#: mod/settings.php:779
+#: mod/settings.php:722
 msgid "Your current password to confirm the changes"
 msgstr ""
 
-#: mod/settings.php:780
+#: mod/settings.php:723
 msgid "Password:"
 msgstr ""
 
-#: mod/settings.php:780
+#: mod/settings.php:723
 msgid "Your current password to confirm the changes of the email address"
 msgstr ""
 
-#: mod/settings.php:783
+#: mod/settings.php:726
 msgid "Delete OpenID URL"
 msgstr ""
 
-#: mod/settings.php:785
+#: mod/settings.php:728
 msgid "Basic Settings"
 msgstr ""
 
-#: mod/settings.php:786 src/Module/Profile/Profile.php:144
+#: mod/settings.php:729 src/Module/Profile/Profile.php:144
 msgid "Full Name:"
 msgstr ""
 
-#: mod/settings.php:787
+#: mod/settings.php:730
 msgid "Email Address:"
 msgstr ""
 
-#: mod/settings.php:788
+#: mod/settings.php:731
 msgid "Your Timezone:"
 msgstr ""
 
-#: mod/settings.php:789
+#: mod/settings.php:732
 msgid "Your Language:"
 msgstr ""
 
-#: mod/settings.php:789
+#: mod/settings.php:732
 msgid ""
 "Set the language we use to show you friendica interface and to send you "
 "emails"
 msgstr ""
 
-#: mod/settings.php:790
+#: mod/settings.php:733
 msgid "Default Post Location:"
 msgstr ""
 
-#: mod/settings.php:791
+#: mod/settings.php:734
 msgid "Use Browser Location:"
 msgstr ""
 
-#: mod/settings.php:793
+#: mod/settings.php:736
 msgid "Security and Privacy Settings"
 msgstr ""
 
-#: mod/settings.php:795
+#: mod/settings.php:738
 msgid "Maximum Friend Requests/Day:"
 msgstr ""
 
-#: mod/settings.php:795 mod/settings.php:805
+#: mod/settings.php:738 mod/settings.php:748
 msgid "(to prevent spam abuse)"
 msgstr ""
 
-#: mod/settings.php:797
+#: mod/settings.php:740
 msgid "Allow your profile to be searchable globally?"
 msgstr ""
 
-#: mod/settings.php:797
+#: mod/settings.php:740
 msgid ""
 "Activate this setting if you want others to easily find and follow you. Your "
 "profile will be searchable on remote systems. This setting also determines "
@@ -2377,43 +2340,43 @@ msgid ""
 "indexed or not."
 msgstr ""
 
-#: mod/settings.php:798
+#: mod/settings.php:741
 msgid "Hide your contact/friend list from viewers of your profile?"
 msgstr ""
 
-#: mod/settings.php:798
+#: mod/settings.php:741
 msgid ""
 "A list of your contacts is displayed on your profile page. Activate this "
 "option to disable the display of your contact list."
 msgstr ""
 
-#: mod/settings.php:799
+#: mod/settings.php:742
 msgid "Hide your profile details from anonymous viewers?"
 msgstr ""
 
-#: mod/settings.php:799
+#: mod/settings.php:742
 msgid ""
 "Anonymous visitors will only see your profile picture, your display name and "
 "the nickname you are using on your profile page. Your public posts and "
 "replies will still be accessible by other means."
 msgstr ""
 
-#: mod/settings.php:800
+#: mod/settings.php:743
 msgid "Make public posts unlisted"
 msgstr ""
 
-#: mod/settings.php:800
+#: mod/settings.php:743
 msgid ""
 "Your public posts will not appear on the community pages or in search "
 "results, nor be sent to relay servers. However they can still appear on "
 "public feeds on remote servers."
 msgstr ""
 
-#: mod/settings.php:801
+#: mod/settings.php:744
 msgid "Make all posted pictures accessible"
 msgstr ""
 
-#: mod/settings.php:801
+#: mod/settings.php:744
 msgid ""
 "This option makes every posted picture accessible via the direct link. This "
 "is a workaround for the problem that most other networks can't handle "
@@ -2421,209 +2384,209 @@ msgid ""
 "public on your photo albums though."
 msgstr ""
 
-#: mod/settings.php:802
+#: mod/settings.php:745
 msgid "Allow friends to post to your profile page?"
 msgstr ""
 
-#: mod/settings.php:802
+#: mod/settings.php:745
 msgid ""
 "Your contacts may write posts on your profile wall. These posts will be "
 "distributed to your contacts"
 msgstr ""
 
-#: mod/settings.php:803
+#: mod/settings.php:746
 msgid "Allow friends to tag your posts?"
 msgstr ""
 
-#: mod/settings.php:803
+#: mod/settings.php:746
 msgid "Your contacts can add additional tags to your posts."
 msgstr ""
 
-#: mod/settings.php:804
+#: mod/settings.php:747
 msgid "Permit unknown people to send you private mail?"
 msgstr ""
 
-#: mod/settings.php:804
+#: mod/settings.php:747
 msgid ""
 "Friendica network users may send you private messages even if they are not "
 "in your contact list."
 msgstr ""
 
-#: mod/settings.php:805
+#: mod/settings.php:748
 msgid "Maximum private messages per day from unknown people:"
 msgstr ""
 
-#: mod/settings.php:807
+#: mod/settings.php:750
 msgid "Default Post Permissions"
 msgstr ""
 
-#: mod/settings.php:811
+#: mod/settings.php:754
 msgid "Expiration settings"
 msgstr ""
 
-#: mod/settings.php:812
+#: mod/settings.php:755
 msgid "Automatically expire posts after this many days:"
 msgstr ""
 
-#: mod/settings.php:812
+#: mod/settings.php:755
 msgid "If empty, posts will not expire. Expired posts will be deleted"
 msgstr ""
 
-#: mod/settings.php:813
+#: mod/settings.php:756
 msgid "Expire posts"
 msgstr ""
 
-#: mod/settings.php:813
+#: mod/settings.php:756
 msgid "When activated, posts and comments will be expired."
 msgstr ""
 
-#: mod/settings.php:814
+#: mod/settings.php:757
 msgid "Expire personal notes"
 msgstr ""
 
-#: mod/settings.php:814
+#: mod/settings.php:757
 msgid ""
 "When activated, the personal notes on your profile page will be expired."
 msgstr ""
 
-#: mod/settings.php:815
+#: mod/settings.php:758
 msgid "Expire starred posts"
 msgstr ""
 
-#: mod/settings.php:815
+#: mod/settings.php:758
 msgid ""
 "Starring posts keeps them from being expired. That behaviour is overwritten "
 "by this setting."
 msgstr ""
 
-#: mod/settings.php:816
+#: mod/settings.php:759
 msgid "Expire photos"
 msgstr ""
 
-#: mod/settings.php:816
+#: mod/settings.php:759
 msgid "When activated, photos will be expired."
 msgstr ""
 
-#: mod/settings.php:817
+#: mod/settings.php:760
 msgid "Only expire posts by others"
 msgstr ""
 
-#: mod/settings.php:817
+#: mod/settings.php:760
 msgid ""
 "When activated, your own posts never expire. Then the settings above are "
 "only valid for posts you received."
 msgstr ""
 
-#: mod/settings.php:820
+#: mod/settings.php:763
 msgid "Notification Settings"
 msgstr ""
 
-#: mod/settings.php:821
+#: mod/settings.php:764
 msgid "Send a notification email when:"
 msgstr ""
 
-#: mod/settings.php:822
+#: mod/settings.php:765
 msgid "You receive an introduction"
 msgstr ""
 
-#: mod/settings.php:823
+#: mod/settings.php:766
 msgid "Your introductions are confirmed"
 msgstr ""
 
-#: mod/settings.php:824
+#: mod/settings.php:767
 msgid "Someone writes on your profile wall"
 msgstr ""
 
-#: mod/settings.php:825
+#: mod/settings.php:768
 msgid "Someone writes a followup comment"
 msgstr ""
 
-#: mod/settings.php:826
+#: mod/settings.php:769
 msgid "You receive a private message"
 msgstr ""
 
-#: mod/settings.php:827
+#: mod/settings.php:770
 msgid "You receive a friend suggestion"
 msgstr ""
 
-#: mod/settings.php:828
+#: mod/settings.php:771
 msgid "You are tagged in a post"
 msgstr ""
 
-#: mod/settings.php:829
+#: mod/settings.php:772
 msgid "You are poked/prodded/etc. in a post"
 msgstr ""
 
-#: mod/settings.php:831
+#: mod/settings.php:774
 msgid "Activate desktop notifications"
 msgstr ""
 
-#: mod/settings.php:831
+#: mod/settings.php:774
 msgid "Show desktop popup on new notifications"
 msgstr ""
 
-#: mod/settings.php:833
+#: mod/settings.php:776
 msgid "Text-only notification emails"
 msgstr ""
 
-#: mod/settings.php:835
+#: mod/settings.php:778
 msgid "Send text only notification emails, without the html part"
 msgstr ""
 
-#: mod/settings.php:837
+#: mod/settings.php:780
 msgid "Show detailled notifications"
 msgstr ""
 
-#: mod/settings.php:839
+#: mod/settings.php:782
 msgid ""
 "Per default, notifications are condensed to a single notification per item. "
 "When enabled every notification is displayed."
 msgstr ""
 
-#: mod/settings.php:841
+#: mod/settings.php:784
 msgid "Show notifications of ignored contacts"
 msgstr ""
 
-#: mod/settings.php:843
+#: mod/settings.php:786
 msgid ""
 "You don't see posts from ignored contacts. But you still see their comments. "
 "This setting controls if you want to still receive regular notifications "
 "that are caused by ignored contacts or not."
 msgstr ""
 
-#: mod/settings.php:845
+#: mod/settings.php:788
 msgid "Advanced Account/Page Type Settings"
 msgstr ""
 
-#: mod/settings.php:846
+#: mod/settings.php:789
 msgid "Change the behaviour of this account for special situations"
 msgstr ""
 
-#: mod/settings.php:849
+#: mod/settings.php:792
 msgid "Import Contacts"
 msgstr ""
 
-#: mod/settings.php:850
+#: mod/settings.php:793
 msgid ""
 "Upload a CSV file that contains the handle of your followed accounts in the "
 "first column you exported from the old account."
 msgstr ""
 
-#: mod/settings.php:851
+#: mod/settings.php:794
 msgid "Upload File"
 msgstr ""
 
-#: mod/settings.php:853
+#: mod/settings.php:796
 msgid "Relocate"
 msgstr ""
 
-#: mod/settings.php:854
+#: mod/settings.php:797
 msgid ""
 "If you have moved this profile from another server, and some of your "
 "contacts don't receive your updates, try pushing this button."
 msgstr ""
 
-#: mod/settings.php:855
+#: mod/settings.php:798
 msgid "Resend relocate message to contacts"
 msgstr ""
 
@@ -2746,7 +2709,7 @@ msgstr ""
 msgid "File upload failed."
 msgstr ""
 
-#: mod/wall_upload.php:233 src/Model/Photo.php:985
+#: mod/wall_upload.php:233 src/Model/Photo.php:987
 msgid "Wall Photos"
 msgstr ""
 
@@ -3435,8 +3398,8 @@ msgid ""
 "<a href=\"%1$s\" target=\"_blank\" rel=\"noopener noreferrer\">%2$s</a> %3$s"
 msgstr ""
 
-#: src/Content/Text/BBCode.php:1108 src/Model/Item.php:3134
-#: src/Model/Item.php:3140 src/Model/Item.php:3141
+#: src/Content/Text/BBCode.php:1108 src/Model/Item.php:3142
+#: src/Model/Item.php:3148 src/Model/Item.php:3149
 msgid "Link to source"
 msgstr ""
 
@@ -3591,7 +3554,7 @@ msgstr ""
 msgid "Organisations"
 msgstr ""
 
-#: src/Content/Widget.php:532 src/Model/Contact.php:1467
+#: src/Content/Widget.php:532 src/Model/Contact.php:1471
 msgid "News"
 msgstr ""
 
@@ -3977,137 +3940,137 @@ msgstr ""
 msgid "Could not connect to database."
 msgstr ""
 
-#: src/Core/L10n.php:377 src/Model/Event.php:434
+#: src/Core/L10n.php:377 src/Model/Event.php:418
 #: src/Module/Settings/Display.php:178
 msgid "Monday"
 msgstr ""
 
-#: src/Core/L10n.php:377 src/Model/Event.php:435
+#: src/Core/L10n.php:377 src/Model/Event.php:419
 msgid "Tuesday"
 msgstr ""
 
-#: src/Core/L10n.php:377 src/Model/Event.php:436
+#: src/Core/L10n.php:377 src/Model/Event.php:420
 msgid "Wednesday"
 msgstr ""
 
-#: src/Core/L10n.php:377 src/Model/Event.php:437
+#: src/Core/L10n.php:377 src/Model/Event.php:421
 msgid "Thursday"
 msgstr ""
 
-#: src/Core/L10n.php:377 src/Model/Event.php:438
+#: src/Core/L10n.php:377 src/Model/Event.php:422
 msgid "Friday"
 msgstr ""
 
-#: src/Core/L10n.php:377 src/Model/Event.php:439
+#: src/Core/L10n.php:377 src/Model/Event.php:423
 msgid "Saturday"
 msgstr ""
 
-#: src/Core/L10n.php:377 src/Model/Event.php:433
+#: src/Core/L10n.php:377 src/Model/Event.php:417
 #: src/Module/Settings/Display.php:178
 msgid "Sunday"
 msgstr ""
 
-#: src/Core/L10n.php:381 src/Model/Event.php:454
+#: src/Core/L10n.php:381 src/Model/Event.php:438
 msgid "January"
 msgstr ""
 
-#: src/Core/L10n.php:381 src/Model/Event.php:455
+#: src/Core/L10n.php:381 src/Model/Event.php:439
 msgid "February"
 msgstr ""
 
-#: src/Core/L10n.php:381 src/Model/Event.php:456
+#: src/Core/L10n.php:381 src/Model/Event.php:440
 msgid "March"
 msgstr ""
 
-#: src/Core/L10n.php:381 src/Model/Event.php:457
+#: src/Core/L10n.php:381 src/Model/Event.php:441
 msgid "April"
 msgstr ""
 
-#: src/Core/L10n.php:381 src/Core/L10n.php:401 src/Model/Event.php:445
+#: src/Core/L10n.php:381 src/Core/L10n.php:401 src/Model/Event.php:429
 msgid "May"
 msgstr ""
 
-#: src/Core/L10n.php:381 src/Model/Event.php:458
+#: src/Core/L10n.php:381 src/Model/Event.php:442
 msgid "June"
 msgstr ""
 
-#: src/Core/L10n.php:381 src/Model/Event.php:459
+#: src/Core/L10n.php:381 src/Model/Event.php:443
 msgid "July"
 msgstr ""
 
-#: src/Core/L10n.php:381 src/Model/Event.php:460
+#: src/Core/L10n.php:381 src/Model/Event.php:444
 msgid "August"
 msgstr ""
 
-#: src/Core/L10n.php:381 src/Model/Event.php:461
+#: src/Core/L10n.php:381 src/Model/Event.php:445
 msgid "September"
 msgstr ""
 
-#: src/Core/L10n.php:381 src/Model/Event.php:462
+#: src/Core/L10n.php:381 src/Model/Event.php:446
 msgid "October"
 msgstr ""
 
-#: src/Core/L10n.php:381 src/Model/Event.php:463
+#: src/Core/L10n.php:381 src/Model/Event.php:447
 msgid "November"
 msgstr ""
 
-#: src/Core/L10n.php:381 src/Model/Event.php:464
+#: src/Core/L10n.php:381 src/Model/Event.php:448
 msgid "December"
 msgstr ""
 
-#: src/Core/L10n.php:397 src/Model/Event.php:426
+#: src/Core/L10n.php:397 src/Model/Event.php:410
 msgid "Mon"
 msgstr ""
 
-#: src/Core/L10n.php:397 src/Model/Event.php:427
+#: src/Core/L10n.php:397 src/Model/Event.php:411
 msgid "Tue"
 msgstr ""
 
-#: src/Core/L10n.php:397 src/Model/Event.php:428
+#: src/Core/L10n.php:397 src/Model/Event.php:412
 msgid "Wed"
 msgstr ""
 
-#: src/Core/L10n.php:397 src/Model/Event.php:429
+#: src/Core/L10n.php:397 src/Model/Event.php:413
 msgid "Thu"
 msgstr ""
 
-#: src/Core/L10n.php:397 src/Model/Event.php:430
+#: src/Core/L10n.php:397 src/Model/Event.php:414
 msgid "Fri"
 msgstr ""
 
-#: src/Core/L10n.php:397 src/Model/Event.php:431
+#: src/Core/L10n.php:397 src/Model/Event.php:415
 msgid "Sat"
 msgstr ""
 
-#: src/Core/L10n.php:397 src/Model/Event.php:425
+#: src/Core/L10n.php:397 src/Model/Event.php:409
 msgid "Sun"
 msgstr ""
 
-#: src/Core/L10n.php:401 src/Model/Event.php:441
+#: src/Core/L10n.php:401 src/Model/Event.php:425
 msgid "Jan"
 msgstr ""
 
-#: src/Core/L10n.php:401 src/Model/Event.php:442
+#: src/Core/L10n.php:401 src/Model/Event.php:426
 msgid "Feb"
 msgstr ""
 
-#: src/Core/L10n.php:401 src/Model/Event.php:443
+#: src/Core/L10n.php:401 src/Model/Event.php:427
 msgid "Mar"
 msgstr ""
 
-#: src/Core/L10n.php:401 src/Model/Event.php:444
+#: src/Core/L10n.php:401 src/Model/Event.php:428
 msgid "Apr"
 msgstr ""
 
-#: src/Core/L10n.php:401 src/Model/Event.php:446
+#: src/Core/L10n.php:401 src/Model/Event.php:430
 msgid "Jun"
 msgstr ""
 
-#: src/Core/L10n.php:401 src/Model/Event.php:447
+#: src/Core/L10n.php:401 src/Model/Event.php:431
 msgid "Jul"
 msgstr ""
 
-#: src/Core/L10n.php:401 src/Model/Event.php:448
+#: src/Core/L10n.php:401 src/Model/Event.php:432
 msgid "Aug"
 msgstr ""
 
@@ -4115,15 +4078,15 @@ msgstr ""
 msgid "Sep"
 msgstr ""
 
-#: src/Core/L10n.php:401 src/Model/Event.php:450
+#: src/Core/L10n.php:401 src/Model/Event.php:434
 msgid "Oct"
 msgstr ""
 
-#: src/Core/L10n.php:401 src/Model/Event.php:451
+#: src/Core/L10n.php:401 src/Model/Event.php:435
 msgid "Nov"
 msgstr ""
 
-#: src/Core/L10n.php:401 src/Model/Event.php:452
+#: src/Core/L10n.php:401 src/Model/Event.php:436
 msgid "Dec"
 msgstr ""
 
@@ -4291,21 +4254,21 @@ msgid ""
 "tables."
 msgstr ""
 
-#: src/Database/DBStructure.php:90
+#: src/Database/DBStructure.php:91
 msgid "No unused tables found."
 msgstr ""
 
-#: src/Database/DBStructure.php:95
+#: src/Database/DBStructure.php:96
 msgid ""
 "These tables are not used for friendica and will be deleted when you execute "
 "\"dbstructure drop -e\":"
 msgstr ""
 
-#: src/Database/DBStructure.php:133
+#: src/Database/DBStructure.php:134
 msgid "There are no tables on MyISAM or InnoDB with the Antelope file format."
 msgstr ""
 
-#: src/Database/DBStructure.php:157
+#: src/Database/DBStructure.php:158
 #, php-format
 msgid ""
 "\n"
@@ -4313,20 +4276,20 @@ msgid ""
 "%s\n"
 msgstr ""
 
-#: src/Database/DBStructure.php:160
+#: src/Database/DBStructure.php:161
 msgid "Errors encountered performing database changes: "
 msgstr ""
 
-#: src/Database/DBStructure.php:548
+#: src/Database/DBStructure.php:549
 msgid "Another database update is currently running."
 msgstr ""
 
-#: src/Database/DBStructure.php:552
+#: src/Database/DBStructure.php:553
 #, php-format
 msgid "%s: Database update"
 msgstr ""
 
-#: src/Database/DBStructure.php:852
+#: src/Database/DBStructure.php:853
 #, php-format
 msgid "%s: updating %s table."
 msgstr ""
@@ -4412,153 +4375,153 @@ msgstr ""
 msgid "Legacy module file not found: %s"
 msgstr ""
 
-#: src/Model/Contact.php:1039 src/Model/Contact.php:1052
+#: src/Model/Contact.php:1043 src/Model/Contact.php:1056
 msgid "UnFollow"
 msgstr ""
 
-#: src/Model/Contact.php:1048
+#: src/Model/Contact.php:1052
 msgid "Drop Contact"
 msgstr ""
 
-#: src/Model/Contact.php:1058 src/Module/Admin/Users/Pending.php:107
+#: src/Model/Contact.php:1062 src/Module/Admin/Users/Pending.php:107
 #: src/Module/Notifications/Introductions.php:111
 #: src/Module/Notifications/Introductions.php:183
 msgid "Approve"
 msgstr ""
 
-#: src/Model/Contact.php:1463
+#: src/Model/Contact.php:1467
 msgid "Organisation"
 msgstr ""
 
-#: src/Model/Contact.php:1471
+#: src/Model/Contact.php:1475
 msgid "Forum"
 msgstr ""
 
-#: src/Model/Contact.php:2327
+#: src/Model/Contact.php:2331
 msgid "Disallowed profile URL."
 msgstr ""
 
-#: src/Model/Contact.php:2332 src/Module/Friendica.php:80
+#: src/Model/Contact.php:2336 src/Module/Friendica.php:80
 msgid "Blocked domain"
 msgstr ""
 
-#: src/Model/Contact.php:2337
+#: src/Model/Contact.php:2341
 msgid "Connect URL missing."
 msgstr ""
 
-#: src/Model/Contact.php:2346
+#: src/Model/Contact.php:2350
 msgid ""
 "The contact could not be added. Please check the relevant network "
 "credentials in your Settings -> Social Networks page."
 msgstr ""
 
-#: src/Model/Contact.php:2383
+#: src/Model/Contact.php:2387
 msgid "The profile address specified does not provide adequate information."
 msgstr ""
 
-#: src/Model/Contact.php:2385
+#: src/Model/Contact.php:2389
 msgid "No compatible communication protocols or feeds were discovered."
 msgstr ""
 
-#: src/Model/Contact.php:2388
+#: src/Model/Contact.php:2392
 msgid "An author or name was not found."
 msgstr ""
 
-#: src/Model/Contact.php:2391
+#: src/Model/Contact.php:2395
 msgid "No browser URL could be matched to this address."
 msgstr ""
 
-#: src/Model/Contact.php:2394
+#: src/Model/Contact.php:2398
 msgid ""
 "Unable to match @-style Identity Address with a known protocol or email "
 "contact."
 msgstr ""
 
-#: src/Model/Contact.php:2395
+#: src/Model/Contact.php:2399
 msgid "Use mailto: in front of address to force email check."
 msgstr ""
 
-#: src/Model/Contact.php:2401
+#: src/Model/Contact.php:2405
 msgid ""
 "The profile address specified belongs to a network which has been disabled "
 "on this site."
 msgstr ""
 
-#: src/Model/Contact.php:2406
+#: src/Model/Contact.php:2410
 msgid ""
 "Limited profile. This person will be unable to receive direct/personal "
 "notifications from you."
 msgstr ""
 
-#: src/Model/Contact.php:2465
+#: src/Model/Contact.php:2469
 msgid "Unable to retrieve contact information."
 msgstr ""
 
-#: src/Model/Event.php:52 src/Model/Event.php:874
+#: src/Model/Event.php:52 src/Model/Event.php:857
 #: src/Module/Debug/Localtime.php:36
 msgid "l F d, Y \\@ g:i A"
 msgstr ""
 
-#: src/Model/Event.php:79 src/Model/Event.php:96 src/Model/Event.php:473
-#: src/Model/Event.php:944
+#: src/Model/Event.php:79 src/Model/Event.php:96 src/Model/Event.php:457
+#: src/Model/Event.php:927
 msgid "Starts:"
 msgstr ""
 
-#: src/Model/Event.php:82 src/Model/Event.php:102 src/Model/Event.php:474
-#: src/Model/Event.php:948
+#: src/Model/Event.php:82 src/Model/Event.php:102 src/Model/Event.php:458
+#: src/Model/Event.php:931
 msgid "Finishes:"
 msgstr ""
 
-#: src/Model/Event.php:423
+#: src/Model/Event.php:407
 msgid "all-day"
 msgstr ""
 
-#: src/Model/Event.php:449
+#: src/Model/Event.php:433
 msgid "Sept"
 msgstr ""
 
-#: src/Model/Event.php:471
+#: src/Model/Event.php:455
 msgid "No events to display"
 msgstr ""
 
-#: src/Model/Event.php:590
+#: src/Model/Event.php:573
 msgid "l, F j"
 msgstr ""
 
-#: src/Model/Event.php:621
+#: src/Model/Event.php:604
 msgid "Edit event"
 msgstr ""
 
-#: src/Model/Event.php:622
+#: src/Model/Event.php:605
 msgid "Duplicate event"
 msgstr ""
 
-#: src/Model/Event.php:623
+#: src/Model/Event.php:606
 msgid "Delete event"
 msgstr ""
 
-#: src/Model/Event.php:875
+#: src/Model/Event.php:858
 msgid "D g:i A"
 msgstr ""
 
-#: src/Model/Event.php:876
+#: src/Model/Event.php:859
 msgid "g:i A"
 msgstr ""
 
-#: src/Model/Event.php:963 src/Model/Event.php:965
+#: src/Model/Event.php:946 src/Model/Event.php:948
 msgid "Show map"
 msgstr ""
 
-#: src/Model/Event.php:964
+#: src/Model/Event.php:947
 msgid "Hide map"
 msgstr ""
 
-#: src/Model/Event.php:1056
+#: src/Model/Event.php:1039
 #, php-format
 msgid "%s's birthday"
 msgstr ""
 
-#: src/Model/Event.php:1057
+#: src/Model/Event.php:1040
 #, php-format
 msgid "Happy Birthday %s"
 msgstr ""
@@ -4607,33 +4570,33 @@ msgstr ""
 msgid "Edit groups"
 msgstr ""
 
-#: src/Model/Item.php:1660
+#: src/Model/Item.php:1668
 #, php-format
 msgid "Detected languages in this post:\\n%s"
 msgstr ""
 
-#: src/Model/Item.php:2610
+#: src/Model/Item.php:2618
 msgid "activity"
 msgstr ""
 
-#: src/Model/Item.php:2612
+#: src/Model/Item.php:2620
 msgid "comment"
 msgstr ""
 
-#: src/Model/Item.php:2615
+#: src/Model/Item.php:2623
 msgid "post"
 msgstr ""
 
-#: src/Model/Item.php:2729
+#: src/Model/Item.php:2737
 #, php-format
 msgid "Content warning: %s"
 msgstr ""
 
-#: src/Model/Item.php:3099
+#: src/Model/Item.php:3107
 msgid "bytes"
 msgstr ""
 
-#: src/Model/Item.php:3128 src/Model/Item.php:3129
+#: src/Model/Item.php:3136 src/Model/Item.php:3137
 msgid "View on separate page"
 msgstr ""
 
@@ -7012,6 +6975,10 @@ msgstr ""
 msgid "Item was not found."
 msgstr ""
 
+#: src/Module/BaseAdmin.php:54 src/Module/BaseAdmin.php:58
+msgid "Please login to continue."
+msgstr ""
+
 #: src/Module/BaseAdmin.php:63
 msgid "You don't have access to administration pages."
 msgstr ""
@@ -7223,6 +7190,11 @@ msgstr ""
 msgid "Do you really want to delete this contact?"
 msgstr ""
 
+#: src/Module/Contact.php:464 src/Module/Notifications/Introductions.php:123
+#: src/Module/OAuth/Acknowledge.php:47 src/Module/Register.php:115
+msgid "Yes"
+msgstr ""
+
 #: src/Module/Contact.php:476
 msgid "Contact has been removed."
 msgstr ""
@@ -7473,6 +7445,10 @@ msgstr ""
 msgid "Results for: %s"
 msgstr ""
 
+#: src/Module/Contact.php:890
+msgid "Update"
+msgstr ""
+
 #: src/Module/Contact.php:893 src/Module/Contact.php:1190
 msgid "Archive"
 msgstr ""
@@ -8583,6 +8559,11 @@ msgstr ""
 msgid "Claims to be known to you: "
 msgstr ""
 
+#: src/Module/Notifications/Introductions.php:123
+#: src/Module/OAuth/Acknowledge.php:48 src/Module/Register.php:116
+msgid "No"
+msgstr ""
+
 #: src/Module/Notifications/Introductions.php:131
 msgid "Shall your connection be bidirectional or not?"
 msgstr ""
@@ -8647,6 +8628,16 @@ msgstr ""
 msgid "Show all"
 msgstr ""
 
+#: src/Module/OAuth/Acknowledge.php:44
+msgid "Authorize application connection"
+msgstr ""
+
+#: src/Module/OAuth/Acknowledge.php:46
+msgid ""
+"Do you want to authorize this application to access your posts and contacts, "
+"and/or create new posts for you?"
+msgstr ""
+
 #: src/Module/OAuth/Authorize.php:55
 msgid "Unsupported or missing response type"
 msgstr ""