From b86ff1e9700c8ea16f8e87b4445a955b1fd36cfc Mon Sep 17 00:00:00 2001 From: Philipp Date: Thu, 23 Jun 2022 22:56:25 +0200 Subject: [PATCH 1/7] Rename 2FA recovery message --- src/Module/Security/TwoFactor/Verify.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Module/Security/TwoFactor/Verify.php b/src/Module/Security/TwoFactor/Verify.php index c6d1294320..2ef5aaa0e3 100644 --- a/src/Module/Security/TwoFactor/Verify.php +++ b/src/Module/Security/TwoFactor/Verify.php @@ -96,7 +96,7 @@ class Verify extends BaseModule '$message' => DI::l10n()->t('

Open the two-factor authentication app on your device to get an authentication code and verify your identity.

'), '$errors_label' => DI::l10n()->tt('Error', 'Errors', count(self::$errors)), '$errors' => self::$errors, - '$recovery_message' => DI::l10n()->t('Don’t have your phone? Enter a two-factor recovery code', '2fa/recovery'), + '$recovery_message' => DI::l10n()->t('If you do not have access to your authentication code you can use a two-factor recovery code.', '2fa/recovery'), '$verify_code' => ['verify_code', DI::l10n()->t('Please enter a code from your authentication app'), '', '', DI::l10n()->t('Required'), 'autofocus autocomplete="off" placeholder="000000"', 'tel'], '$trust_browser' => ['trust_browser', DI::l10n()->t('This is my two-factor authenticator app device'), !empty($_REQUEST['trust_browser'])], '$verify_label' => DI::l10n()->t('Verify code and complete login'), From 759d9d9f1a68f13bd66594de6f24cb6938cfe599 Mon Sep 17 00:00:00 2001 From: Philipp Date: Thu, 23 Jun 2022 23:29:56 +0200 Subject: [PATCH 2/7] Add more 2fa properties --- src/Module/Security/TwoFactor/Verify.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Module/Security/TwoFactor/Verify.php b/src/Module/Security/TwoFactor/Verify.php index 2ef5aaa0e3..16f146d6de 100644 --- a/src/Module/Security/TwoFactor/Verify.php +++ b/src/Module/Security/TwoFactor/Verify.php @@ -97,7 +97,7 @@ class Verify extends BaseModule '$errors_label' => DI::l10n()->tt('Error', 'Errors', count(self::$errors)), '$errors' => self::$errors, '$recovery_message' => DI::l10n()->t('If you do not have access to your authentication code you can use a two-factor recovery code.', '2fa/recovery'), - '$verify_code' => ['verify_code', DI::l10n()->t('Please enter a code from your authentication app'), '', '', DI::l10n()->t('Required'), 'autofocus autocomplete="off" placeholder="000000"', 'tel'], + '$verify_code' => ['verify_code', DI::l10n()->t('Please enter a code from your authentication app'), '', '', DI::l10n()->t('Required'), 'autofocus autocomplete="one-time-code" placeholder="000000" inputmode="numeric" pattern="[0-9]*"', 'tel'], '$trust_browser' => ['trust_browser', DI::l10n()->t('This is my two-factor authenticator app device'), !empty($_REQUEST['trust_browser'])], '$verify_label' => DI::l10n()->t('Verify code and complete login'), ]); From f3de8d7764fa1fe2511cc5c26ca3c5337016d39f Mon Sep 17 00:00:00 2001 From: Philipp Date: Thu, 23 Jun 2022 23:30:33 +0200 Subject: [PATCH 3/7] improve 2fa token field --- src/Module/Security/TwoFactor/Verify.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Module/Security/TwoFactor/Verify.php b/src/Module/Security/TwoFactor/Verify.php index 16f146d6de..b102823576 100644 --- a/src/Module/Security/TwoFactor/Verify.php +++ b/src/Module/Security/TwoFactor/Verify.php @@ -97,7 +97,7 @@ class Verify extends BaseModule '$errors_label' => DI::l10n()->tt('Error', 'Errors', count(self::$errors)), '$errors' => self::$errors, '$recovery_message' => DI::l10n()->t('If you do not have access to your authentication code you can use a two-factor recovery code.', '2fa/recovery'), - '$verify_code' => ['verify_code', DI::l10n()->t('Please enter a code from your authentication app'), '', '', DI::l10n()->t('Required'), 'autofocus autocomplete="one-time-code" placeholder="000000" inputmode="numeric" pattern="[0-9]*"', 'tel'], + '$verify_code' => ['verify_code', DI::l10n()->t('Please enter a code from your authentication app'), '', '', DI::l10n()->t('Required'), 'autofocus autocomplete="one-time-code" placeholder="000000" inputmode="numeric" pattern="[0-9]*"'], '$trust_browser' => ['trust_browser', DI::l10n()->t('This is my two-factor authenticator app device'), !empty($_REQUEST['trust_browser'])], '$verify_label' => DI::l10n()->t('Verify code and complete login'), ]); From 0223c030a9e7918c055d382ebea44003de289b0f Mon Sep 17 00:00:00 2001 From: Philipp Date: Sat, 25 Jun 2022 14:45:33 +0200 Subject: [PATCH 4/7] Improve 2 factor usage --- database.sql | 3 +- doc/database/db_2fa_trusted_browser.md | 15 +- src/Model/User/Cookie.php | 17 ++- src/Module/Security/Logout.php | 18 +-- src/Module/Security/TwoFactor/Signout.php | 129 ++++++++++++++++++ src/Module/Security/TwoFactor/Trust.php | 126 +++++++++++++++++ src/Module/Security/TwoFactor/Verify.php | 76 +++++------ src/Module/Settings/TwoFactor/Index.php | 5 +- src/Module/Settings/TwoFactor/Trusted.php | 4 +- src/Security/Authentication.php | 19 ++- .../TwoFactor/Factory/TrustedBrowser.php | 4 +- .../TwoFactor/Model/TrustedBrowser.php | 14 +- static/dbstructure.config.php | 3 +- static/routes.config.php | 2 + .../TwoFactor/Factory/TrustedBrowserTest.php | 5 +- .../TwoFactor/Model/TrustedBrowserTest.php | 3 + .../settings/twofactor/trusted_browsers.tpl | 4 + view/templates/twofactor/signout.tpl | 14 ++ view/templates/twofactor/trust.tpl | 14 ++ view/templates/twofactor/verify.tpl | 2 - 20 files changed, 400 insertions(+), 77 deletions(-) create mode 100644 src/Module/Security/TwoFactor/Signout.php create mode 100644 src/Module/Security/TwoFactor/Trust.php create mode 100644 view/templates/twofactor/signout.tpl create mode 100644 view/templates/twofactor/trust.tpl diff --git a/database.sql b/database.sql index 10b18d4cae..01bd84b00b 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2022.09-dev (Giant Rhubarb) --- DB_UPDATE_VERSION 1472 +-- DB_UPDATE_VERSION 1473 -- ------------------------------------------ @@ -297,6 +297,7 @@ CREATE TABLE IF NOT EXISTS `2fa_trusted_browser` ( `cookie_hash` varchar(80) NOT NULL COMMENT 'Trusted cookie hash', `uid` mediumint unsigned NOT NULL COMMENT 'User ID', `user_agent` text COMMENT 'User agent string', + `trusted` boolean NOT NULL DEFAULT '1' COMMENT 'Whenever this browser should be trusted or not', `created` datetime NOT NULL COMMENT 'Datetime the trusted browser was recorded', `last_used` datetime COMMENT 'Datetime the trusted browser was last used', PRIMARY KEY(`cookie_hash`), diff --git a/doc/database/db_2fa_trusted_browser.md b/doc/database/db_2fa_trusted_browser.md index d12d9e1fc0..18126b49fc 100644 --- a/doc/database/db_2fa_trusted_browser.md +++ b/doc/database/db_2fa_trusted_browser.md @@ -6,13 +6,14 @@ Two-factor authentication trusted browsers Fields ------ -| Field | Description | Type | Null | Key | Default | Extra | -| ----------- | ------------------------------------------ | ------------------ | ---- | --- | ------- | ----- | -| cookie_hash | Trusted cookie hash | varchar(80) | NO | PRI | NULL | | -| uid | User ID | mediumint unsigned | NO | | NULL | | -| user_agent | User agent string | text | YES | | NULL | | -| created | Datetime the trusted browser was recorded | datetime | NO | | NULL | | -| last_used | Datetime the trusted browser was last used | datetime | YES | | NULL | | +| Field | Description | Type | Null | Key | Default | Extra | +| ----------- | ---------------------------------------------- | ------------------ | ---- | --- | ------- | ----- | +| cookie_hash | Trusted cookie hash | varchar(80) | NO | PRI | NULL | | +| uid | User ID | mediumint unsigned | NO | | NULL | | +| user_agent | User agent string | text | YES | | NULL | | +| trusted | Whenever this browser should be trusted or not | boolean | NO | | 1 | | +| created | Datetime the trusted browser was recorded | datetime | NO | | NULL | | +| last_used | Datetime the trusted browser was last used | datetime | YES | | NULL | | Indexes ------------ diff --git a/src/Model/User/Cookie.php b/src/Model/User/Cookie.php index aabb028209..4359d21071 100644 --- a/src/Model/User/Cookie.php +++ b/src/Model/User/Cookie.php @@ -124,6 +124,19 @@ class Cookie } } + /** + * Resets the cookie to a given data set + * + * @param array $data + * + * @return bool + */ + public function reset(array $data): bool + { + return $this->clear() && + $this->setMultiple($data); + } + /** * Clears the Friendica cookie */ @@ -131,7 +144,7 @@ class Cookie { $this->data = []; // make sure cookie is deleted on browser close, as a security measure - return $this->setCookie( '', -3600, $this->sslEnabled); + return $this->setCookie('', -3600, $this->sslEnabled); } /** @@ -161,7 +174,7 @@ class Cookie * */ protected function setCookie(string $value = null, int $expire = null, - bool $secure = null): bool + bool $secure = null): bool { return setcookie(self::NAME, $value, $expire, self::PATH, self::DOMAIN, $secure, self::HTTPONLY); } diff --git a/src/Module/Security/Logout.php b/src/Module/Security/Logout.php index 1ec0764834..004292cb5c 100644 --- a/src/Module/Security/Logout.php +++ b/src/Module/Security/Logout.php @@ -31,7 +31,6 @@ use Friendica\Core\System; use Friendica\Model\Profile; use Friendica\Model\User\Cookie; use Friendica\Module\Response; -use Friendica\Security\TwoFactor; use Friendica\Util\Profiler; use Psr\Log\LoggerInterface; @@ -46,17 +45,14 @@ class Logout extends BaseModule protected $cookie; /** @var IHandleSessions */ protected $session; - /** @var TwoFactor\Repository\TrustedBrowser */ - protected $trustedBrowserRepo; - public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, TwoFactor\Repository\TrustedBrowser $trustedBrowserRepo, ICanCache $cache, Cookie $cookie, IHandleSessions $session, array $server, array $parameters = []) + public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, ICanCache $cache, Cookie $cookie, IHandleSessions $session, array $server, array $parameters = []) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); - $this->cache = $cache; - $this->cookie = $cookie; - $this->session = $session; - $this->trustedBrowserRepo = $trustedBrowserRepo; + $this->cache = $cache; + $this->cookie = $cookie; + $this->session = $session; } @@ -73,9 +69,9 @@ class Logout extends BaseModule Hook::callAll("logging_out"); - // Remove this trusted browser as it won't be able to be used ever again after the cookie is cleared - if ($this->cookie->get('trusted')) { - $this->trustedBrowserRepo->removeForUser(local_user(), $this->cookie->get('trusted')); + // If this is a trusted browser, redirect to the 2fa signout page + if ($this->cookie->get('2fa_cookie_hash')) { + $this->baseUrl->redirect('2fa/signout'); } $this->cookie->clear(); diff --git a/src/Module/Security/TwoFactor/Signout.php b/src/Module/Security/TwoFactor/Signout.php new file mode 100644 index 0000000000..3e52b27e71 --- /dev/null +++ b/src/Module/Security/TwoFactor/Signout.php @@ -0,0 +1,129 @@ +. + * + */ + +namespace Friendica\Module\Security\TwoFactor; + +use Friendica\App; +use Friendica\BaseModule; +use Friendica\Core\L10n; +use Friendica\Core\Renderer; +use Friendica\Core\Session\Capability\IHandleSessions; +use Friendica\Model\User\Cookie; +use Friendica\Module\Response; +use Friendica\Network\HTTPException\NotFoundException; +use Friendica\Util\Profiler; +use Friendica\Security\TwoFactor; +use Psr\Log\LoggerInterface; + +/** + * Page 4: Logout dialog for trusted browsers + * + * @package Friendica\Module\TwoFactor + */ +class Signout extends BaseModule +{ + protected $errors = []; + + /** @var IHandleSessions */ + protected $session; + /** @var Cookie */ + protected $cookie; + /** @var TwoFactor\Repository\TrustedBrowser */ + protected $trustedBrowserRepositoy; + + public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, IHandleSessions $session, Cookie $cookie, TwoFactor\Repository\TrustedBrowser $trustedBrowserRepositoy, Profiler $profiler, Response $response, array $server, array $parameters = []) + { + parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); + + $this->session = $session; + $this->cookie = $cookie; + $this->trustedBrowserRepositoy = $trustedBrowserRepositoy; + } + + protected function post(array $request = []) + { + if (!local_user() || !($this->cookie->get('2fa_cookie_hash'))) { + return; + } + + $action = $request['action'] ?? ''; + + if (!empty($action)) { + self::checkFormSecurityTokenRedirectOnError('2fa', 'twofactor_signout'); + + switch ($action) { + case 'trust_and_sign_out': + $trusted = $this->cookie->get('2fa_cookie_hash'); + $this->cookie->reset(['2fa_cookie_hash' => $trusted]); + $this->session->clear(); + + info($this->t('Logged out.')); + $this->baseUrl->redirect(); + break; + case 'sign_out': + $this->trustedBrowserRepositoy->removeForUser(local_user(), $this->cookie->get('2fa_cookie_hash')); + $this->cookie->clear(); + $this->session->clear(); + + info($this->t('Logged out.')); + $this->baseUrl->redirect(); + break; + default: + $this->baseUrl->redirect(); + } + } + } + + protected function content(array $request = []): string + { + if (!local_user() || !($this->cookie->get('2fa_cookie_hash'))) { + $this->baseUrl->redirect(); + } + + try { + $trustedBrowser = $this->trustedBrowserRepositoy->selectOneByHash($this->cookie->get('2fa_cookie_hash')); + if (!$trustedBrowser->trusted) { + $trusted = $this->cookie->get('2fa_cookie_hash'); + $this->cookie->reset(['2fa_cookie_hash' => $trusted]); + $this->session->clear(); + + info($this->t('Logged out.')); + $this->baseUrl->redirect(); + } + } catch (NotFoundException $exception) { + $this->cookie->clear(); + $this->session->clear(); + + info($this->t('Logged out.')); + $this->baseUrl->redirect(); + } + + return Renderer::replaceMacros(Renderer::getMarkupTemplate('twofactor/signout.tpl'), [ + '$form_security_token' => self::getFormSecurityToken('twofactor_signout'), + + '$title' => $this->t('Sign out of this browser?'), + '$message' => $this->t('

If you trust this browser, you will not be asked for verification code the next time you sign in.

'), + '$sign_out_label' => $this->t('Sign out'), + '$cancel_label' => $this->t('Cancel'), + '$trust_and_sign_out_label' => $this->t('Trust and sign out'), + ]); + } +} diff --git a/src/Module/Security/TwoFactor/Trust.php b/src/Module/Security/TwoFactor/Trust.php new file mode 100644 index 0000000000..a245e6be56 --- /dev/null +++ b/src/Module/Security/TwoFactor/Trust.php @@ -0,0 +1,126 @@ +. + * + */ + +namespace Friendica\Module\Security\TwoFactor; + +use Friendica\App; +use Friendica\BaseModule; +use Friendica\Core\L10n; +use Friendica\Core\Renderer; +use Friendica\Core\Session\Capability\IHandleSessions; +use Friendica\Model\User; +use Friendica\Model\User\Cookie; +use Friendica\Module\Response; +use Friendica\Network\HTTPException\NotFoundException; +use Friendica\Security\Authentication; +use Friendica\Util\Profiler; +use Friendica\Security\TwoFactor; +use Psr\Log\LoggerInterface; + +/** + * Page 2: Trust Browser dialog + * + * @package Friendica\Module\TwoFactor + */ +class Trust extends BaseModule +{ + /** @var App */ + protected $app; + /** @var Authentication */ + protected $auth; + /** @var IHandleSessions */ + protected $session; + /** @var Cookie */ + protected $cookie; + /** @var TwoFactor\Factory\TrustedBrowser */ + protected $trustedBrowserFactory; + /** @var TwoFactor\Repository\TrustedBrowser */ + protected $trustedBrowserRepositoy; + + public function __construct(App $app, Authentication $auth, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, IHandleSessions $session, Cookie $cookie, TwoFactor\Factory\TrustedBrowser $trustedBrowserFactory, TwoFactor\Repository\TrustedBrowser $trustedBrowserRepositoy, Response $response, array $server, array $parameters = []) + { + parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); + + $this->app = $app; + $this->auth = $auth; + $this->session = $session; + $this->cookie = $cookie; + $this->trustedBrowserFactory = $trustedBrowserFactory; + $this->trustedBrowserRepositoy = $trustedBrowserRepositoy; + } + + protected function post(array $request = []) + { + if (!local_user() || !$this->session->get('2fa')) { + return; + } + + $action = $request['action'] ?? ''; + + if (!empty($action)) { + self::checkFormSecurityTokenRedirectOnError('2fa', 'twofactor_trust'); + + switch ($action) { + case 'trust': + case 'dont_trust': + $trustedBrowser = $this->trustedBrowserFactory->createForUserWithUserAgent(local_user(), $this->server['HTTP_USER_AGENT'], $action === 'trust'); + $this->trustedBrowserRepositoy->save($trustedBrowser); + + // The string is sent to the browser to be sent back with each request + if (!$this->cookie->set('2fa_cookie_hash', $trustedBrowser->cookie_hash)) { + notice($this->t('Couldn\'t save browser to Cookie.')); + }; + break; + } + + $this->auth->setForUser($this->app, User::getById($this->app->getLoggedInUserId()), true, true); + } + } + + protected function content(array $request = []): string + { + if (!local_user() || !$this->session->get('2fa')) { + $this->baseUrl->redirect(); + } + + if ($this->cookie->get('2fa_cookie_hash')) { + try { + $trustedBrowser = $this->trustedBrowserRepositoy->selectOneByHash($this->cookie->get('2fa_cookie_hash')); + if (!$trustedBrowser->trusted) { + $this->auth->setForUser($this->app, User::getById($this->app->getLoggedInUserId()), true, true); + $this->baseUrl->redirect(); + } + } catch (NotFoundException $exception) { + $this->logger->notice('Trusted Browser of the cookie not found.', ['cookie_hash' => $this->cookie->get('trusted'), 'uid' => $this->app->getLoggedInUserId(), 'exception' => $exception]); + } + } + + return Renderer::replaceMacros(Renderer::getMarkupTemplate('twofactor/trust.tpl'), [ + '$form_security_token' => self::getFormSecurityToken('twofactor_trust'), + + '$title' => $this->t('Trust this browser?'), + '$message' => $this->t('

If you choose to trust this browser, you will not be asked for a verification code the next time you sign in.

'), + '$not_now_label' => $this->t('Not now'), + '$dont_trust_label' => $this->t('Don\'t trust'), + '$trust_label' => $this->t('Trust'), + ]); + } +} diff --git a/src/Module/Security/TwoFactor/Verify.php b/src/Module/Security/TwoFactor/Verify.php index b102823576..d0850aedcb 100644 --- a/src/Module/Security/TwoFactor/Verify.php +++ b/src/Module/Security/TwoFactor/Verify.php @@ -21,13 +21,17 @@ namespace Friendica\Module\Security\TwoFactor; +use Friendica\App; use Friendica\BaseModule; +use Friendica\Core\L10n; +use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues; use Friendica\Core\Renderer; -use Friendica\Core\Session; -use Friendica\DI; -use Friendica\Model\User; +use Friendica\Core\Session\Capability\IHandleSessions; +use Friendica\Module\Response; +use Friendica\Util\Profiler; use PragmaRX\Google2FA\Google2FA; use Friendica\Security\TwoFactor; +use Psr\Log\LoggerInterface; /** * Page 1: Authenticator code verification @@ -36,7 +40,20 @@ use Friendica\Security\TwoFactor; */ class Verify extends BaseModule { - private static $errors = []; + protected $errors = []; + + /** @var IHandleSessions */ + protected $session; + /** @var IManagePersonalConfigValues */ + protected $pConfig; + + public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IManagePersonalConfigValues $pConfig, IHandleSessions $session, array $server, array $parameters = []) + { + parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); + + $this->session = $session; + $this->pConfig = $pConfig; + } protected function post(array $request = []) { @@ -44,36 +61,20 @@ class Verify extends BaseModule return; } - if (($_POST['action'] ?? '') == 'verify') { + if (($request['action'] ?? '') === 'verify') { self::checkFormSecurityTokenRedirectOnError('2fa', 'twofactor_verify'); - $a = DI::app(); + $code = $request['verify_code'] ?? ''; - $code = $_POST['verify_code'] ?? ''; - - $valid = (new Google2FA())->verifyKey(DI::pConfig()->get(local_user(), '2fa', 'secret'), $code); + $valid = (new Google2FA())->verifyKey($this->pConfig->get(local_user(), '2fa', 'secret'), $code); // The same code can't be used twice even if it's valid - if ($valid && Session::get('2fa') !== $code) { - Session::set('2fa', $code); + if ($valid && $this->session->get('2fa') !== $code) { + $this->session->set('2fa', $code); - // Trust this browser feature - if (!empty($_REQUEST['trust_browser'])) { - $trustedBrowserFactory = new TwoFactor\Factory\TrustedBrowser(DI::logger()); - $trustedBrowserRepository = new TwoFactor\Repository\TrustedBrowser(DI::dba(), DI::logger(), $trustedBrowserFactory); - - $trustedBrowser = $trustedBrowserFactory->createForUserWithUserAgent(local_user(), $_SERVER['HTTP_USER_AGENT']); - - $trustedBrowserRepository->save($trustedBrowser); - - // The string is sent to the browser to be sent back with each request - DI::cookie()->set('trusted', $trustedBrowser->cookie_hash); - } - - // Resume normal login workflow - DI::auth()->setForUser($a, User::getById($a->getLoggedInUserId()), true, true); + $this->baseUrl->redirect('2fa/trust'); } else { - self::$errors[] = DI::l10n()->t('Invalid code, please retry.'); + $this->errors[] = $this->t('Invalid code, please retry.'); } } } @@ -81,25 +82,24 @@ class Verify extends BaseModule protected function content(array $request = []): string { if (!local_user()) { - DI::baseUrl()->redirect(); + $this->baseUrl->redirect(); } // Already authenticated with 2FA token - if (Session::get('2fa')) { - DI::baseUrl()->redirect(); + if ($this->session->get('2fa')) { + $this->baseUrl->redirect(); } return Renderer::replaceMacros(Renderer::getMarkupTemplate('twofactor/verify.tpl'), [ '$form_security_token' => self::getFormSecurityToken('twofactor_verify'), - '$title' => DI::l10n()->t('Two-factor authentication'), - '$message' => DI::l10n()->t('

Open the two-factor authentication app on your device to get an authentication code and verify your identity.

'), - '$errors_label' => DI::l10n()->tt('Error', 'Errors', count(self::$errors)), - '$errors' => self::$errors, - '$recovery_message' => DI::l10n()->t('If you do not have access to your authentication code you can use a two-factor recovery code.', '2fa/recovery'), - '$verify_code' => ['verify_code', DI::l10n()->t('Please enter a code from your authentication app'), '', '', DI::l10n()->t('Required'), 'autofocus autocomplete="one-time-code" placeholder="000000" inputmode="numeric" pattern="[0-9]*"'], - '$trust_browser' => ['trust_browser', DI::l10n()->t('This is my two-factor authenticator app device'), !empty($_REQUEST['trust_browser'])], - '$verify_label' => DI::l10n()->t('Verify code and complete login'), + '$title' => $this->t('Two-factor authentication'), + '$message' => $this->t('

Open the two-factor authentication app on your device to get an authentication code and verify your identity.

'), + '$errors_label' => $this->tt('Error', 'Errors', count($this->errors)), + '$errors' => $this->errors, + '$recovery_message' => $this->t('If you do not have access to your authentication code you can use a two-factor recovery code.', '2fa/recovery'), + '$verify_code' => ['verify_code', $this->t('Please enter a code from your authentication app'), '', '', $this->t('Required'), 'autofocus autocomplete="one-time-code" placeholder="000000" inputmode="numeric" pattern="[0-9]*"'], + '$verify_label' => $this->t('Verify code and complete login'), ]); } } diff --git a/src/Module/Settings/TwoFactor/Index.php b/src/Module/Settings/TwoFactor/Index.php index 35c5d3cf9c..98826824b9 100644 --- a/src/Module/Settings/TwoFactor/Index.php +++ b/src/Module/Settings/TwoFactor/Index.php @@ -24,6 +24,7 @@ namespace Friendica\Module\Settings\TwoFactor; use Friendica\Core\Renderer; use Friendica\Core\Session; use Friendica\DI; +use Friendica\Network\HTTPException\FoundException; use Friendica\Security\TwoFactor\Model\AppSpecificPassword; use Friendica\Security\TwoFactor\Model\RecoveryCode; use Friendica\Model\User; @@ -90,7 +91,9 @@ class Index extends BaseSettings break; } } catch (\Exception $e) { - notice(DI::l10n()->t('Wrong Password')); + if (!($e instanceof FoundException)) { + notice(DI::l10n()->t($e->getMessage())); + } } } diff --git a/src/Module/Settings/TwoFactor/Trusted.php b/src/Module/Settings/TwoFactor/Trusted.php index 12327a5918..d1c0476de5 100644 --- a/src/Module/Settings/TwoFactor/Trusted.php +++ b/src/Module/Settings/TwoFactor/Trusted.php @@ -121,6 +121,7 @@ class Trusted extends BaseSettings 'os' => $result->os->family, 'device' => $result->device->family, 'browser' => $result->ua->family, + 'trusted_labeled' => $trustedBrowser->trusted ? $this->t('Yes') : $this->t('No'), ]; return $trustedBrowser->toArray() + $dates + $uaData; @@ -135,7 +136,8 @@ class Trusted extends BaseSettings '$device_label' => $this->t('Device'), '$os_label' => $this->t('OS'), '$browser_label' => $this->t('Browser'), - '$created_label' => $this->t('Trusted'), + '$trusted_label' => $this->t('Trusted'), + '$created_label' => $this->t('Created At'), '$last_used_label' => $this->t('Last Use'), '$remove_label' => $this->t('Remove'), '$remove_all_label' => $this->t('Remove All'), diff --git a/src/Security/Authentication.php b/src/Security/Authentication.php index aca4f2c23e..a23d0c9557 100644 --- a/src/Security/Authentication.php +++ b/src/Security/Authentication.php @@ -144,7 +144,7 @@ class Authentication // Renew the cookie $this->cookie->send(); - // Do the authentification if not done by now + // Do the authentication if not done by now if (!$this->session->get('authenticated')) { $this->setForUser($a, $user); @@ -269,7 +269,11 @@ class Authentication } if (!$remember) { + $trusted = $this->cookie->get('2fa_cookie_hash') ?? null; $this->cookie->clear(); + if ($trusted) { + $this->cookie->set('2fa_cookie_hash', $trusted); + } } // if we haven't failed up this point, log them in. @@ -407,11 +411,11 @@ class Authentication } // Case 1b: Check for trusted browser - if ($this->cookie->get('trusted')) { + if ($this->cookie->get('2fa_cookie_hash')) { // Retrieve a trusted_browser model based on cookie hash $trustedBrowserRepository = new TrustedBrowser($this->dba, $this->logger); try { - $trustedBrowser = $trustedBrowserRepository->selectOneByHash($this->cookie->get('trusted')); + $trustedBrowser = $trustedBrowserRepository->selectOneByHash($this->cookie->get('2fa_cookie_hash')); // Verify record ownership if ($trustedBrowser->uid === $uid) { // Update last_used date @@ -420,10 +424,13 @@ class Authentication // Save it to the database $trustedBrowserRepository->save($trustedBrowser); - // Set 2fa session key and return - $this->session->set('2fa', true); + // Only use this entry, if its really trusted, otherwise just update the record and proceed + if ($trustedBrowser->trusted) { + // Set 2fa session key and return + $this->session->set('2fa', true); - return; + return; + } } else { // Invalid trusted cookie value, removing it $this->cookie->unset('trusted'); diff --git a/src/Security/TwoFactor/Factory/TrustedBrowser.php b/src/Security/TwoFactor/Factory/TrustedBrowser.php index 61ec154fcc..21961f7ef3 100644 --- a/src/Security/TwoFactor/Factory/TrustedBrowser.php +++ b/src/Security/TwoFactor/Factory/TrustedBrowser.php @@ -27,7 +27,7 @@ use Friendica\Util\Strings; class TrustedBrowser extends BaseFactory { - public function createForUserWithUserAgent($uid, $userAgent): \Friendica\Security\TwoFactor\Model\TrustedBrowser + public function createForUserWithUserAgent(int $uid, string $userAgent, bool $trusted): \Friendica\Security\TwoFactor\Model\TrustedBrowser { $trustedHash = Strings::getRandomHex(); @@ -35,6 +35,7 @@ class TrustedBrowser extends BaseFactory $trustedHash, $uid, $userAgent, + $trusted, DateTimeFormat::utcNow() ); } @@ -45,6 +46,7 @@ class TrustedBrowser extends BaseFactory $row['cookie_hash'], $row['uid'], $row['user_agent'], + $row['trusted'], $row['created'], $row['last_used'] ); diff --git a/src/Security/TwoFactor/Model/TrustedBrowser.php b/src/Security/TwoFactor/Model/TrustedBrowser.php index d0a654d5f2..cd9d2007e6 100644 --- a/src/Security/TwoFactor/Model/TrustedBrowser.php +++ b/src/Security/TwoFactor/Model/TrustedBrowser.php @@ -31,6 +31,7 @@ use Friendica\Util\DateTimeFormat; * @property-read $cookie_hash * @property-read $uid * @property-read $user_agent + * @property-read $trusted * @property-read $created * @property-read $last_used * @package Friendica\Model\TwoFactor @@ -40,6 +41,7 @@ class TrustedBrowser extends BaseEntity protected $cookie_hash; protected $uid; protected $user_agent; + protected $trusted; protected $created; protected $last_used; @@ -51,16 +53,18 @@ class TrustedBrowser extends BaseEntity * @param string $cookie_hash * @param int $uid * @param string $user_agent + * @param bool $trusted * @param string $created * @param string|null $last_used */ - public function __construct(string $cookie_hash, int $uid, string $user_agent, string $created, string $last_used = null) + public function __construct(string $cookie_hash, int $uid, string $user_agent, bool $trusted, string $created, string $last_used = null) { $this->cookie_hash = $cookie_hash; - $this->uid = $uid; - $this->user_agent = $user_agent; - $this->created = $created; - $this->last_used = $last_used; + $this->uid = $uid; + $this->user_agent = $user_agent; + $this->trusted = $trusted; + $this->created = $created; + $this->last_used = $last_used; } public function recordUse() diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index c48da6a09a..758c33d0da 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -55,7 +55,7 @@ use Friendica\Database\DBA; if (!defined('DB_UPDATE_VERSION')) { - define('DB_UPDATE_VERSION', 1472); + define('DB_UPDATE_VERSION', 1473); } return [ @@ -358,6 +358,7 @@ return [ "cookie_hash" => ["type" => "varchar(80)", "not null" => "1", "primary" => "1", "comment" => "Trusted cookie hash"], "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "User ID"], "user_agent" => ["type" => "text", "comment" => "User agent string"], + "trusted" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => "Whenever this browser should be trusted or not"], "created" => ["type" => "datetime", "not null" => "1", "comment" => "Datetime the trusted browser was recorded"], "last_used" => ["type" => "datetime", "comment" => "Datetime the trusted browser was last used"], ], diff --git a/static/routes.config.php b/static/routes.config.php index 72964d2308..9c82c8e1f1 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -165,6 +165,8 @@ return [ '/2fa' => [ '[/]' => [Module\Security\TwoFactor\Verify::class, [R::GET, R::POST]], '/recovery' => [Module\Security\TwoFactor\Recovery::class, [R::GET, R::POST]], + '/trust' => [Module\Security\TwoFactor\Trust::class, [R::GET, R::POST]], + '/signout' => [Module\Security\TwoFactor\Signout::class, [R::GET, R::POST]], ], '/api' => [ diff --git a/tests/src/Security/TwoFactor/Factory/TrustedBrowserTest.php b/tests/src/Security/TwoFactor/Factory/TrustedBrowserTest.php index 84a118eb80..baddfb3791 100644 --- a/tests/src/Security/TwoFactor/Factory/TrustedBrowserTest.php +++ b/tests/src/Security/TwoFactor/Factory/TrustedBrowserTest.php @@ -38,6 +38,7 @@ class TrustedBrowserTest extends MockedTest 'uid' => 42, 'user_agent' => 'PHPUnit', 'created' => DateTimeFormat::utcNow(), + 'trusted' => true, 'last_used' => null, ]; @@ -57,6 +58,7 @@ class TrustedBrowserTest extends MockedTest 'uid' => null, 'user_agent' => null, 'created' => null, + 'trusted' => true, 'last_used' => null, ]; @@ -72,11 +74,12 @@ class TrustedBrowserTest extends MockedTest $uid = 42; $userAgent = 'PHPUnit'; - $trustedBrowser = $factory->createForUserWithUserAgent($uid, $userAgent); + $trustedBrowser = $factory->createForUserWithUserAgent($uid, $userAgent, true); $this->assertNotEmpty($trustedBrowser->cookie_hash); $this->assertEquals($uid, $trustedBrowser->uid); $this->assertEquals($userAgent, $trustedBrowser->user_agent); + $this->assertTrue($trustedBrowser->trusted); $this->assertNotEmpty($trustedBrowser->created); } } diff --git a/tests/src/Security/TwoFactor/Model/TrustedBrowserTest.php b/tests/src/Security/TwoFactor/Model/TrustedBrowserTest.php index 0c91ea5e5e..cf5db0ffd8 100644 --- a/tests/src/Security/TwoFactor/Model/TrustedBrowserTest.php +++ b/tests/src/Security/TwoFactor/Model/TrustedBrowserTest.php @@ -36,12 +36,14 @@ class TrustedBrowserTest extends MockedTest $hash, 42, 'PHPUnit', + true, DateTimeFormat::utcNow() ); $this->assertEquals($hash, $trustedBrowser->cookie_hash); $this->assertEquals(42, $trustedBrowser->uid); $this->assertEquals('PHPUnit', $trustedBrowser->user_agent); + $this->assertTrue($trustedBrowser->trusted); $this->assertNotEmpty($trustedBrowser->created); } @@ -54,6 +56,7 @@ class TrustedBrowserTest extends MockedTest $hash, 42, 'PHPUnit', + true, $past, $past ); diff --git a/view/templates/settings/twofactor/trusted_browsers.tpl b/view/templates/settings/twofactor/trusted_browsers.tpl index 29d2ab29c6..1a9ae91fe5 100644 --- a/view/templates/settings/twofactor/trusted_browsers.tpl +++ b/view/templates/settings/twofactor/trusted_browsers.tpl @@ -10,6 +10,7 @@ {{$device_label}} {{$os_label}} {{$browser_label}} + {{$trusted_label}} {{$created_label}} {{$last_used_label}} @@ -28,6 +29,9 @@ {{$trusted_browser.browser}} + {{$trusted_browser.trusted_labeled}} + + diff --git a/view/templates/twofactor/signout.tpl b/view/templates/twofactor/signout.tpl new file mode 100644 index 0000000000..f2a211102e --- /dev/null +++ b/view/templates/twofactor/signout.tpl @@ -0,0 +1,14 @@ +
+

{{$title}}

+
{{$message nofilter}}
+ +
+ + +
+ + + +
+
+
diff --git a/view/templates/twofactor/trust.tpl b/view/templates/twofactor/trust.tpl new file mode 100644 index 0000000000..6bfe307d5e --- /dev/null +++ b/view/templates/twofactor/trust.tpl @@ -0,0 +1,14 @@ +
+

{{$title}}

+
{{$message nofilter}}
+ +
+ + +
+ + + +
+
+
diff --git a/view/templates/twofactor/verify.tpl b/view/templates/twofactor/verify.tpl index 938f98da09..2b1fe31421 100644 --- a/view/templates/twofactor/verify.tpl +++ b/view/templates/twofactor/verify.tpl @@ -18,8 +18,6 @@ {{include file="field_input.tpl" field=$verify_code}} - {{include file="field_checkbox.tpl" field=$trust_browser}} -
From 123c1165916cabed07152d3e3a73ba9870b4c2f2 Mon Sep 17 00:00:00 2001 From: Philipp Date: Sat, 25 Jun 2022 22:37:50 +0200 Subject: [PATCH 5/7] Update messages.po --- view/lang/C/messages.po | 1099 ++++++++++++++++++++------------------- 1 file changed, 576 insertions(+), 523 deletions(-) diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index 333a0aaa66..3a29f77684 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2022.09-dev\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-06-13 05:45+0000\n" +"POT-Creation-Date: 2022-06-25 22:37+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -28,7 +28,7 @@ msgid "Access denied." msgstr "" #: mod/cal.php:63 mod/cal.php:80 mod/photos.php:69 mod/photos.php:140 -#: mod/photos.php:798 src/Model/Profile.php:231 src/Module/Feed.php:72 +#: mod/photos.php:798 src/Model/Profile.php:232 src/Module/Feed.php:72 #: src/Module/HCard.php:52 src/Module/Profile/Common.php:41 #: src/Module/Profile/Common.php:52 src/Module/Profile/Contacts.php:40 #: src/Module/Profile/Contacts.php:50 src/Module/Profile/Media.php:38 @@ -62,21 +62,21 @@ msgstr "" msgid "Next" msgstr "" -#: mod/cal.php:249 mod/events.php:383 src/Model/Event.php:457 +#: mod/cal.php:249 mod/events.php:383 src/Model/Event.php:456 msgid "today" msgstr "" -#: mod/cal.php:250 mod/events.php:384 src/Model/Event.php:458 +#: mod/cal.php:250 mod/events.php:384 src/Model/Event.php:457 #: src/Util/Temporal.php:334 msgid "month" msgstr "" -#: mod/cal.php:251 mod/events.php:385 src/Model/Event.php:459 +#: mod/cal.php:251 mod/events.php:385 src/Model/Event.php:458 #: src/Util/Temporal.php:335 msgid "week" msgstr "" -#: mod/cal.php:252 mod/events.php:386 src/Model/Event.php:460 +#: mod/cal.php:252 mod/events.php:386 src/Model/Event.php:459 #: src/Util/Temporal.php:336 msgid "day" msgstr "" @@ -106,7 +106,7 @@ msgstr "" #: mod/display.php:143 mod/photos.php:802 #: src/Module/Conversation/Community.php:175 src/Module/Directory.php:49 -#: src/Module/Search/Index.php:50 +#: src/Module/Search/Index.php:65 msgid "Public access denied." msgstr "" @@ -159,13 +159,13 @@ msgstr "" msgid "Edit post" msgstr "" -#: mod/editpost.php:91 mod/notes.php:56 src/Content/Text/HTML.php:875 +#: mod/editpost.php:91 mod/notes.php:56 src/Content/Text/HTML.php:882 #: src/Module/Admin/Storage.php:142 src/Module/Filer/SaveTag.php:73 msgid "Save" msgstr "" #: mod/editpost.php:92 mod/photos.php:1338 src/Content/Conversation.php:338 -#: src/Module/Contact/Poke.php:176 src/Object/Post.php:989 +#: src/Module/Contact/Poke.php:176 src/Object/Post.php:993 msgid "Loading..." msgstr "" @@ -231,7 +231,7 @@ msgstr "" #: mod/editpost.php:107 mod/message.php:200 mod/message.php:358 #: mod/photos.php:1489 mod/wallmessage.php:142 src/Content/Conversation.php:368 #: src/Content/Conversation.php:713 src/Module/Item/Compose.php:177 -#: src/Object/Post.php:528 +#: src/Object/Post.php:538 msgid "Please wait" msgstr "" @@ -263,7 +263,7 @@ msgstr "" #: mod/editpost.php:128 mod/events.php:513 mod/photos.php:1337 #: mod/photos.php:1393 mod/photos.php:1467 src/Content/Conversation.php:383 -#: src/Module/Item/Compose.php:172 src/Object/Post.php:999 +#: src/Module/Item/Compose.php:172 src/Object/Post.php:1003 msgid "Preview" msgstr "" @@ -271,52 +271,53 @@ msgstr "" #: mod/follow.php:144 mod/photos.php:1004 mod/photos.php:1105 mod/tagrm.php:35 #: mod/tagrm.php:127 mod/unfollow.php:97 src/Content/Conversation.php:386 #: src/Module/Contact/Revoke.php:108 src/Module/RemoteFollow.php:127 +#: src/Module/Security/TwoFactor/Signout.php:125 msgid "Cancel" msgstr "" #: mod/editpost.php:134 src/Content/Conversation.php:343 -#: src/Module/Item/Compose.php:163 src/Object/Post.php:990 +#: src/Module/Item/Compose.php:163 src/Object/Post.php:994 msgid "Bold" msgstr "" #: mod/editpost.php:135 src/Content/Conversation.php:344 -#: src/Module/Item/Compose.php:164 src/Object/Post.php:991 +#: src/Module/Item/Compose.php:164 src/Object/Post.php:995 msgid "Italic" msgstr "" #: mod/editpost.php:136 src/Content/Conversation.php:345 -#: src/Module/Item/Compose.php:165 src/Object/Post.php:992 +#: src/Module/Item/Compose.php:165 src/Object/Post.php:996 msgid "Underline" msgstr "" #: mod/editpost.php:137 src/Content/Conversation.php:346 -#: src/Module/Item/Compose.php:166 src/Object/Post.php:993 +#: src/Module/Item/Compose.php:166 src/Object/Post.php:997 msgid "Quote" msgstr "" #: mod/editpost.php:138 src/Content/Conversation.php:347 -#: src/Module/Item/Compose.php:167 src/Object/Post.php:994 +#: src/Module/Item/Compose.php:167 src/Object/Post.php:998 msgid "Code" msgstr "" #: mod/editpost.php:139 src/Content/Conversation.php:349 -#: src/Module/Item/Compose.php:169 src/Object/Post.php:996 +#: src/Module/Item/Compose.php:169 src/Object/Post.php:1000 msgid "Link" msgstr "" #: mod/editpost.php:140 src/Content/Conversation.php:350 -#: src/Module/Item/Compose.php:170 src/Object/Post.php:997 +#: src/Module/Item/Compose.php:170 src/Object/Post.php:1001 msgid "Link or Media" msgstr "" #: mod/editpost.php:143 src/Content/Conversation.php:393 -#: src/Content/Widget/VCard.php:113 src/Model/Profile.php:462 +#: src/Content/Widget/VCard.php:113 src/Model/Profile.php:463 #: src/Module/Admin/Logs/View.php:93 msgid "Message" msgstr "" #: mod/editpost.php:144 src/Content/Conversation.php:394 -#: src/Module/Settings/TwoFactor/Trusted.php:137 +#: src/Module/Settings/TwoFactor/Trusted.php:138 msgid "Browser" msgstr "" @@ -366,8 +367,8 @@ msgstr "" #: src/Module/Install.php:286 src/Module/Install.php:291 #: src/Module/Install.php:305 src/Module/Install.php:320 #: src/Module/Install.php:347 src/Module/Register.php:148 -#: src/Module/Security/TwoFactor/Verify.php:100 -#: src/Module/Settings/TwoFactor/Index.php:133 +#: src/Module/Security/TwoFactor/Verify.php:101 +#: src/Module/Settings/TwoFactor/Index.php:136 #: src/Module/Settings/TwoFactor/Verify.php:154 msgid "Required" msgstr "" @@ -386,8 +387,8 @@ msgid "Description:" msgstr "" #: mod/events.php:504 src/Content/Widget/VCard.php:104 src/Model/Event.php:80 -#: src/Model/Event.php:107 src/Model/Event.php:466 src/Model/Event.php:915 -#: src/Model/Profile.php:370 src/Module/Contact/Profile.php:369 +#: src/Model/Event.php:107 src/Model/Event.php:465 src/Model/Event.php:915 +#: src/Model/Profile.php:371 src/Module/Contact/Profile.php:369 #: src/Module/Directory.php:148 src/Module/Notifications/Introductions.php:185 #: src/Module/Profile/Profile.php:194 msgid "Location:" @@ -413,7 +414,7 @@ msgstr "" #: src/Module/Install.php:252 src/Module/Install.php:294 #: src/Module/Install.php:331 src/Module/Invite.php:178 #: src/Module/Item/Compose.php:162 src/Module/Profile/Profile.php:247 -#: src/Module/Settings/Profile/Index.php:222 src/Object/Post.php:988 +#: src/Module/Settings/Profile/Index.php:222 src/Object/Post.php:992 #: view/theme/duepuntozero/config.php:69 view/theme/frio/config.php:160 #: view/theme/quattro/config.php:71 view/theme/vier/config.php:119 msgid "Submit" @@ -466,8 +467,8 @@ msgstr "" msgid "OStatus support is disabled. Contact can't be added." msgstr "" -#: mod/follow.php:138 src/Content/Item.php:443 src/Content/Widget.php:78 -#: src/Model/Contact.php:1102 src/Model/Contact.php:1114 +#: mod/follow.php:138 src/Content/Item.php:443 src/Content/Widget.php:80 +#: src/Model/Contact.php:1103 src/Model/Contact.php:1115 #: view/theme/vier/theme.php:172 msgid "Connect/Follow" msgstr "" @@ -1068,16 +1069,16 @@ msgstr "" #: mod/photos.php:1333 mod/photos.php:1389 mod/photos.php:1463 #: src/Module/Contact.php:544 src/Module/Item/Compose.php:160 -#: src/Object/Post.php:985 +#: src/Object/Post.php:989 msgid "This is you" msgstr "" #: mod/photos.php:1335 mod/photos.php:1391 mod/photos.php:1465 -#: src/Object/Post.php:522 src/Object/Post.php:987 +#: src/Object/Post.php:532 src/Object/Post.php:991 msgid "Comment" msgstr "" -#: mod/photos.php:1424 src/Content/Conversation.php:629 src/Object/Post.php:247 +#: mod/photos.php:1424 src/Content/Conversation.php:629 src/Object/Post.php:256 msgid "Select" msgstr "" @@ -1087,19 +1088,19 @@ msgstr "" msgid "Delete" msgstr "" -#: mod/photos.php:1486 src/Object/Post.php:369 +#: mod/photos.php:1486 src/Object/Post.php:379 msgid "Like" msgstr "" -#: mod/photos.php:1487 src/Object/Post.php:369 +#: mod/photos.php:1487 src/Object/Post.php:379 msgid "I like this (toggle)" msgstr "" -#: mod/photos.php:1488 src/Object/Post.php:370 +#: mod/photos.php:1488 src/Object/Post.php:380 msgid "Dislike" msgstr "" -#: mod/photos.php:1490 src/Object/Post.php:370 +#: mod/photos.php:1490 src/Object/Post.php:380 msgid "I don't like this (toggle)" msgstr "" @@ -1128,7 +1129,7 @@ msgstr "" msgid "Contact not found." msgstr "" -#: mod/removeme.php:65 src/Navigation/Notifications/Repository/Notify.php:482 +#: mod/removeme.php:65 src/Navigation/Notifications/Repository/Notify.php:483 msgid "[Friendica System Notify]" msgstr "" @@ -1166,7 +1167,7 @@ msgid "Resubscribing to OStatus contacts" msgstr "" #: mod/repair_ostatus.php:46 src/Module/Debug/ActivityPubConversion.php:134 -#: src/Module/Debug/Babel.php:293 src/Module/Security/TwoFactor/Verify.php:97 +#: src/Module/Debug/Babel.php:293 src/Module/Security/TwoFactor/Verify.php:98 msgid "Error" msgid_plural "Errors" msgstr[0] "" @@ -1404,11 +1405,11 @@ msgid "" "hours." msgstr "" -#: mod/suggest.php:55 src/Content/Widget.php:81 view/theme/vier/theme.php:175 +#: mod/suggest.php:55 src/Content/Widget.php:83 view/theme/vier/theme.php:175 msgid "Friend Suggestions" msgstr "" -#: mod/tagger.php:78 src/Content/Item.php:342 src/Model/Item.php:2699 +#: mod/tagger.php:78 src/Content/Item.php:342 src/Model/Item.php:2728 msgid "photo" msgstr "" @@ -1430,7 +1431,7 @@ msgid "Select a tag to remove: " msgstr "" #: mod/tagrm.php:126 src/Module/Settings/Delegation.php:179 -#: src/Module/Settings/TwoFactor/Trusted.php:140 +#: src/Module/Settings/TwoFactor/Trusted.php:142 msgid "Remove" msgstr "" @@ -1522,7 +1523,7 @@ msgstr "" msgid "File upload failed." msgstr "" -#: mod/wall_upload.php:218 src/Model/Photo.php:1061 +#: mod/wall_upload.php:218 src/Model/Photo.php:1085 msgid "Wall Photos" msgstr "" @@ -1546,11 +1547,11 @@ msgid "" "your site allow private mail from unknown senders." msgstr "" -#: src/App.php:463 +#: src/App.php:473 msgid "No system theme config value set." msgstr "" -#: src/App.php:584 +#: src/App.php:594 msgid "Apologies but the website is unavailable at the moment." msgstr "" @@ -1568,56 +1569,56 @@ msgstr "" msgid "toggle mobile" msgstr "" -#: src/App/Router.php:275 +#: src/App/Router.php:282 #, php-format msgid "Method not allowed for this module. Allowed method(s): %s" msgstr "" -#: src/App/Router.php:277 src/Module/HTTPException/PageNotFound.php:34 +#: src/App/Router.php:284 src/Module/HTTPException/PageNotFound.php:49 msgid "Page not found." msgstr "" -#: src/App/Router.php:305 +#: src/App/Router.php:312 msgid "You must be logged in to use addons. " msgstr "" -#: src/BaseModule.php:377 +#: src/BaseModule.php:392 msgid "" "The form security token was not correct. This probably happened because the " "form has been opened for too long (>3 hours) before submitting it." msgstr "" -#: src/BaseModule.php:404 +#: src/BaseModule.php:419 msgid "All contacts" msgstr "" -#: src/BaseModule.php:409 src/Content/Widget.php:233 src/Core/ACL.php:194 +#: src/BaseModule.php:424 src/Content/Widget.php:235 src/Core/ACL.php:194 #: src/Module/Contact.php:367 src/Module/PermissionTooltip.php:122 #: src/Module/PermissionTooltip.php:144 msgid "Followers" msgstr "" -#: src/BaseModule.php:414 src/Content/Widget.php:234 src/Module/Contact.php:368 +#: src/BaseModule.php:429 src/Content/Widget.php:236 src/Module/Contact.php:368 msgid "Following" msgstr "" -#: src/BaseModule.php:419 src/Content/Widget.php:235 src/Module/Contact.php:369 +#: src/BaseModule.php:434 src/Content/Widget.php:237 src/Module/Contact.php:369 msgid "Mutual friends" msgstr "" -#: src/BaseModule.php:427 +#: src/BaseModule.php:442 msgid "Common" msgstr "" -#: src/Console/Addon.php:177 src/Console/Addon.php:202 +#: src/Console/Addon.php:175 src/Console/Addon.php:199 msgid "Addon not found" msgstr "" -#: src/Console/Addon.php:181 +#: src/Console/Addon.php:179 msgid "Addon already enabled" msgstr "" -#: src/Console/Addon.php:206 +#: src/Console/Addon.php:203 msgid "Addon already disabled" msgstr "" @@ -1840,78 +1841,78 @@ msgstr "" msgid "Monthly" msgstr "" -#: src/Content/ContactSelector.php:123 +#: src/Content/ContactSelector.php:126 msgid "DFRN" msgstr "" -#: src/Content/ContactSelector.php:124 +#: src/Content/ContactSelector.php:127 msgid "OStatus" msgstr "" -#: src/Content/ContactSelector.php:125 +#: src/Content/ContactSelector.php:128 msgid "RSS/Atom" msgstr "" -#: src/Content/ContactSelector.php:126 src/Module/Admin/Users/Active.php:129 +#: src/Content/ContactSelector.php:129 src/Module/Admin/Users/Active.php:129 #: src/Module/Admin/Users/Blocked.php:130 src/Module/Admin/Users/Create.php:73 #: src/Module/Admin/Users/Deleted.php:88 src/Module/Admin/Users/Index.php:142 #: src/Module/Admin/Users/Index.php:162 src/Module/Admin/Users/Pending.php:104 msgid "Email" msgstr "" -#: src/Content/ContactSelector.php:127 src/Module/Debug/Babel.php:307 +#: src/Content/ContactSelector.php:130 src/Module/Debug/Babel.php:307 msgid "Diaspora" msgstr "" -#: src/Content/ContactSelector.php:128 +#: src/Content/ContactSelector.php:131 msgid "Zot!" msgstr "" -#: src/Content/ContactSelector.php:129 +#: src/Content/ContactSelector.php:132 msgid "LinkedIn" msgstr "" -#: src/Content/ContactSelector.php:130 +#: src/Content/ContactSelector.php:133 msgid "XMPP/IM" msgstr "" -#: src/Content/ContactSelector.php:131 +#: src/Content/ContactSelector.php:134 msgid "MySpace" msgstr "" -#: src/Content/ContactSelector.php:132 +#: src/Content/ContactSelector.php:135 msgid "Google+" msgstr "" -#: src/Content/ContactSelector.php:133 +#: src/Content/ContactSelector.php:136 msgid "pump.io" msgstr "" -#: src/Content/ContactSelector.php:134 +#: src/Content/ContactSelector.php:137 msgid "Twitter" msgstr "" -#: src/Content/ContactSelector.php:135 +#: src/Content/ContactSelector.php:138 msgid "Discourse" msgstr "" -#: src/Content/ContactSelector.php:136 +#: src/Content/ContactSelector.php:139 msgid "Diaspora Connector" msgstr "" -#: src/Content/ContactSelector.php:137 +#: src/Content/ContactSelector.php:140 msgid "GNU Social Connector" msgstr "" -#: src/Content/ContactSelector.php:138 +#: src/Content/ContactSelector.php:141 msgid "ActivityPub" msgstr "" -#: src/Content/ContactSelector.php:139 +#: src/Content/ContactSelector.php:142 msgid "pnut" msgstr "" -#: src/Content/ContactSelector.php:175 +#: src/Content/ContactSelector.php:178 #, php-format msgid "%s (via %s)" msgstr "" @@ -2016,7 +2017,7 @@ msgid "Visible to everybody" msgstr "" #: src/Content/Conversation.php:308 src/Module/Item/Compose.php:171 -#: src/Object/Post.php:998 +#: src/Object/Post.php:1002 msgid "Please enter a image/video/audio/webpage URL:" msgstr "" @@ -2049,7 +2050,7 @@ msgid "Share" msgstr "" #: src/Content/Conversation.php:348 src/Module/Item/Compose.php:168 -#: src/Object/Post.php:995 +#: src/Object/Post.php:999 msgid "Image" msgstr "" @@ -2061,25 +2062,25 @@ msgstr "" msgid "Scheduled at" msgstr "" -#: src/Content/Conversation.php:657 src/Object/Post.php:235 +#: src/Content/Conversation.php:657 src/Object/Post.php:244 msgid "Pinned item" msgstr "" -#: src/Content/Conversation.php:673 src/Object/Post.php:476 -#: src/Object/Post.php:477 +#: src/Content/Conversation.php:673 src/Object/Post.php:486 +#: src/Object/Post.php:487 #, php-format msgid "View %s's profile @ %s" msgstr "" -#: src/Content/Conversation.php:686 src/Object/Post.php:464 +#: src/Content/Conversation.php:686 src/Object/Post.php:474 msgid "Categories:" msgstr "" -#: src/Content/Conversation.php:687 src/Object/Post.php:465 +#: src/Content/Conversation.php:687 src/Object/Post.php:475 msgid "Filed under:" msgstr "" -#: src/Content/Conversation.php:695 src/Object/Post.php:490 +#: src/Content/Conversation.php:695 src/Object/Post.php:500 #, php-format msgid "%s from %s" msgstr "" @@ -2250,7 +2251,7 @@ msgid "Display membership date in profile" msgstr "" #: src/Content/ForumManager.php:151 src/Content/Nav.php:239 -#: src/Content/Text/HTML.php:896 src/Content/Widget.php:522 +#: src/Content/Text/HTML.php:903 src/Content/Widget.php:524 msgid "Forums" msgstr "" @@ -2258,12 +2259,12 @@ msgstr "" msgid "External link to forum" msgstr "" -#: src/Content/ForumManager.php:156 src/Content/Widget.php:501 +#: src/Content/ForumManager.php:156 src/Content/Widget.php:503 msgid "show less" msgstr "" -#: src/Content/ForumManager.php:157 src/Content/Widget.php:403 -#: src/Content/Widget.php:502 +#: src/Content/ForumManager.php:157 src/Content/Widget.php:405 +#: src/Content/Widget.php:504 msgid "show more" msgstr "" @@ -2272,7 +2273,7 @@ msgstr "" msgid "%1$s poked %2$s" msgstr "" -#: src/Content/Item.php:334 src/Model/Item.php:2697 +#: src/Content/Item.php:334 src/Model/Item.php:2726 msgid "event" msgstr "" @@ -2280,31 +2281,31 @@ msgstr "" msgid "Follow Thread" msgstr "" -#: src/Content/Item.php:423 src/Model/Contact.php:1107 +#: src/Content/Item.php:423 src/Model/Contact.php:1108 msgid "View Status" msgstr "" -#: src/Content/Item.php:424 src/Content/Item.php:446 src/Model/Contact.php:1041 -#: src/Model/Contact.php:1099 src/Model/Contact.php:1108 +#: src/Content/Item.php:424 src/Content/Item.php:446 src/Model/Contact.php:1042 +#: src/Model/Contact.php:1100 src/Model/Contact.php:1109 #: src/Module/Directory.php:158 src/Module/Settings/Profile/Index.php:225 msgid "View Profile" msgstr "" -#: src/Content/Item.php:425 src/Model/Contact.php:1109 +#: src/Content/Item.php:425 src/Model/Contact.php:1110 msgid "View Photos" msgstr "" -#: src/Content/Item.php:426 src/Model/Contact.php:1100 -#: src/Model/Contact.php:1110 +#: src/Content/Item.php:426 src/Model/Contact.php:1101 +#: src/Model/Contact.php:1111 msgid "Network Posts" msgstr "" -#: src/Content/Item.php:427 src/Model/Contact.php:1101 -#: src/Model/Contact.php:1111 +#: src/Content/Item.php:427 src/Model/Contact.php:1102 +#: src/Model/Contact.php:1112 msgid "View Contact" msgstr "" -#: src/Content/Item.php:428 src/Model/Contact.php:1112 +#: src/Content/Item.php:428 src/Model/Contact.php:1113 msgid "Send PM" msgstr "" @@ -2323,11 +2324,11 @@ msgstr "" msgid "Ignore" msgstr "" -#: src/Content/Item.php:434 src/Object/Post.php:445 +#: src/Content/Item.php:434 src/Object/Post.php:455 msgid "Languages" msgstr "" -#: src/Content/Item.php:438 src/Model/Contact.php:1113 +#: src/Content/Item.php:438 src/Model/Contact.php:1114 msgid "Poke" msgstr "" @@ -2343,7 +2344,7 @@ msgstr "" msgid "Clear notifications" msgstr "" -#: src/Content/Nav.php:96 src/Content/Text/HTML.php:883 +#: src/Content/Nav.php:96 src/Content/Text/HTML.php:890 msgid "@name, !forum, #tags, content" msgstr "" @@ -2366,7 +2367,7 @@ msgstr "" #: src/Content/Nav.php:190 src/Module/BaseProfile.php:56 #: src/Module/Contact.php:433 src/Module/Contact/Profile.php:380 -#: src/Module/Settings/TwoFactor/Index.php:112 view/theme/frio/theme.php:225 +#: src/Module/Settings/TwoFactor/Index.php:115 view/theme/frio/theme.php:225 msgid "Status" msgstr "" @@ -2427,7 +2428,7 @@ msgstr "" #: src/Content/Nav.php:222 src/Module/Help.php:67 #: src/Module/Settings/TwoFactor/AppSpecific.php:127 -#: src/Module/Settings/TwoFactor/Index.php:111 +#: src/Module/Settings/TwoFactor/Index.php:114 #: src/Module/Settings/TwoFactor/Recovery.php:105 #: src/Module/Settings/TwoFactor/Verify.php:145 view/theme/vier/theme.php:217 msgid "Help" @@ -2445,8 +2446,8 @@ msgstr "" msgid "Addon applications, utilities, games" msgstr "" -#: src/Content/Nav.php:230 src/Content/Text/HTML.php:881 -#: src/Module/Admin/Logs/View.php:87 src/Module/Search/Index.php:97 +#: src/Content/Nav.php:230 src/Content/Text/HTML.php:888 +#: src/Module/Admin/Logs/View.php:87 src/Module/Search/Index.php:112 msgid "Search" msgstr "" @@ -2454,17 +2455,17 @@ msgstr "" msgid "Search site content" msgstr "" -#: src/Content/Nav.php:233 src/Content/Text/HTML.php:890 +#: src/Content/Nav.php:233 src/Content/Text/HTML.php:897 msgid "Full Text" msgstr "" -#: src/Content/Nav.php:234 src/Content/Text/HTML.php:891 +#: src/Content/Nav.php:234 src/Content/Text/HTML.php:898 #: src/Content/Widget/TagCloud.php:68 msgid "Tags" msgstr "" #: src/Content/Nav.php:235 src/Content/Nav.php:294 -#: src/Content/Text/HTML.php:892 src/Module/BaseProfile.php:125 +#: src/Content/Text/HTML.php:899 src/Module/BaseProfile.php:125 #: src/Module/BaseProfile.php:128 src/Module/Contact.php:370 #: src/Module/Contact.php:464 view/theme/frio/theme.php:236 msgid "Contacts" @@ -2491,7 +2492,7 @@ msgstr "" msgid "People directory" msgstr "" -#: src/Content/Nav.php:263 src/Module/BaseAdmin.php:85 +#: src/Content/Nav.php:263 src/Module/BaseAdmin.php:88 msgid "Information" msgstr "" @@ -2500,7 +2501,7 @@ msgid "Information about this friendica instance" msgstr "" #: src/Content/Nav.php:266 src/Module/Admin/Tos.php:76 -#: src/Module/BaseAdmin.php:96 src/Module/Register.php:176 +#: src/Module/BaseAdmin.php:99 src/Module/Register.php:176 #: src/Module/Tos.php:87 msgid "Terms of Service" msgstr "" @@ -2572,7 +2573,7 @@ msgstr "" msgid "Manage/edit friends and contacts" msgstr "" -#: src/Content/Nav.php:299 src/Module/BaseAdmin.php:126 +#: src/Content/Nav.php:299 src/Module/BaseAdmin.php:129 msgid "Admin" msgstr "" @@ -2612,8 +2613,8 @@ msgstr "" msgid "last" msgstr "" -#: src/Content/Text/BBCode.php:990 src/Content/Text/BBCode.php:1784 -#: src/Content/Text/BBCode.php:1785 +#: src/Content/Text/BBCode.php:990 src/Content/Text/BBCode.php:1808 +#: src/Content/Text/BBCode.php:1809 msgid "Image/photo" msgstr "" @@ -2623,41 +2624,41 @@ msgid "" "%2$s %3$s" msgstr "" -#: src/Content/Text/BBCode.php:1188 src/Model/Item.php:3271 -#: src/Model/Item.php:3277 src/Model/Item.php:3278 +#: src/Content/Text/BBCode.php:1188 src/Model/Item.php:3301 +#: src/Model/Item.php:3307 src/Model/Item.php:3308 msgid "Link to source" msgstr "" -#: src/Content/Text/BBCode.php:1702 src/Content/Text/HTML.php:933 +#: src/Content/Text/BBCode.php:1726 src/Content/Text/HTML.php:940 msgid "Click to open/close" msgstr "" -#: src/Content/Text/BBCode.php:1733 +#: src/Content/Text/BBCode.php:1757 msgid "$1 wrote:" msgstr "" -#: src/Content/Text/BBCode.php:1789 src/Content/Text/BBCode.php:1790 +#: src/Content/Text/BBCode.php:1813 src/Content/Text/BBCode.php:1814 msgid "Encrypted content" msgstr "" -#: src/Content/Text/BBCode.php:2008 +#: src/Content/Text/BBCode.php:2032 msgid "Invalid source protocol" msgstr "" -#: src/Content/Text/BBCode.php:2023 +#: src/Content/Text/BBCode.php:2047 msgid "Invalid link protocol" msgstr "" -#: src/Content/Text/HTML.php:797 +#: src/Content/Text/HTML.php:805 msgid "Loading more entries..." msgstr "" -#: src/Content/Text/HTML.php:798 +#: src/Content/Text/HTML.php:806 msgid "The end" msgstr "" -#: src/Content/Text/HTML.php:875 src/Content/Widget/VCard.php:109 -#: src/Model/Profile.php:456 +#: src/Content/Text/HTML.php:882 src/Content/Widget/VCard.php:109 +#: src/Model/Profile.php:457 msgid "Follow" msgstr "" @@ -2677,117 +2678,117 @@ msgstr "" msgid "Connect" msgstr "" -#: src/Content/Widget.php:70 +#: src/Content/Widget.php:72 #, php-format msgid "%d invitation available" msgid_plural "%d invitations available" msgstr[0] "" msgstr[1] "" -#: src/Content/Widget.php:76 view/theme/vier/theme.php:170 +#: src/Content/Widget.php:78 view/theme/vier/theme.php:170 msgid "Find People" msgstr "" -#: src/Content/Widget.php:77 view/theme/vier/theme.php:171 +#: src/Content/Widget.php:79 view/theme/vier/theme.php:171 msgid "Enter name or interest" msgstr "" -#: src/Content/Widget.php:79 view/theme/vier/theme.php:173 +#: src/Content/Widget.php:81 view/theme/vier/theme.php:173 msgid "Examples: Robert Morgenstein, Fishing" msgstr "" -#: src/Content/Widget.php:80 src/Module/Contact.php:391 +#: src/Content/Widget.php:82 src/Module/Contact.php:391 #: src/Module/Directory.php:97 view/theme/vier/theme.php:174 msgid "Find" msgstr "" -#: src/Content/Widget.php:82 view/theme/vier/theme.php:176 +#: src/Content/Widget.php:84 view/theme/vier/theme.php:176 msgid "Similar Interests" msgstr "" -#: src/Content/Widget.php:83 view/theme/vier/theme.php:177 +#: src/Content/Widget.php:85 view/theme/vier/theme.php:177 msgid "Random Profile" msgstr "" -#: src/Content/Widget.php:84 view/theme/vier/theme.php:178 +#: src/Content/Widget.php:86 view/theme/vier/theme.php:178 msgid "Invite Friends" msgstr "" -#: src/Content/Widget.php:85 src/Module/Directory.php:89 +#: src/Content/Widget.php:87 src/Module/Directory.php:89 #: view/theme/vier/theme.php:179 msgid "Global Directory" msgstr "" -#: src/Content/Widget.php:87 view/theme/vier/theme.php:181 +#: src/Content/Widget.php:89 view/theme/vier/theme.php:181 msgid "Local Directory" msgstr "" -#: src/Content/Widget.php:209 src/Model/Group.php:570 +#: src/Content/Widget.php:211 src/Model/Group.php:583 #: src/Module/Contact.php:354 src/Module/Welcome.php:76 msgid "Groups" msgstr "" -#: src/Content/Widget.php:211 +#: src/Content/Widget.php:213 msgid "Everyone" msgstr "" -#: src/Content/Widget.php:240 +#: src/Content/Widget.php:242 msgid "Relationships" msgstr "" -#: src/Content/Widget.php:242 src/Module/Contact.php:306 +#: src/Content/Widget.php:244 src/Module/Contact.php:306 #: src/Module/Group.php:293 msgid "All Contacts" msgstr "" -#: src/Content/Widget.php:281 +#: src/Content/Widget.php:283 msgid "Protocols" msgstr "" -#: src/Content/Widget.php:283 +#: src/Content/Widget.php:285 msgid "All Protocols" msgstr "" -#: src/Content/Widget.php:311 +#: src/Content/Widget.php:313 msgid "Saved Folders" msgstr "" -#: src/Content/Widget.php:313 src/Content/Widget.php:344 +#: src/Content/Widget.php:315 src/Content/Widget.php:346 msgid "Everything" msgstr "" -#: src/Content/Widget.php:342 +#: src/Content/Widget.php:344 msgid "Categories" msgstr "" -#: src/Content/Widget.php:399 +#: src/Content/Widget.php:401 #, php-format msgid "%d contact in common" msgid_plural "%d contacts in common" msgstr[0] "" msgstr[1] "" -#: src/Content/Widget.php:495 +#: src/Content/Widget.php:497 msgid "Archives" msgstr "" -#: src/Content/Widget.php:519 +#: src/Content/Widget.php:521 msgid "Persons" msgstr "" -#: src/Content/Widget.php:520 +#: src/Content/Widget.php:522 msgid "Organisations" msgstr "" -#: src/Content/Widget.php:521 src/Model/Contact.php:1537 +#: src/Content/Widget.php:523 src/Model/Contact.php:1538 msgid "News" msgstr "" -#: src/Content/Widget.php:525 src/Module/Settings/Account.php:455 +#: src/Content/Widget.php:527 src/Module/Settings/Account.php:455 msgid "Account Types" msgstr "" -#: src/Content/Widget.php:526 src/Module/Admin/BaseUsers.php:51 +#: src/Content/Widget.php:528 src/Module/Admin/BaseUsers.php:51 msgid "All" msgstr "" @@ -2837,22 +2838,22 @@ msgstr[1] "" msgid "More Trending Tags" msgstr "" -#: src/Content/Widget/VCard.php:102 src/Model/Profile.php:375 +#: src/Content/Widget/VCard.php:102 src/Model/Profile.php:376 #: src/Module/Contact/Profile.php:371 src/Module/Profile/Profile.php:176 msgid "XMPP:" msgstr "" -#: src/Content/Widget/VCard.php:103 src/Model/Profile.php:376 +#: src/Content/Widget/VCard.php:103 src/Model/Profile.php:377 #: src/Module/Contact/Profile.php:373 src/Module/Profile/Profile.php:180 msgid "Matrix:" msgstr "" -#: src/Content/Widget/VCard.php:107 src/Model/Profile.php:468 +#: src/Content/Widget/VCard.php:107 src/Model/Profile.php:469 #: src/Module/Notifications/Introductions.php:199 msgid "Network:" msgstr "" -#: src/Content/Widget/VCard.php:111 src/Model/Profile.php:458 +#: src/Content/Widget/VCard.php:111 src/Model/Profile.php:459 msgid "Unfollow" msgstr "" @@ -3213,206 +3214,206 @@ msgstr "" msgid "Could not connect to database." msgstr "" -#: src/Core/L10n.php:400 src/Model/Event.php:425 +#: src/Core/L10n.php:399 src/Model/Event.php:424 #: src/Module/Settings/Display.php:182 msgid "Monday" msgstr "" -#: src/Core/L10n.php:400 src/Model/Event.php:426 +#: src/Core/L10n.php:399 src/Model/Event.php:425 msgid "Tuesday" msgstr "" -#: src/Core/L10n.php:400 src/Model/Event.php:427 +#: src/Core/L10n.php:399 src/Model/Event.php:426 msgid "Wednesday" msgstr "" -#: src/Core/L10n.php:400 src/Model/Event.php:428 +#: src/Core/L10n.php:399 src/Model/Event.php:427 msgid "Thursday" msgstr "" -#: src/Core/L10n.php:400 src/Model/Event.php:429 +#: src/Core/L10n.php:399 src/Model/Event.php:428 msgid "Friday" msgstr "" -#: src/Core/L10n.php:400 src/Model/Event.php:430 +#: src/Core/L10n.php:399 src/Model/Event.php:429 msgid "Saturday" msgstr "" -#: src/Core/L10n.php:400 src/Model/Event.php:424 +#: src/Core/L10n.php:399 src/Model/Event.php:423 #: src/Module/Settings/Display.php:182 msgid "Sunday" msgstr "" -#: src/Core/L10n.php:404 src/Model/Event.php:445 +#: src/Core/L10n.php:403 src/Model/Event.php:444 msgid "January" msgstr "" -#: src/Core/L10n.php:404 src/Model/Event.php:446 +#: src/Core/L10n.php:403 src/Model/Event.php:445 msgid "February" msgstr "" -#: src/Core/L10n.php:404 src/Model/Event.php:447 +#: src/Core/L10n.php:403 src/Model/Event.php:446 msgid "March" msgstr "" -#: src/Core/L10n.php:404 src/Model/Event.php:448 +#: src/Core/L10n.php:403 src/Model/Event.php:447 msgid "April" msgstr "" -#: src/Core/L10n.php:404 src/Core/L10n.php:424 src/Model/Event.php:436 +#: src/Core/L10n.php:403 src/Core/L10n.php:422 src/Model/Event.php:435 msgid "May" msgstr "" -#: src/Core/L10n.php:404 src/Model/Event.php:449 +#: src/Core/L10n.php:403 src/Model/Event.php:448 msgid "June" msgstr "" -#: src/Core/L10n.php:404 src/Model/Event.php:450 +#: src/Core/L10n.php:403 src/Model/Event.php:449 msgid "July" msgstr "" -#: src/Core/L10n.php:404 src/Model/Event.php:451 +#: src/Core/L10n.php:403 src/Model/Event.php:450 msgid "August" msgstr "" -#: src/Core/L10n.php:404 src/Model/Event.php:452 +#: src/Core/L10n.php:403 src/Model/Event.php:451 msgid "September" msgstr "" -#: src/Core/L10n.php:404 src/Model/Event.php:453 +#: src/Core/L10n.php:403 src/Model/Event.php:452 msgid "October" msgstr "" -#: src/Core/L10n.php:404 src/Model/Event.php:454 +#: src/Core/L10n.php:403 src/Model/Event.php:453 msgid "November" msgstr "" -#: src/Core/L10n.php:404 src/Model/Event.php:455 +#: src/Core/L10n.php:403 src/Model/Event.php:454 msgid "December" msgstr "" -#: src/Core/L10n.php:420 src/Model/Event.php:417 +#: src/Core/L10n.php:418 src/Model/Event.php:416 msgid "Mon" msgstr "" -#: src/Core/L10n.php:420 src/Model/Event.php:418 +#: src/Core/L10n.php:418 src/Model/Event.php:417 msgid "Tue" msgstr "" -#: src/Core/L10n.php:420 src/Model/Event.php:419 +#: src/Core/L10n.php:418 src/Model/Event.php:418 msgid "Wed" msgstr "" -#: src/Core/L10n.php:420 src/Model/Event.php:420 +#: src/Core/L10n.php:418 src/Model/Event.php:419 msgid "Thu" msgstr "" -#: src/Core/L10n.php:420 src/Model/Event.php:421 +#: src/Core/L10n.php:418 src/Model/Event.php:420 msgid "Fri" msgstr "" -#: src/Core/L10n.php:420 src/Model/Event.php:422 +#: src/Core/L10n.php:418 src/Model/Event.php:421 msgid "Sat" msgstr "" -#: src/Core/L10n.php:420 src/Model/Event.php:416 +#: src/Core/L10n.php:418 src/Model/Event.php:415 msgid "Sun" msgstr "" -#: src/Core/L10n.php:424 src/Model/Event.php:432 +#: src/Core/L10n.php:422 src/Model/Event.php:431 msgid "Jan" msgstr "" -#: src/Core/L10n.php:424 src/Model/Event.php:433 +#: src/Core/L10n.php:422 src/Model/Event.php:432 msgid "Feb" msgstr "" -#: src/Core/L10n.php:424 src/Model/Event.php:434 +#: src/Core/L10n.php:422 src/Model/Event.php:433 msgid "Mar" msgstr "" -#: src/Core/L10n.php:424 src/Model/Event.php:435 +#: src/Core/L10n.php:422 src/Model/Event.php:434 msgid "Apr" msgstr "" -#: src/Core/L10n.php:424 src/Model/Event.php:437 +#: src/Core/L10n.php:422 src/Model/Event.php:436 msgid "Jun" msgstr "" -#: src/Core/L10n.php:424 src/Model/Event.php:438 +#: src/Core/L10n.php:422 src/Model/Event.php:437 msgid "Jul" msgstr "" -#: src/Core/L10n.php:424 src/Model/Event.php:439 +#: src/Core/L10n.php:422 src/Model/Event.php:438 msgid "Aug" msgstr "" -#: src/Core/L10n.php:424 +#: src/Core/L10n.php:422 msgid "Sep" msgstr "" -#: src/Core/L10n.php:424 src/Model/Event.php:441 +#: src/Core/L10n.php:422 src/Model/Event.php:440 msgid "Oct" msgstr "" -#: src/Core/L10n.php:424 src/Model/Event.php:442 +#: src/Core/L10n.php:422 src/Model/Event.php:441 msgid "Nov" msgstr "" -#: src/Core/L10n.php:424 src/Model/Event.php:443 +#: src/Core/L10n.php:422 src/Model/Event.php:442 msgid "Dec" msgstr "" -#: src/Core/L10n.php:443 +#: src/Core/L10n.php:441 msgid "poke" msgstr "" -#: src/Core/L10n.php:443 +#: src/Core/L10n.php:441 msgid "poked" msgstr "" -#: src/Core/L10n.php:444 +#: src/Core/L10n.php:442 msgid "ping" msgstr "" -#: src/Core/L10n.php:444 +#: src/Core/L10n.php:442 msgid "pinged" msgstr "" -#: src/Core/L10n.php:445 +#: src/Core/L10n.php:443 msgid "prod" msgstr "" -#: src/Core/L10n.php:445 +#: src/Core/L10n.php:443 msgid "prodded" msgstr "" -#: src/Core/L10n.php:446 +#: src/Core/L10n.php:444 msgid "slap" msgstr "" -#: src/Core/L10n.php:446 +#: src/Core/L10n.php:444 msgid "slapped" msgstr "" -#: src/Core/L10n.php:447 +#: src/Core/L10n.php:445 msgid "finger" msgstr "" -#: src/Core/L10n.php:447 +#: src/Core/L10n.php:445 msgid "fingered" msgstr "" -#: src/Core/L10n.php:448 +#: src/Core/L10n.php:446 msgid "rebuff" msgstr "" -#: src/Core/L10n.php:448 +#: src/Core/L10n.php:446 msgid "rebuffed" msgstr "" #: src/Core/Renderer.php:89 src/Core/Renderer.php:118 src/Core/Renderer.php:145 -#: src/Core/Renderer.php:179 src/Render/FriendicaSmartyEngine.php:56 +#: src/Core/Renderer.php:179 src/Render/FriendicaSmartyEngine.php:69 msgid "" "Friendica can't display this page at the moment, please contact the " "administrator." @@ -3497,35 +3498,35 @@ msgid "" "\t\t\t\t\tThe friendica database was successfully updated from %s to %s." msgstr "" -#: src/Core/UserImport.php:125 +#: src/Core/UserImport.php:126 msgid "Error decoding account file" msgstr "" -#: src/Core/UserImport.php:131 +#: src/Core/UserImport.php:132 msgid "Error! No version data in file! This is not a Friendica account file?" msgstr "" -#: src/Core/UserImport.php:139 +#: src/Core/UserImport.php:140 #, php-format msgid "User '%s' already exists on this server!" msgstr "" -#: src/Core/UserImport.php:175 +#: src/Core/UserImport.php:176 msgid "User creation error" msgstr "" -#: src/Core/UserImport.php:220 +#: src/Core/UserImport.php:221 #, php-format msgid "%d contact not imported" msgid_plural "%d contacts not imported" msgstr[0] "" msgstr[1] "" -#: src/Core/UserImport.php:273 +#: src/Core/UserImport.php:274 msgid "User profile creation error" msgstr "" -#: src/Core/UserImport.php:326 +#: src/Core/UserImport.php:327 msgid "Done. You can now login with your username and password" msgstr "" @@ -3555,7 +3556,7 @@ msgstr "" msgid "There are no tables on MyISAM or InnoDB with the Antelope file format." msgstr "" -#: src/Database/DBStructure.php:158 +#: src/Database/DBStructure.php:157 #, php-format msgid "" "\n" @@ -3563,20 +3564,20 @@ msgid "" "%s\n" msgstr "" -#: src/Database/DBStructure.php:161 +#: src/Database/DBStructure.php:160 msgid "Errors encountered performing database changes: " msgstr "" -#: src/Database/DBStructure.php:549 +#: src/Database/DBStructure.php:563 msgid "Another database update is currently running." msgstr "" -#: src/Database/DBStructure.php:553 +#: src/Database/DBStructure.php:567 #, php-format msgid "%s: Database update" msgstr "" -#: src/Database/DBStructure.php:803 +#: src/Database/DBStructure.php:817 #, php-format msgid "%s: updating %s table." msgstr "" @@ -3607,81 +3608,81 @@ msgstr "" msgid "Legacy module file not found: %s" msgstr "" -#: src/Model/Contact.php:1103 src/Model/Contact.php:1115 +#: src/Model/Contact.php:1104 src/Model/Contact.php:1116 msgid "UnFollow" msgstr "" -#: src/Model/Contact.php:1121 src/Module/Admin/Users/Pending.php:107 +#: src/Model/Contact.php:1122 src/Module/Admin/Users/Pending.php:107 #: src/Module/Notifications/Introductions.php:130 #: src/Module/Notifications/Introductions.php:202 msgid "Approve" msgstr "" -#: src/Model/Contact.php:1533 +#: src/Model/Contact.php:1534 msgid "Organisation" msgstr "" -#: src/Model/Contact.php:1541 +#: src/Model/Contact.php:1542 msgid "Forum" msgstr "" -#: src/Model/Contact.php:2550 +#: src/Model/Contact.php:2625 msgid "Disallowed profile URL." msgstr "" -#: src/Model/Contact.php:2555 src/Module/Friendica.php:81 +#: src/Model/Contact.php:2630 src/Module/Friendica.php:81 msgid "Blocked domain" msgstr "" -#: src/Model/Contact.php:2560 +#: src/Model/Contact.php:2635 msgid "Connect URL missing." msgstr "" -#: src/Model/Contact.php:2569 +#: src/Model/Contact.php:2644 msgid "" "The contact could not be added. Please check the relevant network " "credentials in your Settings -> Social Networks page." msgstr "" -#: src/Model/Contact.php:2611 +#: src/Model/Contact.php:2686 msgid "The profile address specified does not provide adequate information." msgstr "" -#: src/Model/Contact.php:2613 +#: src/Model/Contact.php:2688 msgid "No compatible communication protocols or feeds were discovered." msgstr "" -#: src/Model/Contact.php:2616 +#: src/Model/Contact.php:2691 msgid "An author or name was not found." msgstr "" -#: src/Model/Contact.php:2619 +#: src/Model/Contact.php:2694 msgid "No browser URL could be matched to this address." msgstr "" -#: src/Model/Contact.php:2622 +#: src/Model/Contact.php:2697 msgid "" "Unable to match @-style Identity Address with a known protocol or email " "contact." msgstr "" -#: src/Model/Contact.php:2623 +#: src/Model/Contact.php:2698 msgid "Use mailto: in front of address to force email check." msgstr "" -#: src/Model/Contact.php:2629 +#: src/Model/Contact.php:2704 msgid "" "The profile address specified belongs to a network which has been disabled " "on this site." msgstr "" -#: src/Model/Contact.php:2634 +#: src/Model/Contact.php:2709 msgid "" "Limited profile. This person will be unable to receive direct/personal " "notifications from you." msgstr "" -#: src/Model/Contact.php:2693 +#: src/Model/Contact.php:2768 msgid "Unable to retrieve contact information." msgstr "" @@ -3689,41 +3690,41 @@ msgstr "" msgid "l F d, Y \\@ g:i A \\G\\M\\TP (e)" msgstr "" -#: src/Model/Event.php:73 src/Model/Event.php:90 src/Model/Event.php:464 +#: src/Model/Event.php:73 src/Model/Event.php:90 src/Model/Event.php:463 #: src/Model/Event.php:897 msgid "Starts:" msgstr "" -#: src/Model/Event.php:76 src/Model/Event.php:96 src/Model/Event.php:465 +#: src/Model/Event.php:76 src/Model/Event.php:96 src/Model/Event.php:464 #: src/Model/Event.php:901 msgid "Finishes:" msgstr "" -#: src/Model/Event.php:414 +#: src/Model/Event.php:413 msgid "all-day" msgstr "" -#: src/Model/Event.php:440 +#: src/Model/Event.php:439 msgid "Sept" msgstr "" -#: src/Model/Event.php:462 +#: src/Model/Event.php:461 msgid "No events to display" msgstr "" -#: src/Model/Event.php:578 +#: src/Model/Event.php:577 msgid "l, F j" msgstr "" -#: src/Model/Event.php:609 +#: src/Model/Event.php:608 msgid "Edit event" msgstr "" -#: src/Model/Event.php:610 +#: src/Model/Event.php:609 msgid "Duplicate event" msgstr "" -#: src/Model/Event.php:611 +#: src/Model/Event.php:610 msgid "Delete event" msgstr "" @@ -3747,112 +3748,112 @@ msgstr "" msgid "Hide map" msgstr "" -#: src/Model/Event.php:1009 +#: src/Model/Event.php:1010 #, php-format msgid "%s's birthday" msgstr "" -#: src/Model/Event.php:1010 +#: src/Model/Event.php:1011 #, php-format msgid "Happy Birthday %s" msgstr "" -#: src/Model/Group.php:95 +#: src/Model/Group.php:105 msgid "" "A deleted group with this name was revived. Existing item permissions " "may apply to this group and any future members. If this is " "not what you intended, please create another group with a different name." msgstr "" -#: src/Model/Group.php:486 +#: src/Model/Group.php:499 msgid "Default privacy group for new contacts" msgstr "" -#: src/Model/Group.php:518 +#: src/Model/Group.php:531 msgid "Everybody" msgstr "" -#: src/Model/Group.php:537 +#: src/Model/Group.php:550 msgid "edit" msgstr "" -#: src/Model/Group.php:569 +#: src/Model/Group.php:582 msgid "add" msgstr "" -#: src/Model/Group.php:574 +#: src/Model/Group.php:587 msgid "Edit group" msgstr "" -#: src/Model/Group.php:575 src/Module/Group.php:194 +#: src/Model/Group.php:588 src/Module/Group.php:194 msgid "Contacts not in any group" msgstr "" -#: src/Model/Group.php:577 +#: src/Model/Group.php:590 msgid "Create a new group" msgstr "" -#: src/Model/Group.php:578 src/Module/Group.php:179 src/Module/Group.php:202 +#: src/Model/Group.php:591 src/Module/Group.php:179 src/Module/Group.php:202 #: src/Module/Group.php:277 msgid "Group Name: " msgstr "" -#: src/Model/Group.php:579 +#: src/Model/Group.php:592 msgid "Edit groups" msgstr "" -#: src/Model/Item.php:1795 +#: src/Model/Item.php:1823 #, php-format msgid "Detected languages in this post:\\n%s" msgstr "" -#: src/Model/Item.php:2701 +#: src/Model/Item.php:2730 msgid "activity" msgstr "" -#: src/Model/Item.php:2703 +#: src/Model/Item.php:2732 msgid "comment" msgstr "" -#: src/Model/Item.php:2706 +#: src/Model/Item.php:2735 msgid "post" msgstr "" -#: src/Model/Item.php:2821 +#: src/Model/Item.php:2851 #, php-format msgid "Content warning: %s" msgstr "" -#: src/Model/Item.php:3180 +#: src/Model/Item.php:3210 msgid "bytes" msgstr "" -#: src/Model/Item.php:3214 +#: src/Model/Item.php:3244 #, php-format msgid "%s (%d%s, %d votes)" msgstr "" -#: src/Model/Item.php:3216 +#: src/Model/Item.php:3246 #, php-format msgid "%s (%d votes)" msgstr "" -#: src/Model/Item.php:3221 +#: src/Model/Item.php:3251 #, php-format msgid "%d voters. Poll end: %s" msgstr "" -#: src/Model/Item.php:3223 +#: src/Model/Item.php:3253 #, php-format msgid "%d voters." msgstr "" -#: src/Model/Item.php:3225 +#: src/Model/Item.php:3255 #, php-format msgid "Poll end: %s" msgstr "" -#: src/Model/Item.php:3259 src/Model/Item.php:3260 +#: src/Model/Item.php:3289 src/Model/Item.php:3290 msgid "View on separate page" msgstr "" @@ -3860,147 +3861,147 @@ msgstr "" msgid "[no subject]" msgstr "" -#: src/Model/Profile.php:358 src/Module/Profile/Profile.php:256 +#: src/Model/Profile.php:359 src/Module/Profile/Profile.php:256 #: src/Module/Profile/Profile.php:258 msgid "Edit profile" msgstr "" -#: src/Model/Profile.php:360 +#: src/Model/Profile.php:361 msgid "Change profile photo" msgstr "" -#: src/Model/Profile.php:373 src/Module/Directory.php:153 +#: src/Model/Profile.php:374 src/Module/Directory.php:153 #: src/Module/Profile/Profile.php:184 msgid "Homepage:" msgstr "" -#: src/Model/Profile.php:374 src/Module/Contact/Profile.php:375 +#: src/Model/Profile.php:375 src/Module/Contact/Profile.php:375 #: src/Module/Notifications/Introductions.php:187 msgid "About:" msgstr "" -#: src/Model/Profile.php:460 +#: src/Model/Profile.php:461 msgid "Atom feed" msgstr "" -#: src/Model/Profile.php:504 +#: src/Model/Profile.php:505 msgid "F d" msgstr "" -#: src/Model/Profile.php:568 src/Model/Profile.php:652 +#: src/Model/Profile.php:569 src/Model/Profile.php:653 msgid "[today]" msgstr "" -#: src/Model/Profile.php:577 +#: src/Model/Profile.php:578 msgid "Birthday Reminders" msgstr "" -#: src/Model/Profile.php:578 +#: src/Model/Profile.php:579 msgid "Birthdays this week:" msgstr "" -#: src/Model/Profile.php:601 +#: src/Model/Profile.php:602 msgid "g A l F d" msgstr "" -#: src/Model/Profile.php:639 +#: src/Model/Profile.php:640 msgid "[No description]" msgstr "" -#: src/Model/Profile.php:665 +#: src/Model/Profile.php:666 msgid "Event Reminders" msgstr "" -#: src/Model/Profile.php:666 +#: src/Model/Profile.php:667 msgid "Upcoming events the next 7 days:" msgstr "" -#: src/Model/Profile.php:854 +#: src/Model/Profile.php:855 #, php-format msgid "OpenWebAuth: %1$s welcomes %2$s" msgstr "" -#: src/Model/Profile.php:980 +#: src/Model/Profile.php:981 msgid "Hometown:" msgstr "" -#: src/Model/Profile.php:981 +#: src/Model/Profile.php:982 msgid "Marital Status:" msgstr "" -#: src/Model/Profile.php:982 +#: src/Model/Profile.php:983 msgid "With:" msgstr "" -#: src/Model/Profile.php:983 +#: src/Model/Profile.php:984 msgid "Since:" msgstr "" -#: src/Model/Profile.php:984 +#: src/Model/Profile.php:985 msgid "Sexual Preference:" msgstr "" -#: src/Model/Profile.php:985 +#: src/Model/Profile.php:986 msgid "Political Views:" msgstr "" -#: src/Model/Profile.php:986 +#: src/Model/Profile.php:987 msgid "Religious Views:" msgstr "" -#: src/Model/Profile.php:987 +#: src/Model/Profile.php:988 msgid "Likes:" msgstr "" -#: src/Model/Profile.php:988 +#: src/Model/Profile.php:989 msgid "Dislikes:" msgstr "" -#: src/Model/Profile.php:989 +#: src/Model/Profile.php:990 msgid "Title/Description:" msgstr "" -#: src/Model/Profile.php:990 src/Module/Admin/Summary.php:234 +#: src/Model/Profile.php:991 src/Module/Admin/Summary.php:234 msgid "Summary" msgstr "" -#: src/Model/Profile.php:991 +#: src/Model/Profile.php:992 msgid "Musical interests" msgstr "" -#: src/Model/Profile.php:992 +#: src/Model/Profile.php:993 msgid "Books, literature" msgstr "" -#: src/Model/Profile.php:993 +#: src/Model/Profile.php:994 msgid "Television" msgstr "" -#: src/Model/Profile.php:994 +#: src/Model/Profile.php:995 msgid "Film/dance/culture/entertainment" msgstr "" -#: src/Model/Profile.php:995 +#: src/Model/Profile.php:996 msgid "Hobbies/Interests" msgstr "" -#: src/Model/Profile.php:996 +#: src/Model/Profile.php:997 msgid "Love/romance" msgstr "" -#: src/Model/Profile.php:997 +#: src/Model/Profile.php:998 msgid "Work/employment" msgstr "" -#: src/Model/Profile.php:998 +#: src/Model/Profile.php:999 msgid "School/education" msgstr "" -#: src/Model/Profile.php:999 +#: src/Model/Profile.php:1000 msgid "Contact information and Social Networks" msgstr "" -#: src/Model/User.php:210 src/Model/User.php:1058 +#: src/Model/User.php:212 src/Model/User.php:1058 msgid "SERIOUS ERROR: Generation of security keys failed." msgstr "" @@ -4047,13 +4048,13 @@ msgstr "" msgid "Invalid OpenID url" msgstr "" -#: src/Model/User.php:970 src/Security/Authentication.php:235 +#: src/Model/User.php:970 src/Security/Authentication.php:240 msgid "" "We encountered a problem while logging in with the OpenID you provided. " "Please check the correct spelling of the ID." msgstr "" -#: src/Model/User.php:970 src/Security/Authentication.php:235 +#: src/Model/User.php:970 src/Security/Authentication.php:240 msgid "The error message was:" msgstr "" @@ -4135,7 +4136,7 @@ msgstr "" msgid "Profile Photos" msgstr "" -#: src/Model/User.php:1368 +#: src/Model/User.php:1367 #, php-format msgid "" "\n" @@ -4143,7 +4144,7 @@ msgid "" "\t\t\tthe administrator of %2$s has set up an account for you." msgstr "" -#: src/Model/User.php:1371 +#: src/Model/User.php:1370 #, php-format msgid "" "\n" @@ -4180,12 +4181,12 @@ msgid "" "\t\tThank you and welcome to %4$s." msgstr "" -#: src/Model/User.php:1404 src/Model/User.php:1511 +#: src/Model/User.php:1403 src/Model/User.php:1510 #, php-format msgid "Registration details for %s" msgstr "" -#: src/Model/User.php:1424 +#: src/Model/User.php:1423 #, php-format msgid "" "\n" @@ -4201,12 +4202,12 @@ msgid "" "\t\t" msgstr "" -#: src/Model/User.php:1443 +#: src/Model/User.php:1442 #, php-format msgid "Registration at %s" msgstr "" -#: src/Model/User.php:1467 +#: src/Model/User.php:1466 #, php-format msgid "" "\n" @@ -4215,7 +4216,7 @@ msgid "" "\t\t\t" msgstr "" -#: src/Model/User.php:1475 +#: src/Model/User.php:1474 #, php-format msgid "" "\n" @@ -4295,7 +4296,7 @@ msgid "Administration" msgstr "" #: src/Module/Admin/Addons/Details.php:112 src/Module/Admin/Addons/Index.php:68 -#: src/Module/BaseAdmin.php:93 src/Module/BaseSettings.php:85 +#: src/Module/BaseAdmin.php:96 src/Module/BaseSettings.php:85 msgid "Addons" msgstr "" @@ -4774,7 +4775,7 @@ msgid "" "only reflect the part of the network your node is aware of." msgstr "" -#: src/Module/Admin/Federation.php:197 src/Module/BaseAdmin.php:87 +#: src/Module/Admin/Federation.php:197 src/Module/BaseAdmin.php:90 msgid "Federation Statistics" msgstr "" @@ -4790,7 +4791,7 @@ msgstr "" msgid "Item marked for deletion." msgstr "" -#: src/Module/Admin/Item/Delete.php:65 src/Module/BaseAdmin.php:106 +#: src/Module/Admin/Item/Delete.php:65 src/Module/BaseAdmin.php:109 msgid "Delete Item" msgstr "" @@ -4819,7 +4820,7 @@ msgstr "" msgid "The GUID of the item you want to delete." msgstr "" -#: src/Module/Admin/Item/Source.php:57 src/Module/BaseAdmin.php:116 +#: src/Module/Admin/Item/Source.php:57 src/Module/BaseAdmin.php:119 msgid "Item Source" msgstr "" @@ -4882,8 +4883,8 @@ msgstr "" msgid "PHP log currently disabled." msgstr "" -#: src/Module/Admin/Logs/Settings.php:80 src/Module/BaseAdmin.php:108 -#: src/Module/BaseAdmin.php:109 +#: src/Module/Admin/Logs/Settings.php:80 src/Module/BaseAdmin.php:111 +#: src/Module/BaseAdmin.php:112 msgid "Logs" msgstr "" @@ -4936,7 +4937,7 @@ msgid "" "is readable." msgstr "" -#: src/Module/Admin/Logs/View.php:85 src/Module/BaseAdmin.php:110 +#: src/Module/Admin/Logs/View.php:85 src/Module/BaseAdmin.php:113 msgid "View Logs" msgstr "" @@ -5118,7 +5119,7 @@ msgstr "" msgid "Interactors" msgstr "" -#: src/Module/Admin/Site.php:432 src/Module/BaseAdmin.php:90 +#: src/Module/Admin/Site.php:432 src/Module/BaseAdmin.php:93 msgid "Site" msgstr "" @@ -5907,7 +5908,7 @@ msgid "" msgstr "" #: src/Module/Admin/Site.php:542 src/Module/Contact/Profile.php:273 -#: src/Module/Settings/TwoFactor/Index.php:118 +#: src/Module/Settings/TwoFactor/Index.php:121 msgid "Disabled" msgstr "" @@ -5971,7 +5972,7 @@ msgstr "" msgid "Storage Configuration" msgstr "" -#: src/Module/Admin/Storage.php:141 src/Module/BaseAdmin.php:91 +#: src/Module/Admin/Storage.php:141 src/Module/BaseAdmin.php:94 msgid "Storage" msgstr "" @@ -6187,7 +6188,7 @@ msgid "Screenshot" msgstr "" #: src/Module/Admin/Themes/Details.php:91 src/Module/Admin/Themes/Index.php:112 -#: src/Module/BaseAdmin.php:94 +#: src/Module/BaseAdmin.php:97 msgid "Themes" msgstr "" @@ -6388,7 +6389,7 @@ msgid "Permanent deletion" msgstr "" #: src/Module/Admin/Users/Index.php:150 src/Module/Admin/Users/Index.php:160 -#: src/Module/BaseAdmin.php:92 +#: src/Module/BaseAdmin.php:95 msgid "Users" msgstr "" @@ -6494,89 +6495,89 @@ msgstr "" msgid "Item was not found." msgstr "" -#: src/Module/BaseAdmin.php:54 src/Module/BaseAdmin.php:58 +#: src/Module/BaseAdmin.php:57 src/Module/BaseAdmin.php:61 msgid "Please login to continue." msgstr "" -#: src/Module/BaseAdmin.php:63 +#: src/Module/BaseAdmin.php:66 msgid "You don't have access to administration pages." msgstr "" -#: src/Module/BaseAdmin.php:67 +#: src/Module/BaseAdmin.php:70 msgid "" "Submanaged account can't access the administration pages. Please log back in " "as the main account." msgstr "" -#: src/Module/BaseAdmin.php:86 +#: src/Module/BaseAdmin.php:89 msgid "Overview" msgstr "" -#: src/Module/BaseAdmin.php:89 +#: src/Module/BaseAdmin.php:92 msgid "Configuration" msgstr "" -#: src/Module/BaseAdmin.php:95 src/Module/BaseSettings.php:63 +#: src/Module/BaseAdmin.php:98 src/Module/BaseSettings.php:63 msgid "Additional features" msgstr "" -#: src/Module/BaseAdmin.php:98 +#: src/Module/BaseAdmin.php:101 msgid "Database" msgstr "" -#: src/Module/BaseAdmin.php:99 +#: src/Module/BaseAdmin.php:102 msgid "DB updates" msgstr "" -#: src/Module/BaseAdmin.php:100 +#: src/Module/BaseAdmin.php:103 msgid "Inspect Deferred Workers" msgstr "" -#: src/Module/BaseAdmin.php:101 +#: src/Module/BaseAdmin.php:104 msgid "Inspect worker Queue" msgstr "" -#: src/Module/BaseAdmin.php:103 +#: src/Module/BaseAdmin.php:106 msgid "Tools" msgstr "" -#: src/Module/BaseAdmin.php:104 +#: src/Module/BaseAdmin.php:107 msgid "Contact Blocklist" msgstr "" -#: src/Module/BaseAdmin.php:105 +#: src/Module/BaseAdmin.php:108 msgid "Server Blocklist" msgstr "" -#: src/Module/BaseAdmin.php:112 +#: src/Module/BaseAdmin.php:115 msgid "Diagnostics" msgstr "" -#: src/Module/BaseAdmin.php:113 +#: src/Module/BaseAdmin.php:116 msgid "PHP Info" msgstr "" -#: src/Module/BaseAdmin.php:114 +#: src/Module/BaseAdmin.php:117 msgid "probe address" msgstr "" -#: src/Module/BaseAdmin.php:115 +#: src/Module/BaseAdmin.php:118 msgid "check webfinger" msgstr "" -#: src/Module/BaseAdmin.php:117 +#: src/Module/BaseAdmin.php:120 msgid "Babel" msgstr "" -#: src/Module/BaseAdmin.php:118 src/Module/Debug/ActivityPubConversion.php:142 +#: src/Module/BaseAdmin.php:121 src/Module/Debug/ActivityPubConversion.php:142 msgid "ActivityPub Conversion" msgstr "" -#: src/Module/BaseAdmin.php:127 +#: src/Module/BaseAdmin.php:130 msgid "Addon Features" msgstr "" -#: src/Module/BaseAdmin.php:128 +#: src/Module/BaseAdmin.php:131 msgid "User registrations waiting for confirmation" msgstr "" @@ -6638,8 +6639,8 @@ msgstr "" msgid "Account" msgstr "" -#: src/Module/BaseSettings.php:48 src/Module/Security/TwoFactor/Verify.php:95 -#: src/Module/Settings/TwoFactor/Index.php:110 +#: src/Module/BaseSettings.php:48 src/Module/Security/TwoFactor/Verify.php:96 +#: src/Module/Settings/TwoFactor/Index.php:113 msgid "Two-factor authentication" msgstr "" @@ -6691,7 +6692,7 @@ msgid "Only show blocked contacts" msgstr "" #: src/Module/Contact.php:330 src/Module/Contact.php:377 -#: src/Object/Post.php:329 +#: src/Object/Post.php:339 msgid "Ignored" msgstr "" @@ -6723,7 +6724,7 @@ msgstr "" msgid "Search your contacts" msgstr "" -#: src/Module/Contact.php:390 src/Module/Search/Index.php:192 +#: src/Module/Contact.php:390 src/Module/Search/Index.php:207 #, php-format msgid "Results for: %s" msgstr "" @@ -7088,7 +7089,7 @@ msgid "" msgstr "" #: src/Module/Contact/Profile.php:378 -#: src/Module/Settings/TwoFactor/Index.php:132 +#: src/Module/Settings/TwoFactor/Index.php:135 msgid "Actions" msgstr "" @@ -7147,6 +7148,7 @@ msgstr "" #: src/Module/Contact/Revoke.php:107 #: src/Module/Notifications/Introductions.php:142 #: src/Module/OAuth/Acknowledge.php:53 src/Module/Register.php:130 +#: src/Module/Settings/TwoFactor/Trusted.php:124 msgid "Yes" msgstr "" @@ -7178,8 +7180,8 @@ msgstr "" msgid "Hide" msgstr "" -#: src/Module/Conversation/Community.php:137 src/Module/Search/Index.php:137 -#: src/Module/Search/Index.php:179 +#: src/Module/Conversation/Community.php:137 src/Module/Search/Index.php:152 +#: src/Module/Search/Index.php:194 msgid "No results." msgstr "" @@ -7239,7 +7241,7 @@ msgstr "" msgid "Posts that mention or involve you" msgstr "" -#: src/Module/Conversation/Network.php:287 src/Object/Post.php:341 +#: src/Module/Conversation/Network.php:287 src/Object/Post.php:351 msgid "Starred" msgstr "" @@ -8060,6 +8062,7 @@ msgstr "" #: src/Module/Notifications/Introductions.php:142 #: src/Module/OAuth/Acknowledge.php:54 src/Module/Register.php:131 +#: src/Module/Settings/TwoFactor/Trusted.php:124 msgid "No" msgstr "" @@ -8293,19 +8296,19 @@ msgstr "" #: src/Module/Profile/Profile.php:326 src/Module/Profile/Profile.php:329 #: src/Module/Profile/Status.php:66 src/Module/Profile/Status.php:69 -#: src/Protocol/Feed.php:1017 src/Protocol/OStatus.php:1245 +#: src/Protocol/Feed.php:1018 src/Protocol/OStatus.php:1276 #, php-format msgid "%s's timeline" msgstr "" #: src/Module/Profile/Profile.php:327 src/Module/Profile/Status.php:67 -#: src/Protocol/Feed.php:1021 src/Protocol/OStatus.php:1249 +#: src/Protocol/Feed.php:1022 src/Protocol/OStatus.php:1281 #, php-format msgid "%s's posts" msgstr "" #: src/Module/Profile/Profile.php:328 src/Module/Profile/Status.php:68 -#: src/Protocol/Feed.php:1024 src/Protocol/OStatus.php:1252 +#: src/Protocol/Feed.php:1025 src/Protocol/OStatus.php:1285 #, php-format msgid "%s's comments" msgstr "" @@ -8505,15 +8508,15 @@ msgstr "" msgid "Your Webfinger address or profile URL:" msgstr "" -#: src/Module/Search/Index.php:54 +#: src/Module/Search/Index.php:69 msgid "Only logged in users are permitted to perform a search." msgstr "" -#: src/Module/Search/Index.php:74 +#: src/Module/Search/Index.php:89 msgid "Only one search per minute is permitted for not logged in users." msgstr "" -#: src/Module/Search/Index.php:190 +#: src/Module/Search/Index.php:205 #, php-format msgid "Items tagged with: %s" msgstr "" @@ -8576,7 +8579,11 @@ msgstr "" msgid "privacy policy" msgstr "" -#: src/Module/Security/Logout.php:87 +#: src/Module/Security/Logout.php:83 +#: src/Module/Security/TwoFactor/Signout.php:78 +#: src/Module/Security/TwoFactor/Signout.php:86 +#: src/Module/Security/TwoFactor/Signout.php:108 +#: src/Module/Security/TwoFactor/Signout.php:115 msgid "Logged out." msgstr "" @@ -8602,7 +8609,7 @@ msgid "Remaining recovery codes: %d" msgstr "" #: src/Module/Security/TwoFactor/Recovery.php:77 -#: src/Module/Security/TwoFactor/Verify.php:76 +#: src/Module/Security/TwoFactor/Verify.php:77 #: src/Module/Settings/TwoFactor/Verify.php:94 msgid "Invalid code, please retry." msgstr "" @@ -8618,7 +8625,6 @@ msgid "" msgstr "" #: src/Module/Security/TwoFactor/Recovery.php:98 -#: src/Module/Security/TwoFactor/Verify.php:99 #, php-format msgid "" "Don’t have your phone? Enter a two-factor recovery code" @@ -8632,19 +8638,66 @@ msgstr "" msgid "Submit recovery code and complete login" msgstr "" -#: src/Module/Security/TwoFactor/Verify.php:96 +#: src/Module/Security/TwoFactor/Signout.php:122 +msgid "Sign out of this browser?" +msgstr "" + +#: src/Module/Security/TwoFactor/Signout.php:123 +msgid "" +"

If you trust this browser, you will not be asked for verification code " +"the next time you sign in.

" +msgstr "" + +#: src/Module/Security/TwoFactor/Signout.php:124 +msgid "Sign out" +msgstr "" + +#: src/Module/Security/TwoFactor/Signout.php:126 +msgid "Trust and sign out" +msgstr "" + +#: src/Module/Security/TwoFactor/Trust.php:89 +msgid "Couldn't save browser to Cookie." +msgstr "" + +#: src/Module/Security/TwoFactor/Trust.php:119 +msgid "Trust this browser?" +msgstr "" + +#: src/Module/Security/TwoFactor/Trust.php:120 +msgid "" +"

If you choose to trust this browser, you will not be asked for a " +"verification code the next time you sign in.

" +msgstr "" + +#: src/Module/Security/TwoFactor/Trust.php:121 +msgid "Not now" +msgstr "" + +#: src/Module/Security/TwoFactor/Trust.php:122 +msgid "Don't trust" +msgstr "" + +#: src/Module/Security/TwoFactor/Trust.php:123 +msgid "Trust" +msgstr "" + +#: src/Module/Security/TwoFactor/Verify.php:97 msgid "" "

Open the two-factor authentication app on your device to get an " "authentication code and verify your identity.

" msgstr "" #: src/Module/Security/TwoFactor/Verify.php:100 -#: src/Module/Settings/TwoFactor/Verify.php:154 -msgid "Please enter a code from your authentication app" +#, php-format +msgid "" +"If you do not have access to your authentication code you can use a two-factor recovery code." msgstr "" #: src/Module/Security/TwoFactor/Verify.php:101 -msgid "This is my two-factor authenticator app device" +#: src/Module/Settings/TwoFactor/Verify.php:154 +msgid "Please enter a code from your authentication app" msgstr "" #: src/Module/Security/TwoFactor/Verify.php:102 @@ -9651,99 +9704,95 @@ msgstr "" msgid "Generate" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:67 +#: src/Module/Settings/TwoFactor/Index.php:68 msgid "Two-factor authentication successfully disabled." msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:93 -msgid "Wrong Password" -msgstr "" - -#: src/Module/Settings/TwoFactor/Index.php:113 +#: src/Module/Settings/TwoFactor/Index.php:116 msgid "" "

Use an application on a mobile device to get two-factor authentication " "codes when prompted on login.

" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:117 +#: src/Module/Settings/TwoFactor/Index.php:120 msgid "Authenticator app" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:118 +#: src/Module/Settings/TwoFactor/Index.php:121 msgid "Configured" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:118 +#: src/Module/Settings/TwoFactor/Index.php:121 msgid "Not Configured" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:119 +#: src/Module/Settings/TwoFactor/Index.php:122 msgid "

You haven't finished configuring your authenticator app.

" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:120 +#: src/Module/Settings/TwoFactor/Index.php:123 msgid "

Your authenticator app is correctly configured.

" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:122 +#: src/Module/Settings/TwoFactor/Index.php:125 msgid "Recovery codes" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:123 +#: src/Module/Settings/TwoFactor/Index.php:126 msgid "Remaining valid codes" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:125 +#: src/Module/Settings/TwoFactor/Index.php:128 msgid "" "

These one-use codes can replace an authenticator app code in case you " "have lost access to it.

" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:127 +#: src/Module/Settings/TwoFactor/Index.php:130 msgid "App-specific passwords" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:128 +#: src/Module/Settings/TwoFactor/Index.php:131 msgid "Generated app-specific passwords" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:130 +#: src/Module/Settings/TwoFactor/Index.php:133 msgid "" "

These randomly generated passwords allow you to authenticate on apps not " "supporting two-factor authentication.

" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:133 +#: src/Module/Settings/TwoFactor/Index.php:136 msgid "Current password:" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:133 +#: src/Module/Settings/TwoFactor/Index.php:136 msgid "" "You need to provide your current password to change two-factor " "authentication settings." msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:134 +#: src/Module/Settings/TwoFactor/Index.php:137 msgid "Enable two-factor authentication" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:135 +#: src/Module/Settings/TwoFactor/Index.php:138 msgid "Disable two-factor authentication" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:136 +#: src/Module/Settings/TwoFactor/Index.php:139 msgid "Show recovery codes" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:137 +#: src/Module/Settings/TwoFactor/Index.php:140 msgid "Manage app-specific passwords" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:138 +#: src/Module/Settings/TwoFactor/Index.php:141 msgid "Manage trusted browsers" msgstr "" -#: src/Module/Settings/TwoFactor/Index.php:139 +#: src/Module/Settings/TwoFactor/Index.php:142 msgid "Finish app configuration" msgstr "" @@ -9785,34 +9834,38 @@ msgstr "" msgid "Trusted browser successfully removed." msgstr "" -#: src/Module/Settings/TwoFactor/Trusted.php:133 +#: src/Module/Settings/TwoFactor/Trusted.php:134 msgid "Two-factor Trusted Browsers" msgstr "" -#: src/Module/Settings/TwoFactor/Trusted.php:134 +#: src/Module/Settings/TwoFactor/Trusted.php:135 msgid "" "Trusted browsers are individual browsers you chose to skip two-factor " "authentication to access Friendica. Please use this feature sparingly, as it " "can negate the benefit of two-factor authentication." msgstr "" -#: src/Module/Settings/TwoFactor/Trusted.php:135 +#: src/Module/Settings/TwoFactor/Trusted.php:136 msgid "Device" msgstr "" -#: src/Module/Settings/TwoFactor/Trusted.php:136 +#: src/Module/Settings/TwoFactor/Trusted.php:137 msgid "OS" msgstr "" -#: src/Module/Settings/TwoFactor/Trusted.php:138 +#: src/Module/Settings/TwoFactor/Trusted.php:139 msgid "Trusted" msgstr "" -#: src/Module/Settings/TwoFactor/Trusted.php:139 -msgid "Last Use" +#: src/Module/Settings/TwoFactor/Trusted.php:140 +msgid "Created At" msgstr "" #: src/Module/Settings/TwoFactor/Trusted.php:141 +msgid "Last Use" +msgstr "" + +#: src/Module/Settings/TwoFactor/Trusted.php:143 msgid "Remove All" msgstr "" @@ -10285,205 +10338,205 @@ msgstr "" msgid "%1$s commented on your thread %2$s" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:221 -#: src/Navigation/Notifications/Repository/Notify.php:735 +#: src/Navigation/Notifications/Repository/Notify.php:222 +#: src/Navigation/Notifications/Repository/Notify.php:736 msgid "[Friendica:Notify]" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:285 +#: src/Navigation/Notifications/Repository/Notify.php:286 #, php-format msgid "%s New mail received at %s" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:287 +#: src/Navigation/Notifications/Repository/Notify.php:288 #, php-format msgid "%1$s sent you a new private message at %2$s." msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:288 +#: src/Navigation/Notifications/Repository/Notify.php:289 msgid "a private message" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:288 +#: src/Navigation/Notifications/Repository/Notify.php:289 #, php-format msgid "%1$s sent you %2$s." msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:290 +#: src/Navigation/Notifications/Repository/Notify.php:291 #, php-format msgid "Please visit %s to view and/or reply to your private messages." msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:320 +#: src/Navigation/Notifications/Repository/Notify.php:321 #, php-format msgid "%1$s commented on %2$s's %3$s %4$s" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:325 +#: src/Navigation/Notifications/Repository/Notify.php:326 #, php-format msgid "%1$s commented on your %2$s %3$s" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:329 +#: src/Navigation/Notifications/Repository/Notify.php:330 #, php-format msgid "%1$s commented on their %2$s %3$s" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:333 -#: src/Navigation/Notifications/Repository/Notify.php:769 +#: src/Navigation/Notifications/Repository/Notify.php:334 +#: src/Navigation/Notifications/Repository/Notify.php:770 #, php-format msgid "%1$s Comment to conversation #%2$d by %3$s" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:335 +#: src/Navigation/Notifications/Repository/Notify.php:336 #, php-format msgid "%s commented on an item/conversation you have been following." msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:339 -#: src/Navigation/Notifications/Repository/Notify.php:354 -#: src/Navigation/Notifications/Repository/Notify.php:373 -#: src/Navigation/Notifications/Repository/Notify.php:784 +#: src/Navigation/Notifications/Repository/Notify.php:340 +#: src/Navigation/Notifications/Repository/Notify.php:355 +#: src/Navigation/Notifications/Repository/Notify.php:374 +#: src/Navigation/Notifications/Repository/Notify.php:785 #, php-format msgid "Please visit %s to view and/or reply to the conversation." msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:346 +#: src/Navigation/Notifications/Repository/Notify.php:347 #, php-format msgid "%s %s posted to your profile wall" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:348 +#: src/Navigation/Notifications/Repository/Notify.php:349 #, php-format msgid "%1$s posted to your profile wall at %2$s" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:349 +#: src/Navigation/Notifications/Repository/Notify.php:350 #, php-format msgid "%1$s posted to [url=%2$s]your wall[/url]" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:361 +#: src/Navigation/Notifications/Repository/Notify.php:362 #, php-format msgid "%1$s %2$s poked you" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:363 +#: src/Navigation/Notifications/Repository/Notify.php:364 #, php-format msgid "%1$s poked you at %2$s" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:364 +#: src/Navigation/Notifications/Repository/Notify.php:365 #, php-format msgid "%1$s [url=%2$s]poked you[/url]." msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:381 +#: src/Navigation/Notifications/Repository/Notify.php:382 #, php-format msgid "%s Introduction received" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:383 +#: src/Navigation/Notifications/Repository/Notify.php:384 #, php-format msgid "You've received an introduction from '%1$s' at %2$s" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:384 +#: src/Navigation/Notifications/Repository/Notify.php:385 #, php-format msgid "You've received [url=%1$s]an introduction[/url] from %2$s." msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:389 -#: src/Navigation/Notifications/Repository/Notify.php:435 +#: src/Navigation/Notifications/Repository/Notify.php:390 +#: src/Navigation/Notifications/Repository/Notify.php:436 #, php-format msgid "You may visit their profile at %s" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:391 +#: src/Navigation/Notifications/Repository/Notify.php:392 #, php-format msgid "Please visit %s to approve or reject the introduction." msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:398 +#: src/Navigation/Notifications/Repository/Notify.php:399 #, php-format msgid "%s A new person is sharing with you" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:400 #: src/Navigation/Notifications/Repository/Notify.php:401 +#: src/Navigation/Notifications/Repository/Notify.php:402 #, php-format msgid "%1$s is sharing with you at %2$s" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:408 +#: src/Navigation/Notifications/Repository/Notify.php:409 #, php-format msgid "%s You have a new follower" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:410 #: src/Navigation/Notifications/Repository/Notify.php:411 +#: src/Navigation/Notifications/Repository/Notify.php:412 #, php-format msgid "You have a new follower at %2$s : %1$s" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:424 +#: src/Navigation/Notifications/Repository/Notify.php:425 #, php-format msgid "%s Friend suggestion received" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:426 +#: src/Navigation/Notifications/Repository/Notify.php:427 #, php-format msgid "You've received a friend suggestion from '%1$s' at %2$s" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:427 +#: src/Navigation/Notifications/Repository/Notify.php:428 #, php-format msgid "You've received [url=%1$s]a friend suggestion[/url] for %2$s from %3$s." msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:433 +#: src/Navigation/Notifications/Repository/Notify.php:434 msgid "Name:" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:434 +#: src/Navigation/Notifications/Repository/Notify.php:435 msgid "Photo:" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:437 +#: src/Navigation/Notifications/Repository/Notify.php:438 #, php-format msgid "Please visit %s to approve or reject the suggestion." msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:445 -#: src/Navigation/Notifications/Repository/Notify.php:460 +#: src/Navigation/Notifications/Repository/Notify.php:446 +#: src/Navigation/Notifications/Repository/Notify.php:461 #, php-format msgid "%s Connection accepted" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:447 -#: src/Navigation/Notifications/Repository/Notify.php:462 -#, php-format -msgid "'%1$s' has accepted your connection request at %2$s" -msgstr "" - #: src/Navigation/Notifications/Repository/Notify.php:448 #: src/Navigation/Notifications/Repository/Notify.php:463 #, php-format +msgid "'%1$s' has accepted your connection request at %2$s" +msgstr "" + +#: src/Navigation/Notifications/Repository/Notify.php:449 +#: src/Navigation/Notifications/Repository/Notify.php:464 +#, php-format msgid "%2$s has accepted your [url=%1$s]connection request[/url]." msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:453 +#: src/Navigation/Notifications/Repository/Notify.php:454 msgid "" "You are now mutual friends and may exchange status updates, photos, and " "email without restriction." msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:455 +#: src/Navigation/Notifications/Repository/Notify.php:456 #, php-format msgid "Please visit %s if you wish to make any changes to this relationship." msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:468 +#: src/Navigation/Notifications/Repository/Notify.php:469 #, php-format msgid "" "'%1$s' has chosen to accept you a fan, which restricts some forms of " @@ -10492,33 +10545,33 @@ msgid "" "automatically." msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:470 +#: src/Navigation/Notifications/Repository/Notify.php:471 #, php-format msgid "" "'%1$s' may choose to extend this into a two-way or more permissive " "relationship in the future." msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:472 +#: src/Navigation/Notifications/Repository/Notify.php:473 #, php-format msgid "Please visit %s if you wish to make any changes to this relationship." msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:482 +#: src/Navigation/Notifications/Repository/Notify.php:483 msgid "registration request" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:484 -#, php-format -msgid "You've received a registration request from '%1$s' at %2$s" -msgstr "" - #: src/Navigation/Notifications/Repository/Notify.php:485 #, php-format +msgid "You've received a registration request from '%1$s' at %2$s" +msgstr "" + +#: src/Navigation/Notifications/Repository/Notify.php:486 +#, php-format msgid "You've received a [url=%1$s]registration request[/url] from %2$s." msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:490 +#: src/Navigation/Notifications/Repository/Notify.php:491 #, php-format msgid "" "Full Name:\t%s\n" @@ -10526,17 +10579,17 @@ msgid "" "Login Name:\t%s (%s)" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:496 +#: src/Navigation/Notifications/Repository/Notify.php:497 #, php-format msgid "Please visit %s to approve or reject the request." msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:763 +#: src/Navigation/Notifications/Repository/Notify.php:764 #, php-format msgid "%s %s tagged you" msgstr "" -#: src/Navigation/Notifications/Repository/Notify.php:766 +#: src/Navigation/Notifications/Repository/Notify.php:767 #, php-format msgid "%s %s shared a new post" msgstr "" @@ -10563,244 +10616,244 @@ msgstr "" msgid "%s posted an update." msgstr "" -#: src/Object/Post.php:134 +#: src/Object/Post.php:136 msgid "Private Message" msgstr "" -#: src/Object/Post.php:137 +#: src/Object/Post.php:140 msgid "Public Message" msgstr "" -#: src/Object/Post.php:140 +#: src/Object/Post.php:144 msgid "Unlisted Message" msgstr "" -#: src/Object/Post.php:170 +#: src/Object/Post.php:179 msgid "This entry was edited" msgstr "" -#: src/Object/Post.php:198 +#: src/Object/Post.php:207 msgid "Connector Message" msgstr "" -#: src/Object/Post.php:213 src/Object/Post.php:215 +#: src/Object/Post.php:222 src/Object/Post.php:224 msgid "Edit" msgstr "" -#: src/Object/Post.php:239 +#: src/Object/Post.php:248 msgid "Delete globally" msgstr "" -#: src/Object/Post.php:239 +#: src/Object/Post.php:248 msgid "Remove locally" msgstr "" -#: src/Object/Post.php:255 +#: src/Object/Post.php:264 #, php-format msgid "Block %s" msgstr "" -#: src/Object/Post.php:260 +#: src/Object/Post.php:269 msgid "Save to folder" msgstr "" -#: src/Object/Post.php:294 +#: src/Object/Post.php:304 msgid "I will attend" msgstr "" -#: src/Object/Post.php:294 +#: src/Object/Post.php:304 msgid "I will not attend" msgstr "" -#: src/Object/Post.php:294 +#: src/Object/Post.php:304 msgid "I might attend" msgstr "" -#: src/Object/Post.php:324 +#: src/Object/Post.php:334 msgid "Ignore thread" msgstr "" -#: src/Object/Post.php:325 +#: src/Object/Post.php:335 msgid "Unignore thread" msgstr "" -#: src/Object/Post.php:326 +#: src/Object/Post.php:336 msgid "Toggle ignore status" msgstr "" -#: src/Object/Post.php:336 +#: src/Object/Post.php:346 msgid "Add star" msgstr "" -#: src/Object/Post.php:337 +#: src/Object/Post.php:347 msgid "Remove star" msgstr "" -#: src/Object/Post.php:338 +#: src/Object/Post.php:348 msgid "Toggle star status" msgstr "" -#: src/Object/Post.php:349 +#: src/Object/Post.php:359 msgid "Pin" msgstr "" -#: src/Object/Post.php:350 +#: src/Object/Post.php:360 msgid "Unpin" msgstr "" -#: src/Object/Post.php:351 +#: src/Object/Post.php:361 msgid "Toggle pin status" msgstr "" -#: src/Object/Post.php:354 +#: src/Object/Post.php:364 msgid "Pinned" msgstr "" -#: src/Object/Post.php:359 +#: src/Object/Post.php:369 msgid "Add tag" msgstr "" -#: src/Object/Post.php:372 +#: src/Object/Post.php:382 msgid "Quote share this" msgstr "" -#: src/Object/Post.php:372 +#: src/Object/Post.php:382 msgid "Quote Share" msgstr "" -#: src/Object/Post.php:375 +#: src/Object/Post.php:385 msgid "Reshare this" msgstr "" -#: src/Object/Post.php:375 +#: src/Object/Post.php:385 msgid "Reshare" msgstr "" -#: src/Object/Post.php:376 +#: src/Object/Post.php:386 msgid "Cancel your Reshare" msgstr "" -#: src/Object/Post.php:376 +#: src/Object/Post.php:386 msgid "Unshare" msgstr "" -#: src/Object/Post.php:423 +#: src/Object/Post.php:433 #, php-format msgid "%s (Received %s)" msgstr "" -#: src/Object/Post.php:428 +#: src/Object/Post.php:438 msgid "Comment this item on your system" msgstr "" -#: src/Object/Post.php:428 +#: src/Object/Post.php:438 msgid "Remote comment" msgstr "" -#: src/Object/Post.php:449 +#: src/Object/Post.php:459 msgid "Share via ..." msgstr "" -#: src/Object/Post.php:449 +#: src/Object/Post.php:459 msgid "Share via external services" msgstr "" -#: src/Object/Post.php:478 +#: src/Object/Post.php:488 msgid "to" msgstr "" -#: src/Object/Post.php:479 +#: src/Object/Post.php:489 msgid "via" msgstr "" -#: src/Object/Post.php:480 +#: src/Object/Post.php:490 msgid "Wall-to-Wall" msgstr "" -#: src/Object/Post.php:481 +#: src/Object/Post.php:491 msgid "via Wall-To-Wall:" msgstr "" -#: src/Object/Post.php:523 +#: src/Object/Post.php:533 #, php-format msgid "Reply to %s" msgstr "" -#: src/Object/Post.php:526 +#: src/Object/Post.php:536 msgid "More" msgstr "" -#: src/Object/Post.php:544 +#: src/Object/Post.php:554 msgid "Notifier task is pending" msgstr "" -#: src/Object/Post.php:545 +#: src/Object/Post.php:555 msgid "Delivery to remote servers is pending" msgstr "" -#: src/Object/Post.php:546 +#: src/Object/Post.php:556 msgid "Delivery to remote servers is underway" msgstr "" -#: src/Object/Post.php:547 +#: src/Object/Post.php:557 msgid "Delivery to remote servers is mostly done" msgstr "" -#: src/Object/Post.php:548 +#: src/Object/Post.php:558 msgid "Delivery to remote servers is done" msgstr "" -#: src/Object/Post.php:568 +#: src/Object/Post.php:578 #, php-format msgid "%d comment" msgid_plural "%d comments" msgstr[0] "" msgstr[1] "" -#: src/Object/Post.php:569 +#: src/Object/Post.php:579 msgid "Show more" msgstr "" -#: src/Object/Post.php:570 +#: src/Object/Post.php:580 msgid "Show fewer" msgstr "" -#: src/Protocol/OStatus.php:1648 +#: src/Protocol/OStatus.php:1705 #, php-format msgid "%s is now following %s." msgstr "" -#: src/Protocol/OStatus.php:1649 +#: src/Protocol/OStatus.php:1706 msgid "following" msgstr "" -#: src/Protocol/OStatus.php:1652 +#: src/Protocol/OStatus.php:1709 #, php-format msgid "%s stopped following %s." msgstr "" -#: src/Protocol/OStatus.php:1653 +#: src/Protocol/OStatus.php:1710 msgid "stopped following" msgstr "" -#: src/Render/FriendicaSmartyEngine.php:52 +#: src/Render/FriendicaSmartyEngine.php:65 msgid "The folder view/smarty3/ must be writable by webserver." msgstr "" -#: src/Security/Authentication.php:221 +#: src/Security/Authentication.php:226 msgid "Login failed." msgstr "" -#: src/Security/Authentication.php:262 +#: src/Security/Authentication.php:267 msgid "Login failed. Please check your credentials." msgstr "" -#: src/Security/Authentication.php:360 +#: src/Security/Authentication.php:369 #, php-format msgid "Welcome %s" msgstr "" -#: src/Security/Authentication.php:361 +#: src/Security/Authentication.php:370 msgid "Please upload a profile photo." msgstr "" @@ -10898,15 +10951,15 @@ msgstr "" msgid "%1$d %2$s ago" msgstr "" -#: src/Worker/Delivery.php:524 +#: src/Worker/Delivery.php:525 msgid "(no subject)" msgstr "" -#: src/Worker/PushSubscription.php:103 +#: src/Worker/PushSubscription.php:112 msgid "Notification from Friendica" msgstr "" -#: src/Worker/PushSubscription.php:104 +#: src/Worker/PushSubscription.php:113 msgid "Empty Post" msgstr "" @@ -11052,39 +11105,39 @@ msgstr "" msgid "Leave background image and color empty for theme defaults" msgstr "" -#: view/theme/frio/php/Image.php:40 +#: view/theme/frio/php/Image.php:39 msgid "Top Banner" msgstr "" -#: view/theme/frio/php/Image.php:40 +#: view/theme/frio/php/Image.php:39 msgid "" "Resize image to the width of the screen and show background color below on " "long pages." msgstr "" -#: view/theme/frio/php/Image.php:41 +#: view/theme/frio/php/Image.php:40 msgid "Full screen" msgstr "" -#: view/theme/frio/php/Image.php:41 +#: view/theme/frio/php/Image.php:40 msgid "" "Resize image to fill entire screen, clipping either the right or the bottom." msgstr "" -#: view/theme/frio/php/Image.php:42 +#: view/theme/frio/php/Image.php:41 msgid "Single row mosaic" msgstr "" -#: view/theme/frio/php/Image.php:42 +#: view/theme/frio/php/Image.php:41 msgid "" "Resize image to repeat it on a single row, either vertical or horizontal." msgstr "" -#: view/theme/frio/php/Image.php:43 +#: view/theme/frio/php/Image.php:42 msgid "Mosaic" msgstr "" -#: view/theme/frio/php/Image.php:43 +#: view/theme/frio/php/Image.php:42 msgid "Repeat image to fill the screen." msgstr "" From 2248850f78100cebe5bcc2d4d073e419b3352cc1 Mon Sep 17 00:00:00 2001 From: Philipp Date: Sat, 25 Jun 2022 23:06:42 +0200 Subject: [PATCH 6/7] add anything .. --- tests/src/Security/TwoFactor/Factory/TrustedBrowserTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/Security/TwoFactor/Factory/TrustedBrowserTest.php b/tests/src/Security/TwoFactor/Factory/TrustedBrowserTest.php index baddfb3791..7bb07a1335 100644 --- a/tests/src/Security/TwoFactor/Factory/TrustedBrowserTest.php +++ b/tests/src/Security/TwoFactor/Factory/TrustedBrowserTest.php @@ -71,7 +71,7 @@ class TrustedBrowserTest extends MockedTest { $factory = new TrustedBrowser(new NullLogger()); - $uid = 42; + $uid = 42; $userAgent = 'PHPUnit'; $trustedBrowser = $factory->createForUserWithUserAgent($uid, $userAgent, true); From b67e488236170dfe56a2122db84369ba6b77f706 Mon Sep 17 00:00:00 2001 From: Philipp Date: Sun, 26 Jun 2022 10:13:32 +0200 Subject: [PATCH 7/7] adaptions --- .../TwoFactor/{Signout.php => SignOut.php} | 16 ++++++------ src/Module/Settings/TwoFactor/Index.php | 25 +++++++++++-------- static/routes.config.php | 2 +- 3 files changed, 24 insertions(+), 19 deletions(-) rename src/Module/Security/TwoFactor/{Signout.php => SignOut.php} (87%) diff --git a/src/Module/Security/TwoFactor/Signout.php b/src/Module/Security/TwoFactor/SignOut.php similarity index 87% rename from src/Module/Security/TwoFactor/Signout.php rename to src/Module/Security/TwoFactor/SignOut.php index 3e52b27e71..20b7f039d6 100644 --- a/src/Module/Security/TwoFactor/Signout.php +++ b/src/Module/Security/TwoFactor/SignOut.php @@ -38,7 +38,7 @@ use Psr\Log\LoggerInterface; * * @package Friendica\Module\TwoFactor */ -class Signout extends BaseModule +class SignOut extends BaseModule { protected $errors = []; @@ -47,15 +47,15 @@ class Signout extends BaseModule /** @var Cookie */ protected $cookie; /** @var TwoFactor\Repository\TrustedBrowser */ - protected $trustedBrowserRepositoy; + protected $trustedBrowserRepository; - public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, IHandleSessions $session, Cookie $cookie, TwoFactor\Repository\TrustedBrowser $trustedBrowserRepositoy, Profiler $profiler, Response $response, array $server, array $parameters = []) + public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, IHandleSessions $session, Cookie $cookie, TwoFactor\Repository\TrustedBrowser $trustedBrowserRepository, Profiler $profiler, Response $response, array $server, array $parameters = []) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); - $this->session = $session; - $this->cookie = $cookie; - $this->trustedBrowserRepositoy = $trustedBrowserRepositoy; + $this->session = $session; + $this->cookie = $cookie; + $this->trustedBrowserRepository = $trustedBrowserRepository; } protected function post(array $request = []) @@ -79,7 +79,7 @@ class Signout extends BaseModule $this->baseUrl->redirect(); break; case 'sign_out': - $this->trustedBrowserRepositoy->removeForUser(local_user(), $this->cookie->get('2fa_cookie_hash')); + $this->trustedBrowserRepository->removeForUser(local_user(), $this->cookie->get('2fa_cookie_hash')); $this->cookie->clear(); $this->session->clear(); @@ -99,7 +99,7 @@ class Signout extends BaseModule } try { - $trustedBrowser = $this->trustedBrowserRepositoy->selectOneByHash($this->cookie->get('2fa_cookie_hash')); + $trustedBrowser = $this->trustedBrowserRepository->selectOneByHash($this->cookie->get('2fa_cookie_hash')); if (!$trustedBrowser->trusted) { $trusted = $this->cookie->get('2fa_cookie_hash'); $this->cookie->reset(['2fa_cookie_hash' => $trusted]); diff --git a/src/Module/Settings/TwoFactor/Index.php b/src/Module/Settings/TwoFactor/Index.php index 98826824b9..0da49f3177 100644 --- a/src/Module/Settings/TwoFactor/Index.php +++ b/src/Module/Settings/TwoFactor/Index.php @@ -45,8 +45,8 @@ class Index extends BaseSettings try { User::getIdFromPasswordAuthentication(local_user(), $_POST['password'] ?? ''); - $has_secret = (bool) DI::pConfig()->get(local_user(), '2fa', 'secret'); - $verified = DI::pConfig()->get(local_user(), '2fa', 'verified'); + $has_secret = (bool)DI::pConfig()->get(local_user(), '2fa', 'secret'); + $verified = DI::pConfig()->get(local_user(), '2fa', 'verified'); switch ($_POST['action'] ?? '') { case 'enable': @@ -55,7 +55,8 @@ class Index extends BaseSettings DI::pConfig()->set(local_user(), '2fa', 'secret', $Google2FA->generateSecretKey(32)); - DI::baseUrl()->redirect('settings/2fa/recovery?t=' . self::getFormSecurityToken('settings_2fa_password')); + DI::baseUrl() + ->redirect('settings/2fa/recovery?t=' . self::getFormSecurityToken('settings_2fa_password')); } break; case 'disable': @@ -71,29 +72,33 @@ class Index extends BaseSettings break; case 'recovery': if ($has_secret) { - DI::baseUrl()->redirect('settings/2fa/recovery?t=' . self::getFormSecurityToken('settings_2fa_password')); + DI::baseUrl() + ->redirect('settings/2fa/recovery?t=' . self::getFormSecurityToken('settings_2fa_password')); } break; case 'app_specific': if ($has_secret) { - DI::baseUrl()->redirect('settings/2fa/app_specific?t=' . self::getFormSecurityToken('settings_2fa_password')); + DI::baseUrl() + ->redirect('settings/2fa/app_specific?t=' . self::getFormSecurityToken('settings_2fa_password')); } break; case 'trusted': if ($has_secret) { - DI::baseUrl()->redirect('settings/2fa/trusted?t=' . self::getFormSecurityToken('settings_2fa_password')); + DI::baseUrl() + ->redirect('settings/2fa/trusted?t=' . self::getFormSecurityToken('settings_2fa_password')); } break; case 'configure': if (!$verified) { - DI::baseUrl()->redirect('settings/2fa/verify?t=' . self::getFormSecurityToken('settings_2fa_password')); + DI::baseUrl() + ->redirect('settings/2fa/verify?t=' . self::getFormSecurityToken('settings_2fa_password')); } break; } + } catch (FoundException $exception) { + // Nothing to do here } catch (\Exception $e) { - if (!($e instanceof FoundException)) { - notice(DI::l10n()->t($e->getMessage())); - } + notice(DI::l10n()->t($e->getMessage())); } } diff --git a/static/routes.config.php b/static/routes.config.php index 9c82c8e1f1..dac56a1255 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -166,7 +166,7 @@ return [ '[/]' => [Module\Security\TwoFactor\Verify::class, [R::GET, R::POST]], '/recovery' => [Module\Security\TwoFactor\Recovery::class, [R::GET, R::POST]], '/trust' => [Module\Security\TwoFactor\Trust::class, [R::GET, R::POST]], - '/signout' => [Module\Security\TwoFactor\Signout::class, [R::GET, R::POST]], + '/signout' => [Module\Security\TwoFactor\SignOut::class, [R::GET, R::POST]], ], '/api' => [