use Friendica\Core\System;
use Friendica\Core\Theme;
use Friendica\Database\Database;
-use Friendica\Model\Contact;
-use Friendica\Model\Profile;
use Friendica\Module\Special\HTTPException as ModuleHTTPException;
use Friendica\Network\HTTPException;
use Friendica\Protocol\ATProtocol\DID;
+use Friendica\Security\OpenWebAuth;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\HTTPInputData;
use Friendica\Util\HTTPSignature;
/** @var string The name of the current mobile theme */
private $currentMobileTheme;
+ /** @var Authentication */
+ private $auth;
+
/**
* @var IManageConfigValues The config
*/
* @param DbaDefinition $dbaDefinition
* @param ViewDefinition $viewDefinition
*/
- public function __construct(Database $database, IManageConfigValues $config, App\Mode $mode, BaseURL $baseURL, LoggerInterface $logger, Profiler $profiler, L10n $l10n, Arguments $args, IManagePersonalConfigValues $pConfig, IHandleUserSessions $session, DbaDefinition $dbaDefinition, ViewDefinition $viewDefinition)
+ public function __construct(Authentication $auth, Database $database, IManageConfigValues $config, App\Mode $mode, BaseURL $baseURL, LoggerInterface $logger, Profiler $profiler, L10n $l10n, Arguments $args, IManagePersonalConfigValues $pConfig, IHandleUserSessions $session, DbaDefinition $dbaDefinition, ViewDefinition $viewDefinition)
{
+ $this->auth = $auth;
$this->database = $database;
$this->config = $config;
$this->mode = $mode;
if ($this->mode->isNormal() && !$this->mode->isBackend()) {
$requester = HTTPSignature::getSigner('', $server);
if (!empty($requester)) {
- Profile::addVisitorCookieForHandle($requester);
+ OpenWebAuth::addVisitorCookieForHandle($requester);
}
}
// Valid profile links contain a path with "/profile/" and no query parameters
if ((parse_url($_GET['zrl'], PHP_URL_QUERY) == '') &&
strpos(parse_url($_GET['zrl'], PHP_URL_PATH) ?? '', '/profile/') !== false) {
- if ($this->session->get('visitor_home') != $_GET['zrl']) {
- $this->session->set('my_url', $_GET['zrl']);
- $this->session->set('authenticated', 0);
-
- $remote_contact = Contact::getByURL($_GET['zrl'], false, ['subscribe']);
- if (!empty($remote_contact['subscribe'])) {
- $_SESSION['remote_comment'] = $remote_contact['subscribe'];
- }
- }
-
- Model\Profile::zrlInit();
+ $this->auth->setUnauthenticatedVisitor($_GET['zrl']);
+ OpenWebAuth::zrlInit();
} else {
// Someone came with an invalid parameter, maybe as a DDoS attempt
// We simply stop processing here
if (!empty($_GET['owt']) && $this->mode->isNormal()) {
$token = $_GET['owt'];
- Model\Profile::openWebAuthInit($token);
+ OpenWebAuth::init($token);
}
if (!$this->mode->isBackend()) {
$auth->withSession($this);
}
- if (empty($_SESSION['authenticated'])) {
+ if ($this->session->isUnauthenticated()) {
header('X-Account-Management-Status: none');
}
use Friendica\Core\Session\Capability\IHandleUserSessions;
use Friendica\Database\Database;
use Friendica\Model\Contact;
-use Friendica\Model\Profile;
use Friendica\Model\User;
use Friendica\Module\Conversation\Community;
use Friendica\Module\Home;
use Friendica\Module\Security\Login;
use Friendica\Network\HTTPException;
+use Friendica\Security\OpenWebAuth;
class Nav
{
$gdirpath = 'directory';
if ($this->config->get('system', 'singleuser') && $this->config->get('system', 'directory')) {
- $gdirpath = Profile::zrl($this->config->get('system', 'directory'), true);
+ $gdirpath = OpenWebAuth::getZrlUrl($this->config->get('system', 'directory'), true);
}
if (Feature::isEnabled($this->session->getLocalUserId(), Feature::COMMUNITY) && (($this->session->getLocalUserId() || $this->config->get('system', 'community_page_style') != Community::DISABLED_VISITOR) &&
use Friendica\Model\Circle;
use Friendica\Model\Item;
use Friendica\Model\Post;
-use Friendica\Model\Profile;
+use Friendica\Security\OpenWebAuth;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Temporal;
$nv['random'] = DI::l10n()->t('Random Profile');
$nv['inv'] = DI::l10n()->t('Invite Friends');
$nv['directory'] = DI::l10n()->t('Global Directory');
- $nv['global_dir'] = Profile::zrl($global_dir, true);
+ $nv['global_dir'] = OpenWebAuth::getZrlUrl($global_dir, true);
$nv['local_directory'] = DI::l10n()->t('Local Directory');
$aside = [];
public function getMyUrl(): string;
/**
- * Returns if the current visitor is authenticated
+ * Returns if the current visitor is a local user
*
- * @return bool "true" when visitor is either a local or remote user
+ * @return bool "true" when visitor is a local user
*/
public function isAuthenticated(): bool;
*/
public function isModerator(): bool;
+ /**
+ * Returns if the current visitor is a verified remote user
+ *
+ * @return bool "true" when visitor is a verified remote user
+ */
+ public function isVisitor(): bool;
+
+ /**
+ * Returns if the current visitor is an unauthenticated user
+ *
+ * @return bool "true" when visitor is an unauthenticated user
+ */
+ public function isUnauthenticated(): bool;
+
/**
* Returns User ID of the managed user in case it's a different identity
*
/** {@inheritDoc} */
public function isAuthenticated(): bool
{
- return $this->session->get('authenticated', false);
+ return $this->session->get('authenticated', false) && $this->getLocalUserId();
}
/** {@inheritDoc} */
return User::isModerator($this->getLocalUserId());
}
+ /** {@inheritDoc} */
+ public function isVisitor(): bool
+ {
+ return $this->session->get('authenticated', false) && $this->session->get('visitor_id') && !$this->session->get('uid');
+ }
+
+ /** {@inheritDoc} */
+ public function isUnauthenticated(): bool
+ {
+ return !$this->session->get('authenticated', false);
+ }
+
/** {@inheritDoc} */
public function setVisitorsContacts(string $my_url)
{
use Friendica\Core\Protocol;
use Friendica\Core\Renderer;
use Friendica\Core\Search;
-use Friendica\Core\System;
use Friendica\Core\Worker;
use Friendica\Database\DBA;
use Friendica\DI;
-use Friendica\Network\HTTPClient\Client\HttpClientAccept;
-use Friendica\Network\HTTPClient\Client\HttpClientOptions;
-use Friendica\Network\HTTPClient\Client\HttpClientRequest;
use Friendica\Network\HTTPException;
-use Friendica\Network\HTTPException\InternalServerErrorException;
use Friendica\Protocol\Activity;
use Friendica\Protocol\Diaspora;
use Friendica\Security\PermissionSet\Entity\PermissionSet;
use Friendica\Util\DateTimeFormat;
-use Friendica\Util\HTTPSignature;
-use Friendica\Util\Network;
use Friendica\Util\Proxy;
use Friendica\Util\Strings;
]);
}
- /**
- * Process the 'zrl' parameter and initiate the remote authentication.
- *
- * This method checks if the visitor has a public contact entry and
- * redirects the visitor to his/her instance to start the magic auth (Authentication)
- * process.
- *
- * Ported from Hubzilla: https://framagit.org/hubzilla/core/blob/master/include/channel.php
- *
- * The implementation for Friendica sadly differs in some points from the one for Hubzilla:
- * - Hubzilla uses the "zid" parameter, while for Friendica it had been replaced with "zrl"
- * - There seem to be some reverse authentication (rmagic) that isn't implemented in Friendica at all
- *
- * It would be favourable to harmonize the two implementations.
- *
- * @return void
- * @throws \Friendica\Network\HTTPException\InternalServerErrorException
- * @throws \ImagickException
- */
- public static function zrlInit()
- {
- $my_url = DI::userSession()->getMyUrl();
- $my_url = Network::isUrlValid($my_url);
-
- if (empty($my_url) || DI::userSession()->getLocalUserId()) {
- return;
- }
-
- $addr = $_GET['addr'] ?? $my_url;
-
- $arr = ['zrl' => $my_url, 'url' => DI::args()->getCommand()];
- Hook::callAll('zrl_init', $arr);
-
- // Try to find the public contact entry of the visitor.
- $contact = Contact::getByURL($my_url, null, ['id', 'url', 'gsid']);
- if (empty($contact)) {
- Logger::info('No contact record found', ['url' => $my_url]);
- return;
- }
-
- if (DI::userSession()->getRemoteUserId() && DI::userSession()->getRemoteUserId() == $contact['id']) {
- Logger::info('The visitor is already authenticated', ['url' => $my_url]);
- return;
- }
-
- $gserver = DBA::selectFirst('gserver', ['url', 'authredirect'], ['id' => $contact['gsid']]);
- if (empty($gserver) || empty($gserver['authredirect'])) {
- Logger::info('No server record found or magic path not defined for server', ['id' => $contact['gsid'], 'gserver' => $gserver]);
- return;
- }
-
- // Avoid endless loops
- $cachekey = 'zrlInit:' . $my_url;
- if (DI::cache()->get($cachekey)) {
- Logger::info('URL ' . $my_url . ' already tried to authenticate.');
- return;
- } else {
- DI::cache()->set($cachekey, true, Duration::MINUTE);
- }
-
- Logger::info('Not authenticated. Invoking reverse magic-auth', ['url' => $my_url]);
-
- // Remove the "addr" parameter from the destination. It is later added as separate parameter again.
- $addr_request = 'addr=' . urlencode($addr);
- $query = rtrim(str_replace($addr_request, '', DI::args()->getQueryString()), '?&');
-
- // The other instance needs to know where to redirect.
- $dest = urlencode(DI::baseUrl() . '/' . $query);
-
- if ($gserver['url'] != DI::baseUrl() && !strstr($dest, '/magic')) {
- $magic_path = $gserver['authredirect'] . '?f=&rev=1&owa=1&dest=' . $dest . '&' . $addr_request;
-
- Logger::info('Doing magic auth for visitor ' . $my_url . ' to ' . $magic_path);
- System::externalRedirect($magic_path);
- }
- }
-
- /**
- * Set the visitor cookies (see remote_user()) for the given handle
- *
- * @param string $handle Visitor handle
- *
- * @return array Visitor contact array
- */
- public static function addVisitorCookieForHandle(string $handle): array
- {
- $a = DI::app();
-
- // Try to find the public contact entry of the visitor.
- $cid = Contact::getIdForURL($handle);
- if (!$cid) {
- Logger::info('Handle not found', ['handle' => $handle]);
- return [];
- }
-
- $visitor = Contact::getById($cid);
-
- // Authenticate the visitor.
- DI::userSession()->setMultiple([
- 'authenticated' => 0,
- 'visitor_id' => $visitor['id'],
- 'visitor_handle' => $visitor['addr'],
- 'visitor_home' => $visitor['url'],
- 'my_url' => $visitor['url'],
- 'remote_comment' => $visitor['subscribe'],
- ]);
-
- DI::userSession()->setVisitorsContacts($visitor['url']);
-
- $a->setContactId($visitor['id']);
-
- Logger::info('Authenticated visitor', ['url' => $visitor['url']]);
-
- return $visitor;
- }
-
- /**
- * Set the visitor cookies (see remote_user()) for signed HTTP requests
- *
- * @param array $server The content of the $_SERVER superglobal
- * @return array Visitor contact array
- * @throws InternalServerErrorException
- */
- public static function addVisitorCookieForHTTPSigner(array $server): array
- {
- $requester = HTTPSignature::getSigner('', $server);
- if (empty($requester)) {
- return [];
- }
- return Profile::addVisitorCookieForHandle($requester);
- }
-
- /**
- * OpenWebAuth authentication.
- *
- * Ported from Hubzilla: https://framagit.org/hubzilla/core/blob/master/include/zid.php
- *
- * @param string $token
- *
- * @return void
- * @throws \Friendica\Network\HTTPException\InternalServerErrorException
- * @throws \ImagickException
- */
- public static function openWebAuthInit(string $token)
- {
- $a = DI::app();
-
- // Clean old OpenWebAuthToken entries.
- OpenWebAuthToken::purge('owt', '3 MINUTE');
-
- // Check if the token we got is the same one
- // we have stored in the database.
- $visitor_handle = OpenWebAuthToken::getMeta('owt', 0, $token);
-
- if ($visitor_handle === false) {
- return;
- }
-
- $visitor = self::addVisitorCookieForHandle($visitor_handle);
- if (empty($visitor)) {
- return;
- }
-
- $arr = [
- 'visitor' => $visitor,
- 'url' => DI::args()->getQueryString()
- ];
- /**
- * @hooks magic_auth_success
- * Called when a magic-auth was successful.
- * * \e array \b visitor
- * * \e string \b url
- */
- Hook::callAll('magic_auth_success', $arr);
-
- $a->setContactId($arr['visitor']['id']);
-
- DI::sysmsg()->addInfo(DI::l10n()->t('OpenWebAuth: %1$s welcomes %2$s', DI::baseUrl()->getHost(), $visitor['name']));
-
- Logger::info('OpenWebAuth: auth success from ' . $visitor['addr']);
- }
-
- /**
- * Returns URL with URL-encoded zrl parameter
- *
- * @param string $url URL to enhance
- * @param bool $force Either to force adding zrl parameter
- *
- * @return string URL with 'zrl' parameter or original URL in case of no Friendica profile URL
- */
- public static function zrl(string $url, bool $force = false): string
- {
- if (!strlen($url)) {
- return $url;
- }
- if (!strpos($url, '/profile/') && !$force) {
- return $url;
- }
- if ($force && substr($url, -1, 1) !== '/') {
- $url = $url . '/';
- }
-
- $achar = strpos($url, '?') ? '&' : '?';
- $mine = DI::userSession()->getMyUrl();
-
- if ($mine && !Strings::compareLink($mine, $url)) {
- return $url . $achar . 'zrl=' . urlencode($mine);
- }
-
- return $url;
- }
-
/**
* Get the user ID of the page owner.
*
use Friendica\Model\Contact;
use Friendica\Model\Item;
use Friendica\Model\Post;
-use Friendica\Model\Profile;
use Friendica\Model\User;
use Friendica\Module\Response;
use Friendica\Navigation\SystemMessages;
use Friendica\Network\HTTPException\ForbiddenException;
use Friendica\Network\Probe;
+use Friendica\Security\OpenWebAuth;
use Friendica\Util\Profiler;
use Friendica\Util\Strings;
use GuzzleHttp\Psr7\Uri;
'$action' => $requestUrl,
'$name' => $contact['name'],
'$url' => $contact['url'],
- '$zrl' => Profile::zrl($contact['url']),
+ '$zrl' => OpenWebAuth::getZrlUrl($contact['url']),
'$myaddr' => $myaddr,
'$keywords' => $contact['keywords'],
use Friendica\Model;
use Friendica\Model\Profile;
use Friendica\Network\HTTPException;
+use Friendica\Security\OpenWebAuth;
/**
* Shows the local directory of this node
$gDirPath = '';
$dirURL = Search::getGlobalDirectory();
if (strlen($dirURL)) {
- $gDirPath = Profile::zrl($dirURL, true);
+ $gDirPath = OpenWebAuth::getZrlUrl($dirURL, true);
}
$pager = new Pager(DI::l10n(), DI::args()->getQueryString(), 60);
namespace Friendica\Module;
-use Friendica\BaseModule;
use Friendica\Contact\Header;
use Friendica\Core\Logger;
use Friendica\Core\Protocol;
use Friendica\Model\Contact;
use Friendica\Model\Photo as MPhoto;
use Friendica\Model\Post;
-use Friendica\Model\Profile;
use Friendica\Core\Storage\Type\ExternalResource;
use Friendica\Core\Storage\Type\SystemResource;
use Friendica\Core\System;
use Friendica\Network\HTTPException;
use Friendica\Network\HTTPException\NotModifiedException;
use Friendica\Object\Image;
+use Friendica\Security\OpenWebAuth;
use Friendica\Util\Images;
-use Friendica\Util\Network;
use Friendica\Util\ParseUrl;
use Friendica\Util\Proxy;
use Friendica\Worker\UpdateContact;
throw new NotModifiedException();
}
- Profile::addVisitorCookieForHTTPSigner($this->server);
+ OpenWebAuth::addVisitorCookieForHTTPSigner($this->server);
$customsize = 0;
$square_resize = true;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\Renderer;
+use Friendica\Core\Session\Capability\IHandleUserSessions;
use Friendica\Core\Worker;
use Friendica\Database\DBA;
use Friendica\DI;
/** @var Tos */
protected $tos;
- public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IManageConfigValues $config, array $server, array $parameters = [])
+ /** @var IHandleUserSessions */
+ private $session;
+
+ public function __construct(IHandleUserSessions $session, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IManageConfigValues $config, array $server, array $parameters = [])
{
parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
$this->tos = new Tos($l10n, $baseUrl, $args, $logger, $profiler, $response, $config, $server, $parameters);
+
+ $this->session = $session;
}
/**
case self::CLOSED:
default:
- if (empty($_SESSION['authenticated']) && empty($_SESSION['administrator'])) {
+ if (!$this->session->isSiteAdmin()) {
DI::sysmsg()->addNotice(DI::l10n()->t('Permission denied.'));
return;
}
use Friendica\Model\User;
use Friendica\Network\HTTPException;
use Friendica\Security\TwoFactor\Repository\TrustedBrowser;
-use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
use LightOpenID;
use Friendica\Core\L10n;
use Friendica\Core\Worker;
use Friendica\Model\Contact;
+use Friendica\Util\Strings;
use Psr\Log\LoggerInterface;
/**
$this->cookie->send();
// Do the authentication if not done by now
- if (!$this->session->get('authenticated')) {
+ if (!$this->session->isAuthenticated()) {
$this->setForUser($a, $user);
if ($this->config->get('system', 'paranoia')) {
}
}
- if ($this->session->get('authenticated')) {
- if ($this->session->get('visitor_id') && !$this->session->get('uid')) {
- $contact = $this->dba->selectFirst('contact', ['id'], ['id' => $this->session->get('visitor_id')]);
- if ($this->dba->isResult($contact)) {
- $a->setContactId($contact['id']);
- }
+ if ($this->session->isVisitor()) {
+ $contact = $this->dba->selectFirst('contact', ['id'], ['id' => $this->session->get('visitor_id')]);
+ if ($this->dba->isResult($contact)) {
+ $a->setContactId($contact['id']);
}
+ }
- if ($this->session->get('uid')) {
- // already logged in user returning
- $check = $this->config->get('system', 'paranoia');
- // extra paranoia - if the IP changed, log them out
- if ($check && ($this->session->get('addr') != $this->remoteAddress)) {
- $this->logger->notice('Session address changed. Paranoid setting in effect, blocking session. ', [
- 'addr' => $this->session->get('addr'),
- 'remote_addr' => $this->remoteAddress
- ]
- );
- $this->session->clear();
- $this->baseUrl->redirect();
- }
-
- $user = $this->dba->selectFirst(
- 'user',
- [],
- [
- 'uid' => $this->session->get('uid'),
- 'blocked' => false,
- 'account_expired' => false,
- 'account_removed' => false,
- 'verified' => true,
- ]
+ if ($this->session->isAuthenticated()) {
+ // already logged in user returning
+ $check = $this->config->get('system', 'paranoia');
+ // extra paranoia - if the IP changed, log them out
+ if ($check && ($this->session->get('addr') != $this->remoteAddress)) {
+ $this->logger->notice('Session address changed. Paranoid setting in effect, blocking session. ', [
+ 'addr' => $this->session->get('addr'),
+ 'remote_addr' => $this->remoteAddress
+ ]
);
- if (!$this->dba->isResult($user)) {
- $this->session->clear();
- $this->baseUrl->redirect();
- }
+ $this->session->clear();
+ $this->baseUrl->redirect();
+ }
- $this->setForUser($a, $user);
+ $user = $this->dba->selectFirst(
+ 'user',
+ [],
+ [
+ 'uid' => $this->session->get('uid'),
+ 'blocked' => false,
+ 'account_expired' => false,
+ 'account_removed' => false,
+ 'verified' => true,
+ ]
+ );
+ if (!$this->dba->isResult($user)) {
+ $this->session->clear();
+ $this->baseUrl->redirect();
}
+
+ $this->setForUser($a, $user);
}
}
$this->baseUrl->redirect('2fa');
}
}
+
+ /**
+ * Set the URL of an unauthenticated visitor
+ *
+ * @param string $url
+ * @return void
+ */
+ public function setUnauthenticatedVisitor(string $url)
+ {
+ if (Strings::compareLink($this->session->get('visitor_home'), $url)) {
+ return;
+ }
+
+ $this->session->set('my_url', $url);
+ $this->session->set('authenticated', 0);
+
+ $remote_contact = Contact::getByURL($url, false, ['subscribe']);
+ if (!empty($remote_contact['subscribe'])) {
+ $this->session->set('remote_comment', $remote_contact['subscribe']);
+ }
+ }
}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2024, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Security;
+
+use Friendica\Core\Cache\Enum\Duration;
+use Friendica\Core\Hook;
+use Friendica\Core\Logger;
+use Friendica\Core\System;
+use Friendica\Database\DBA;
+use Friendica\DI;
+use Friendica\Model\Contact;
+use Friendica\Model\OpenWebAuthToken;
+use Friendica\Util\HTTPSignature;
+use Friendica\Util\Network;
+use Friendica\Util\Strings;
+
+/**
+ * Authentication via OpenWebAuth
+ */
+class OpenWebAuth
+{
+ /**
+ * Process the 'zrl' parameter and initiate the remote authentication.
+ *
+ * This method checks if the visitor has a public contact entry and
+ * redirects the visitor to his/her instance to start the magic auth (Authentication)
+ * process.
+ *
+ * Ported from Hubzilla: https://framagit.org/hubzilla/core/blob/master/include/channel.php
+ *
+ * The implementation for Friendica sadly differs in some points from the one for Hubzilla:
+ * - Hubzilla uses the "zid" parameter, while for Friendica it had been replaced with "zrl"
+ * - There seem to be some reverse authentication (rmagic) that isn't implemented in Friendica at all
+ *
+ * It would be favourable to harmonize the two implementations.
+ *
+ * @return void
+ * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+ * @throws \ImagickException
+ */
+ public static function zrlInit()
+ {
+ $my_url = DI::userSession()->getMyUrl();
+ $my_url = Network::isUrlValid($my_url);
+
+ if (empty($my_url) || DI::userSession()->getLocalUserId()) {
+ return;
+ }
+
+ $addr = $_GET['addr'] ?? $my_url;
+
+ $arr = ['zrl' => $my_url, 'url' => DI::args()->getCommand()];
+ Hook::callAll('zrl_init', $arr);
+
+ // Try to find the public contact entry of the visitor.
+ $contact = Contact::getByURL($my_url, null, ['id', 'url', 'gsid']);
+ if (empty($contact)) {
+ Logger::info('No contact record found', ['url' => $my_url]);
+ return;
+ }
+
+ if (DI::userSession()->getRemoteUserId() && DI::userSession()->getRemoteUserId() == $contact['id']) {
+ Logger::info('The visitor is already authenticated', ['url' => $my_url]);
+ return;
+ }
+
+ $gserver = DBA::selectFirst('gserver', ['url', 'authredirect'], ['id' => $contact['gsid']]);
+ if (empty($gserver) || empty($gserver['authredirect'])) {
+ Logger::info('No server record found or magic path not defined for server', ['id' => $contact['gsid'], 'gserver' => $gserver]);
+ return;
+ }
+
+ // Avoid endless loops
+ $cachekey = 'zrlInit:' . $my_url;
+ if (DI::cache()->get($cachekey)) {
+ Logger::info('URL ' . $my_url . ' already tried to authenticate.');
+ return;
+ } else {
+ DI::cache()->set($cachekey, true, Duration::MINUTE);
+ }
+
+ Logger::info('Not authenticated. Invoking reverse magic-auth', ['url' => $my_url]);
+
+ // Remove the "addr" parameter from the destination. It is later added as separate parameter again.
+ $addr_request = 'addr=' . urlencode($addr);
+ $query = rtrim(str_replace($addr_request, '', DI::args()->getQueryString()), '?&');
+
+ // The other instance needs to know where to redirect.
+ $dest = urlencode(DI::baseUrl() . '/' . $query);
+
+ if ($gserver['url'] != DI::baseUrl() && !strstr($dest, '/magic')) {
+ $magic_path = $gserver['authredirect'] . '?f=&rev=1&owa=1&dest=' . $dest . '&' . $addr_request;
+
+ Logger::info('Doing magic auth for visitor ' . $my_url . ' to ' . $magic_path);
+ System::externalRedirect($magic_path);
+ }
+ }
+
+ /**
+ * OpenWebAuth authentication.
+ *
+ * Ported from Hubzilla: https://framagit.org/hubzilla/core/blob/master/include/zid.php
+ *
+ * @param string $token
+ *
+ * @return void
+ * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+ * @throws \ImagickException
+ */
+ public static function init(string $token)
+ {
+ $a = DI::app();
+
+ // Clean old OpenWebAuthToken entries.
+ OpenWebAuthToken::purge('owt', '3 MINUTE');
+
+ // Check if the token we got is the same one
+ // we have stored in the database.
+ $visitor_handle = OpenWebAuthToken::getMeta('owt', 0, $token);
+
+ if ($visitor_handle === false) {
+ return;
+ }
+
+ $visitor = self::addVisitorCookieForHandle($visitor_handle);
+ if (empty($visitor)) {
+ return;
+ }
+
+ $arr = [
+ 'visitor' => $visitor,
+ 'url' => DI::args()->getQueryString()
+ ];
+ /**
+ * @hooks magic_auth_success
+ * Called when a magic-auth was successful.
+ * * \e array \b visitor
+ * * \e string \b url
+ */
+ Hook::callAll('magic_auth_success', $arr);
+
+ $a->setContactId($arr['visitor']['id']);
+
+ DI::sysmsg()->addInfo(DI::l10n()->t('OpenWebAuth: %1$s welcomes %2$s', DI::baseUrl()->getHost(), $visitor['name']));
+
+ Logger::info('OpenWebAuth: auth success from ' . $visitor['addr']);
+ }
+
+ /**
+ * Set the visitor cookies (see remote_user()) for the given handle
+ *
+ * @param string $handle Visitor handle
+ *
+ * @return array Visitor contact array
+ */
+ public static function addVisitorCookieForHandle(string $handle): array
+ {
+ $a = DI::app();
+
+ // Try to find the public contact entry of the visitor.
+ $cid = Contact::getIdForURL($handle);
+ if (!$cid) {
+ Logger::info('Handle not found', ['handle' => $handle]);
+ return [];
+ }
+
+ $visitor = Contact::getById($cid);
+
+ // Authenticate the visitor.
+ DI::userSession()->setMultiple([
+ 'authenticated' => 1,
+ 'visitor_id' => $visitor['id'],
+ 'visitor_handle' => $visitor['addr'],
+ 'visitor_home' => $visitor['url'],
+ 'my_url' => $visitor['url'],
+ 'remote_comment' => $visitor['subscribe'],
+ ]);
+
+ DI::userSession()->setVisitorsContacts($visitor['url']);
+
+ $a->setContactId($visitor['id']);
+
+ Logger::info('Authenticated visitor', ['url' => $visitor['url']]);
+
+ return $visitor;
+ }
+
+ /**
+ * Set the visitor cookies (see remote_user()) for signed HTTP requests
+ *
+ * @param array $server The content of the $_SERVER superglobal
+ * @return array Visitor contact array
+ * @throws InternalServerErrorException
+ */
+ public static function addVisitorCookieForHTTPSigner(array $server): array
+ {
+ $requester = HTTPSignature::getSigner('', $server);
+ if (empty($requester)) {
+ return [];
+ }
+ return self::addVisitorCookieForHandle($requester);
+ }
+
+ /**
+ * Returns URL with URL-encoded zrl parameter
+ *
+ * @param string $url URL to enhance
+ * @param bool $force Either to force adding zrl parameter
+ *
+ * @return string URL with 'zrl' parameter or original URL in case of no Friendica profile URL
+ */
+ public static function getZrlUrl(string $url, bool $force = false): string
+ {
+ if (!strlen($url)) {
+ return $url;
+ }
+ if (!strpos($url, '/profile/') && !$force) {
+ return $url;
+ }
+ if ($force && substr($url, -1, 1) !== '/') {
+ $url = $url . '/';
+ }
+
+ $achar = strpos($url, '?') ? '&' : '?';
+ $mine = DI::userSession()->getMyUrl();
+
+ if ($mine && !Strings::compareLink($mine, $url)) {
+ return $url . $achar . 'zrl=' . urlencode($mine);
+ }
+
+ return $url;
+ }
+}
'authenticated' => [
'data' => [
'authenticated' => true,
+ 'uid' => 21,
],
'expected' => true,
],
],
'expected' => false,
],
+ 'remote_visitor' => [
+ 'data' => [
+ 'authenticated' => true,
+ 'visitor_id' => 21,
+ ],
+ 'expected' => false,
+ ],
'missing' => [
'data' => [
],
$userSession = new UserSession(new ArraySession($data));
$this->assertEquals($expected, $userSession->isAuthenticated());
}
+
+ public function dataIsVisitor()
+ {
+ return [
+ 'local_user' => [
+ 'data' => [
+ 'authenticated' => true,
+ 'uid' => 21,
+ ],
+ 'expected' => false,
+ ],
+ 'not_authenticated' => [
+ 'data' => [
+ 'authenticated' => false,
+ ],
+ 'expected' => false,
+ ],
+ 'remote_visitor' => [
+ 'data' => [
+ 'authenticated' => true,
+ 'visitor_id' => 21,
+ ],
+ 'expected' => true,
+ ],
+ 'remote_unauthenticated_visitor' => [
+ 'data' => [
+ 'authenticated' => false,
+ 'visitor_id' => 21,
+ ],
+ 'expected' => false,
+ ],
+ 'missing' => [
+ 'data' => [
+ ],
+ 'expected' => false,
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataIsVisitor
+ */
+ public function testIsVisitor(array $data, $expected)
+ {
+ $userSession = new UserSession(new ArraySession($data));
+ $this->assertEquals($expected, $userSession->isVisitor());
+ }
+
+ public function dataIsUnauthenticated()
+ {
+ return [
+ 'local_user' => [
+ 'data' => [
+ 'authenticated' => true,
+ 'uid' => 21,
+ ],
+ 'expected' => false,
+ ],
+ 'not_authenticated' => [
+ 'data' => [
+ 'authenticated' => false,
+ ],
+ 'expected' => true,
+ ],
+ 'authenticated' => [
+ 'data' => [
+ 'authenticated' => true,
+ ],
+ 'expected' => false,
+ ],
+ 'remote_visitor' => [
+ 'data' => [
+ 'authenticated' => true,
+ 'visitor_id' => 21,
+ ],
+ 'expected' => false,
+ ],
+ 'remote_unauthenticated_visitor' => [
+ 'data' => [
+ 'authenticated' => false,
+ 'visitor_id' => 21,
+ ],
+ 'expected' => true,
+ ],
+ 'missing' => [
+ 'data' => [
+ ],
+ 'expected' => true,
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataIsUnauthenticated
+ */
+ public function testIsUnauthenticated(array $data, $expected)
+ {
+ $userSession = new UserSession(new ArraySession($data));
+ $this->assertEquals($expected, $userSession->isUnauthenticated());
+ }
}
msgstr ""
"Project-Id-Version: 2024.06-dev\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-05-26 15:56+0000\n"
+"POT-Creation-Date: 2024-05-27 04:49+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
#: src/Module/Post/Edit.php:76 src/Module/Profile/Common.php:75
#: src/Module/Profile/Contacts.php:78 src/Module/Profile/Photos.php:92
#: src/Module/Profile/Schedule.php:39 src/Module/Profile/Schedule.php:56
-#: src/Module/Register.php:78 src/Module/Register.php:91
-#: src/Module/Register.php:207 src/Module/Register.php:246
+#: src/Module/Register.php:84 src/Module/Register.php:97
+#: src/Module/Register.php:213 src/Module/Register.php:252
#: src/Module/Search/Directory.php:37 src/Module/Settings/Account.php:50
#: src/Module/Settings/Account.php:386 src/Module/Settings/Channels.php:66
#: src/Module/Settings/Channels.php:141 src/Module/Settings/Delegation.php:90
msgstr ""
#: mod/photos.php:66 mod/photos.php:129 mod/photos.php:573
-#: src/Model/Event.php:512 src/Model/Profile.php:234
+#: src/Model/Event.php:512 src/Model/Profile.php:227
#: src/Module/Calendar/Export.php:74 src/Module/Calendar/Show.php:74
#: src/Module/DFRN/Poll.php:43 src/Module/Feed.php:64 src/Module/HCard.php:51
#: src/Module/Profile/Common.php:62 src/Module/Profile/Common.php:71
#: src/Module/Profile/Contacts.php:64 src/Module/Profile/Contacts.php:72
#: src/Module/Profile/Conversations.php:91 src/Module/Profile/Media.php:56
#: src/Module/Profile/Photos.php:83 src/Module/Profile/RemoteFollow.php:71
-#: src/Module/Register.php:268
+#: src/Module/Register.php:274
msgid "User not found."
msgstr ""
msgstr ""
#: mod/photos.php:577 src/Module/Conversation/Community.php:160
-#: src/Module/Directory.php:48 src/Module/Profile/Photos.php:293
+#: src/Module/Directory.php:49 src/Module/Profile/Photos.php:293
#: src/Module/Search/Index.php:65
msgid "Public access denied."
msgstr ""
msgid "Map"
msgstr ""
-#: src/App.php:438
+#: src/App.php:441
msgid "No system theme config value set."
msgstr ""
-#: src/App.php:546
+#: src/App.php:549
msgid "Apologies but the website is unavailable at the moment."
msgstr ""
msgstr ""
#: src/Content/Conversation.php:424 src/Content/Widget/VCard.php:131
-#: src/Model/Profile.php:483 src/Module/Admin/Logs/View.php:94
+#: src/Model/Profile.php:476 src/Module/Admin/Logs/View.php:94
#: src/Module/Post/Edit.php:181
msgid "Message"
msgstr ""
#: src/Content/Item.php:430 src/Content/Item.php:453 src/Model/Contact.php:1168
#: src/Model/Contact.php:1224 src/Model/Contact.php:1234
-#: src/Module/Directory.php:157 src/Module/Settings/Profile/Index.php:259
+#: src/Module/Directory.php:158 src/Module/Settings/Profile/Index.php:259
msgid "View Profile"
msgstr ""
msgstr ""
#: src/Content/Item.php:432 src/Model/Contact.php:1202
-#: src/Model/Profile.php:468
+#: src/Model/Profile.php:461
msgid "Network Posts"
msgstr ""
msgid "Home Page"
msgstr ""
-#: src/Content/Nav.php:255 src/Module/Register.php:169
+#: src/Content/Nav.php:255 src/Module/Register.php:175
#: src/Module/Security/Login.php:124
msgid "Register"
msgstr ""
msgstr ""
#: src/Content/Nav.php:301 src/Module/Admin/Tos.php:78
-#: src/Module/BaseAdmin.php:95 src/Module/Register.php:177
+#: src/Module/BaseAdmin.php:95 src/Module/Register.php:183
#: src/Module/Tos.php:101
msgid "Terms of Service"
msgstr ""
msgstr ""
#: src/Content/Text/HTML.php:861 src/Content/Widget/VCard.php:127
-#: src/Model/Profile.php:477 src/Module/Contact/Profile.php:478
+#: src/Model/Profile.php:470 src/Module/Contact/Profile.php:478
msgid "Follow"
msgstr ""
msgstr ""
#: src/Content/Widget.php:82 src/Module/Contact.php:460
-#: src/Module/Directory.php:96 view/theme/vier/theme.php:197
+#: src/Module/Directory.php:97 view/theme/vier/theme.php:197
msgid "Find"
msgstr ""
msgid "Invite Friends"
msgstr ""
-#: src/Content/Widget.php:87 src/Module/Directory.php:88
+#: src/Content/Widget.php:87 src/Module/Directory.php:89
#: view/theme/vier/theme.php:202
msgid "Global Directory"
msgstr ""
msgstr ""
#: src/Content/Widget/VCard.php:105 src/Model/Contact.php:1196
-#: src/Model/Profile.php:462
+#: src/Model/Profile.php:455
msgid "Post to group"
msgstr ""
#: src/Content/Widget/VCard.php:110 src/Model/Contact.php:1200
-#: src/Model/Profile.php:466 src/Module/Moderation/Item/Source.php:85
+#: src/Model/Profile.php:459 src/Module/Moderation/Item/Source.php:85
msgid "Mention"
msgstr ""
-#: src/Content/Widget/VCard.php:120 src/Model/Profile.php:381
+#: src/Content/Widget/VCard.php:120 src/Model/Profile.php:374
#: src/Module/Contact/Profile.php:414 src/Module/Profile/Profile.php:199
msgid "XMPP:"
msgstr ""
-#: src/Content/Widget/VCard.php:121 src/Model/Profile.php:382
+#: src/Content/Widget/VCard.php:121 src/Model/Profile.php:375
#: src/Module/Contact/Profile.php:416 src/Module/Profile/Profile.php:203
msgid "Matrix:"
msgstr ""
#: src/Content/Widget/VCard.php:122 src/Model/Event.php:82
#: src/Model/Event.php:109 src/Model/Event.php:471 src/Model/Event.php:960
-#: src/Model/Profile.php:376 src/Module/Contact/Profile.php:412
-#: src/Module/Directory.php:147 src/Module/Notifications/Introductions.php:187
+#: src/Model/Profile.php:369 src/Module/Contact/Profile.php:412
+#: src/Module/Directory.php:148 src/Module/Notifications/Introductions.php:187
#: src/Module/Profile/Profile.php:221
msgid "Location:"
msgstr ""
-#: src/Content/Widget/VCard.php:125 src/Model/Profile.php:490
+#: src/Content/Widget/VCard.php:125 src/Model/Profile.php:483
#: src/Module/Notifications/Introductions.php:201
msgid "Network:"
msgstr ""
#: src/Content/Widget/VCard.php:129 src/Model/Contact.php:1228
-#: src/Model/Contact.php:1240 src/Model/Profile.php:479
+#: src/Model/Contact.php:1240 src/Model/Profile.php:472
#: src/Module/Contact/Profile.php:470
msgid "Unfollow"
msgstr ""
#: src/Content/Widget/VCard.php:135 src/Model/Contact.php:1198
-#: src/Model/Profile.php:464
+#: src/Model/Profile.php:457
msgid "View group"
msgstr ""
msgid "Wall Photos"
msgstr ""
-#: src/Model/Profile.php:364 src/Module/Profile/Profile.php:283
+#: src/Model/Profile.php:357 src/Module/Profile/Profile.php:283
#: src/Module/Profile/Profile.php:285
msgid "Edit profile"
msgstr ""
-#: src/Model/Profile.php:366
+#: src/Model/Profile.php:359
msgid "Change profile photo"
msgstr ""
-#: src/Model/Profile.php:379 src/Module/Directory.php:152
+#: src/Model/Profile.php:372 src/Module/Directory.php:153
#: src/Module/Profile/Profile.php:209
msgid "Homepage:"
msgstr ""
-#: src/Model/Profile.php:380 src/Module/Contact/Profile.php:418
+#: src/Model/Profile.php:373 src/Module/Contact/Profile.php:418
#: src/Module/Notifications/Introductions.php:189
msgid "About:"
msgstr ""
-#: src/Model/Profile.php:481
+#: src/Model/Profile.php:474
msgid "Atom feed"
msgstr ""
-#: src/Model/Profile.php:488
+#: src/Model/Profile.php:481
msgid "This website has been verified to belong to the same person."
msgstr ""
-#: src/Model/Profile.php:539
+#: src/Model/Profile.php:532
msgid "F d"
msgstr ""
-#: src/Model/Profile.php:603 src/Model/Profile.php:680
+#: src/Model/Profile.php:596 src/Model/Profile.php:673
msgid "[today]"
msgstr ""
-#: src/Model/Profile.php:612
+#: src/Model/Profile.php:605
msgid "Birthday Reminders"
msgstr ""
-#: src/Model/Profile.php:613
+#: src/Model/Profile.php:606
msgid "Birthdays this week:"
msgstr ""
-#: src/Model/Profile.php:629
+#: src/Model/Profile.php:622
msgid "g A l F d"
msgstr ""
-#: src/Model/Profile.php:667
+#: src/Model/Profile.php:660
msgid "[No description]"
msgstr ""
-#: src/Model/Profile.php:693
+#: src/Model/Profile.php:686
msgid "Event Reminders"
msgstr ""
-#: src/Model/Profile.php:694
+#: src/Model/Profile.php:687
msgid "Upcoming events the next 7 days:"
msgstr ""
-#: src/Model/Profile.php:876
-#, php-format
-msgid "OpenWebAuth: %1$s welcomes %2$s"
-msgstr ""
-
-#: src/Model/Profile.php:1016
+#: src/Model/Profile.php:797
msgid "Hometown:"
msgstr ""
-#: src/Model/Profile.php:1017
+#: src/Model/Profile.php:798
msgid "Marital Status:"
msgstr ""
-#: src/Model/Profile.php:1018
+#: src/Model/Profile.php:799
msgid "With:"
msgstr ""
-#: src/Model/Profile.php:1019
+#: src/Model/Profile.php:800
msgid "Since:"
msgstr ""
-#: src/Model/Profile.php:1020
+#: src/Model/Profile.php:801
msgid "Sexual Preference:"
msgstr ""
-#: src/Model/Profile.php:1021
+#: src/Model/Profile.php:802
msgid "Political Views:"
msgstr ""
-#: src/Model/Profile.php:1022
+#: src/Model/Profile.php:803
msgid "Religious Views:"
msgstr ""
-#: src/Model/Profile.php:1023
+#: src/Model/Profile.php:804
msgid "Likes:"
msgstr ""
-#: src/Model/Profile.php:1024
+#: src/Model/Profile.php:805
msgid "Dislikes:"
msgstr ""
-#: src/Model/Profile.php:1025
+#: src/Model/Profile.php:806
msgid "Title/Description:"
msgstr ""
-#: src/Model/Profile.php:1026 src/Module/Admin/Summary.php:197
+#: src/Model/Profile.php:807 src/Module/Admin/Summary.php:197
#: src/Module/Moderation/Report/Create.php:280
#: src/Module/Moderation/Summary.php:76
msgid "Summary"
msgstr ""
-#: src/Model/Profile.php:1027
+#: src/Model/Profile.php:808
msgid "Musical interests"
msgstr ""
-#: src/Model/Profile.php:1028
+#: src/Model/Profile.php:809
msgid "Books, literature"
msgstr ""
-#: src/Model/Profile.php:1029
+#: src/Model/Profile.php:810
msgid "Television"
msgstr ""
-#: src/Model/Profile.php:1030
+#: src/Model/Profile.php:811
msgid "Film/dance/culture/entertainment"
msgstr ""
-#: src/Model/Profile.php:1031
+#: src/Model/Profile.php:812
msgid "Hobbies/Interests"
msgstr ""
-#: src/Model/Profile.php:1032
+#: src/Model/Profile.php:813
msgid "Love/romance"
msgstr ""
-#: src/Model/Profile.php:1033
+#: src/Model/Profile.php:814
msgid "Work/employment"
msgstr ""
-#: src/Model/Profile.php:1034
+#: src/Model/Profile.php:815
msgid "School/education"
msgstr ""
-#: src/Model/Profile.php:1035
+#: src/Model/Profile.php:816
msgid "Contact information and Social Networks"
msgstr ""
msgid "Invalid OpenID url"
msgstr ""
-#: src/Model/User.php:1218 src/Security/Authentication.php:230
+#: src/Model/User.php:1218 src/Security/Authentication.php:228
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:1218 src/Security/Authentication.php:230
+#: src/Model/User.php:1218 src/Security/Authentication.php:228
msgid "The error message was:"
msgstr ""
#: src/Module/Admin/Features.php:67
#: src/Module/Notifications/Introductions.php:144
-#: src/Module/OAuth/Acknowledge.php:55 src/Module/Register.php:132
+#: src/Module/OAuth/Acknowledge.php:55 src/Module/Register.php:138
#: src/Module/Settings/TwoFactor/Trusted.php:129
msgid "No"
msgstr ""
#: src/Module/Admin/Features.php:67 src/Module/Contact/Revoke.php:108
#: src/Module/Notifications/Introductions.php:144
-#: src/Module/OAuth/Acknowledge.php:54 src/Module/Register.php:131
+#: src/Module/OAuth/Acknowledge.php:54 src/Module/Register.php:137
#: src/Module/Settings/TwoFactor/Trusted.php:129
msgid "Yes"
msgstr ""
msgid "Republish users to directory"
msgstr ""
-#: src/Module/Admin/Site.php:460 src/Module/Register.php:153
+#: src/Module/Admin/Site.php:460 src/Module/Register.php:159
msgid "Registration"
msgstr ""
#: src/Module/Moderation/Blocklist/Server/Index.php:87
#: src/Module/Moderation/Blocklist/Server/Index.php:115
#: src/Module/Moderation/Blocklist/Server/Index.php:116
-#: src/Module/Moderation/Item/Delete.php:67 src/Module/Register.php:149
+#: src/Module/Moderation/Item/Delete.php:67 src/Module/Register.php:155
#: src/Module/Security/TwoFactor/Verify.php:101
#: src/Module/Settings/Channels.php:190 src/Module/Settings/Channels.php:211
#: src/Module/Settings/TwoFactor/Index.php:161
msgid "Lookup address:"
msgstr ""
-#: src/Module/Directory.php:74
+#: src/Module/Directory.php:75
msgid "No entries (some entries may be hidden)."
msgstr ""
-#: src/Module/Directory.php:90
+#: src/Module/Directory.php:91
msgid "Find on this site"
msgstr ""
-#: src/Module/Directory.php:92
+#: src/Module/Directory.php:93
msgid "Results for:"
msgstr ""
-#: src/Module/Directory.php:94
+#: src/Module/Directory.php:95
msgid "Site Directory"
msgstr ""
msgid "ignored"
msgstr ""
-#: src/Module/Photo.php:124
+#: src/Module/Photo.php:122
msgid "The Photo is not available."
msgstr ""
-#: src/Module/Photo.php:149
+#: src/Module/Photo.php:147
#, php-format
msgid "The Photo with id %s is not available."
msgstr ""
-#: src/Module/Photo.php:190
+#: src/Module/Photo.php:188
#, php-format
msgid "Invalid external resource with url %s."
msgstr ""
-#: src/Module/Photo.php:192
+#: src/Module/Photo.php:190
#, php-format
msgid "Invalid photo with id %s."
msgstr ""
msgid "Remove post"
msgstr ""
-#: src/Module/Register.php:85
+#: src/Module/Register.php:91
msgid "Only parent users can create additional accounts."
msgstr ""
-#: src/Module/Register.php:100 src/Module/User/Import.php:112
+#: src/Module/Register.php:106 src/Module/User/Import.php:112
msgid ""
"This site has exceeded the number of allowed daily account registrations. "
"Please try again tomorrow."
msgstr ""
-#: src/Module/Register.php:117
+#: src/Module/Register.php:123
msgid ""
"You may (optionally) fill in this form via OpenID by supplying your OpenID "
"and clicking \"Register\"."
msgstr ""
-#: src/Module/Register.php:118
+#: src/Module/Register.php:124
msgid ""
"If you are not familiar with OpenID, please leave that field blank and fill "
"in the rest of the items."
msgstr ""
-#: src/Module/Register.php:119
+#: src/Module/Register.php:125
msgid "Your OpenID (optional): "
msgstr ""
-#: src/Module/Register.php:128
+#: src/Module/Register.php:134
msgid "Include your profile in member directory?"
msgstr ""
-#: src/Module/Register.php:149
+#: src/Module/Register.php:155
msgid "Note for the admin"
msgstr ""
-#: src/Module/Register.php:149
+#: src/Module/Register.php:155
msgid "Leave a message for the admin, why you want to join this node"
msgstr ""
-#: src/Module/Register.php:150
+#: src/Module/Register.php:156
msgid "Membership on this site is by invitation only."
msgstr ""
-#: src/Module/Register.php:151
+#: src/Module/Register.php:157
msgid "Your invitation code: "
msgstr ""
-#: src/Module/Register.php:159
+#: src/Module/Register.php:165
msgid "Your Display Name (as you would like it to be displayed on this system"
msgstr ""
-#: src/Module/Register.php:160
+#: src/Module/Register.php:166
msgid ""
"Your Email Address: (Initial information will be send there, so this has to "
"be an existing address.)"
msgstr ""
-#: src/Module/Register.php:161
+#: src/Module/Register.php:167
msgid "Please repeat your e-mail address:"
msgstr ""
-#: src/Module/Register.php:163 src/Module/Security/PasswordTooLong.php:100
+#: src/Module/Register.php:169 src/Module/Security/PasswordTooLong.php:100
#: src/Module/Settings/Account.php:564
msgid "New Password:"
msgstr ""
-#: src/Module/Register.php:163
+#: src/Module/Register.php:169
msgid "Leave empty for an auto generated password."
msgstr ""
-#: src/Module/Register.php:164 src/Module/Security/PasswordTooLong.php:101
+#: src/Module/Register.php:170 src/Module/Security/PasswordTooLong.php:101
#: src/Module/Settings/Account.php:565
msgid "Confirm:"
msgstr ""
-#: src/Module/Register.php:165
+#: src/Module/Register.php:171
#, php-format
msgid ""
"Choose a profile nickname. This must begin with a text character. Your "
"profile address on this site will then be \"<strong>nickname@%s</strong>\"."
msgstr ""
-#: src/Module/Register.php:166
+#: src/Module/Register.php:172
msgid "Choose a nickname: "
msgstr ""
-#: src/Module/Register.php:174 src/Module/User/Import.php:118
+#: src/Module/Register.php:180 src/Module/User/Import.php:118
msgid "Import"
msgstr ""
-#: src/Module/Register.php:175
+#: src/Module/Register.php:181
msgid "Import your profile to this friendica instance"
msgstr ""
-#: src/Module/Register.php:182
+#: src/Module/Register.php:188
msgid "Note: This node explicitly contains adult content"
msgstr ""
-#: src/Module/Register.php:184 src/Module/Settings/Delegation.php:181
+#: src/Module/Register.php:190 src/Module/Settings/Delegation.php:181
msgid "Parent Password:"
msgstr ""
-#: src/Module/Register.php:184 src/Module/Settings/Delegation.php:181
+#: src/Module/Register.php:190 src/Module/Settings/Delegation.php:181
msgid ""
"Please enter the password of the parent account to legitimize your request."
msgstr ""
-#: src/Module/Register.php:213
+#: src/Module/Register.php:219
msgid "Password doesn't match."
msgstr ""
-#: src/Module/Register.php:219
+#: src/Module/Register.php:225
msgid "Please enter your password."
msgstr ""
-#: src/Module/Register.php:261
+#: src/Module/Register.php:267
msgid "You have entered too much information."
msgstr ""
-#: src/Module/Register.php:284
+#: src/Module/Register.php:290
msgid "Please enter the identical mail address in the second field."
msgstr ""
-#: src/Module/Register.php:292
+#: src/Module/Register.php:298
msgid "Nickname cannot start with a digit."
msgstr ""
-#: src/Module/Register.php:294
+#: src/Module/Register.php:300
msgid "Nickname can only contain US-ASCII characters."
msgstr ""
-#: src/Module/Register.php:323
+#: src/Module/Register.php:329
msgid "The additional account was created."
msgstr ""
-#: src/Module/Register.php:348
+#: src/Module/Register.php:354
msgid ""
"Registration successful. Please check your email for further instructions."
msgstr ""
-#: src/Module/Register.php:355
+#: src/Module/Register.php:361
#, php-format
msgid ""
"Failed to send email message. Here your accout details:<br> login: %s<br> "
"password: %s<br><br>You can change your password after login."
msgstr ""
-#: src/Module/Register.php:361
+#: src/Module/Register.php:367
msgid "Registration successful."
msgstr ""
-#: src/Module/Register.php:370 src/Module/Register.php:377
-#: src/Module/Register.php:387
+#: src/Module/Register.php:376 src/Module/Register.php:383
+#: src/Module/Register.php:393
msgid "Your registration can not be processed."
msgstr ""
-#: src/Module/Register.php:376
+#: src/Module/Register.php:382
msgid "You have to leave a request note for the admin."
msgstr ""
-#: src/Module/Register.php:386
+#: src/Module/Register.php:392
msgid "An internal error occured."
msgstr ""
-#: src/Module/Register.php:408
+#: src/Module/Register.php:414
msgid "Your registration is pending approval by the site owner."
msgstr ""
msgid "The folder %s must be writable by webserver."
msgstr ""
-#: src/Security/Authentication.php:216
+#: src/Security/Authentication.php:214
msgid "Login failed."
msgstr ""
-#: src/Security/Authentication.php:261
+#: src/Security/Authentication.php:259
msgid "Login failed. Please check your credentials."
msgstr ""
-#: src/Security/Authentication.php:375
+#: src/Security/Authentication.php:373
#, php-format
msgid "Welcome %s"
msgstr ""
-#: src/Security/Authentication.php:376
+#: src/Security/Authentication.php:374
msgid "Please upload a profile photo."
msgstr ""
+#: src/Security/OpenWebAuth.php:163
+#, php-format
+msgid "OpenWebAuth: %1$s welcomes %2$s"
+msgstr ""
+
#: src/Util/EMailer/MailBuilder.php:260
msgid "Friendica Notification"
msgstr ""