OpenWebAuth path is now fetched during probing

This commit is contained in:
Michael 2024-05-20 19:36:40 +00:00
parent ea5e1f1edc
commit da37516abf
13 changed files with 143 additions and 52 deletions

View file

@ -1,6 +1,6 @@
-- ------------------------------------------ -- ------------------------------------------
-- Friendica 2024.06-dev (Yellow Archangel) -- Friendica 2024.06-dev (Yellow Archangel)
-- DB_UPDATE_VERSION 1560 -- DB_UPDATE_VERSION 1561
-- ------------------------------------------ -- ------------------------------------------
@ -23,6 +23,7 @@ CREATE TABLE IF NOT EXISTS `gserver` (
`local-comments` int unsigned COMMENT 'Number of local comments', `local-comments` int unsigned COMMENT 'Number of local comments',
`directory-type` tinyint DEFAULT 0 COMMENT 'Type of directory service (Poco, Mastodon)', `directory-type` tinyint DEFAULT 0 COMMENT 'Type of directory service (Poco, Mastodon)',
`poco` varbinary(383) NOT NULL DEFAULT '' COMMENT '', `poco` varbinary(383) NOT NULL DEFAULT '' COMMENT '',
`openwebauth` varbinary(383) COMMENT 'Path to the OpenWebAuth endpoint',
`noscrape` varbinary(383) NOT NULL DEFAULT '' COMMENT '', `noscrape` varbinary(383) NOT NULL DEFAULT '' COMMENT '',
`network` char(4) NOT NULL DEFAULT '' COMMENT '', `network` char(4) NOT NULL DEFAULT '' COMMENT '',
`protocol` tinyint unsigned COMMENT 'The protocol of the server', `protocol` tinyint unsigned COMMENT 'The protocol of the server',

View file

@ -23,6 +23,7 @@ Fields
| local-comments | Number of local comments | int unsigned | YES | | NULL | | | local-comments | Number of local comments | int unsigned | YES | | NULL | |
| directory-type | Type of directory service (Poco, Mastodon) | tinyint | YES | | 0 | | | directory-type | Type of directory service (Poco, Mastodon) | tinyint | YES | | 0 | |
| poco | | varbinary(383) | NO | | | | | poco | | varbinary(383) | NO | | | |
| openwebauth | Path to the OpenWebAuth endpoint | varbinary(383) | YES | | NULL | |
| noscrape | | varbinary(383) | NO | | | | | noscrape | | varbinary(383) | NO | | | |
| network | | char(4) | NO | | | | | network | | char(4) | NO | | | |
| protocol | The protocol of the server | tinyint unsigned | YES | | NULL | | | protocol | The protocol of the server | tinyint unsigned | YES | | NULL | |

View file

@ -42,6 +42,7 @@ use Friendica\Module\BaseProfile;
use Friendica\Network\HTTPException; use Friendica\Network\HTTPException;
use Friendica\Network\Probe; use Friendica\Network\Probe;
use Friendica\Protocol\Activity; use Friendica\Protocol\Activity;
use Friendica\Protocol\ActivityNamespace;
use Friendica\Security\Security; use Friendica\Security\Security;
use Friendica\Util\Crypto; use Friendica\Util\Crypto;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
@ -408,7 +409,7 @@ function photos_post()
if (count($links)) { if (count($links)) {
foreach ($links as $link) { foreach ($links as $link) {
if ($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page') { if ($link['@attributes']['rel'] === ActivityNamespace::WEBFINGERPROFILE) {
$profile = $link['@attributes']['href']; $profile = $link['@attributes']['href'];
} }

View file

@ -583,7 +583,7 @@ class App
} }
} }
Model\Profile::zrlInit($this); Model\Profile::zrlInit();
} else { } else {
// Someone came with an invalid parameter, maybe as a DDoS attempt // Someone came with an invalid parameter, maybe as a DDoS attempt
// We simply stop processing here // We simply stop processing here

View file

@ -90,7 +90,7 @@ class APContact
$data['url'] = $link['href']; $data['url'] = $link['href'];
} }
if (!empty($link['href']) && !empty($link['type']) && ($link['rel'] == 'http://webfinger.net/rel/profile-page') && ($link['type'] == 'text/html')) { if (!empty($link['href']) && !empty($link['type']) && ($link['rel'] == ActivityNamespace::WEBFINGERPROFILE) && ($link['type'] == 'text/html')) {
$data['alias'] = $link['href']; $data['alias'] = $link['href'];
} }
} }

View file

@ -1446,6 +1446,7 @@ class Contact
} }
} }
GServer::updateFromProbeArray($data);
self::updateFromProbeArray($contact_id, $data); self::updateFromProbeArray($contact_id, $data);
// Don't return a number for a deleted account // Don't return a number for a deleted account
@ -2673,6 +2674,7 @@ class Contact
} }
} }
GServer::updateFromProbeArray($data);
return self::updateFromProbeArray($id, $data); return self::updateFromProbeArray($id, $data);
} }
@ -3215,6 +3217,7 @@ class Contact
} }
if ($probed) { if ($probed) {
GServer::updateFromProbeArray($ret);
self::updateFromProbeArray($contact_id, $ret); self::updateFromProbeArray($contact_id, $ret);
} else { } else {
try { try {

View file

@ -2484,6 +2484,25 @@ class GServer
DI::keyValue()->set('poco_last_federation_discovery', time()); DI::keyValue()->set('poco_last_federation_discovery', time());
} }
public static function updateFromProbeArray(array $data)
{
if (empty($data['gsid']) || empty($data['openwebauth'])) {
return;
}
$gserver = DBA::selectFirst('gserver', ['openwebauth'], ['id' => $data['gsid']]);
if (!DBA::isResult($gserver)) {
return;
}
if ($data['openwebauth'] == $gserver['openwebauth']) {
return;
}
Logger::debug('Set Open Web Auth path', ['baseurl' => $data['baseurl'], 'openwebauth' => $data['openwebauth']]);
self::update(['openwebauth' => $data['openwebauth']], ['id' => $data['gsid']]);
}
/** /**
* Set the protocol for the given server * Set the protocol for the given server
* *

View file

@ -711,13 +711,11 @@ class Profile
* *
* It would be favourable to harmonize the two implementations. * It would be favourable to harmonize the two implementations.
* *
* @param App $a Application instance.
*
* @return void * @return void
* @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException * @throws \ImagickException
*/ */
public static function zrlInit(App $a) public static function zrlInit()
{ {
$my_url = DI::userSession()->getMyUrl(); $my_url = DI::userSession()->getMyUrl();
$my_url = Network::isUrlValid($my_url); $my_url = Network::isUrlValid($my_url);

View file

@ -25,8 +25,10 @@ use Exception;
use Friendica\App; use Friendica\App;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Core\L10n; use Friendica\Core\L10n;
use Friendica\Core\Protocol;
use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Core\Session\Capability\IHandleUserSessions;
use Friendica\Core\System; use Friendica\Core\System;
use Friendica\Core\Worker;
use Friendica\Database\Database; use Friendica\Database\Database;
use Friendica\Model\Contact; use Friendica\Model\Contact;
use Friendica\Model\GServer; use Friendica\Model\GServer;
@ -36,7 +38,7 @@ use Friendica\Network\HTTPClient\Client\HttpClientOptions;
use Friendica\Util\HTTPSignature; use Friendica\Util\HTTPSignature;
use Friendica\Util\Profiler; use Friendica\Util\Profiler;
use Friendica\Util\Strings; use Friendica\Util\Strings;
use GuzzleHttp\Psr7\Uri; use Friendica\Worker\UpdateContact;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
/** /**
@ -115,22 +117,39 @@ class Magic extends BaseModule
$owner = User::getOwnerDataById($this->userSession->getLocalUserId()); $owner = User::getOwnerDataById($this->userSession->getLocalUserId());
if (!empty($contact['gsid'])) { if (!empty($contact['gsid'])) {
$gserver = $this->dba->selectFirst('gserver', ['url'], ['id' => $contact['gsid']]); $gsid = $contact['gsid'];
if (empty($gserver)) {
$this->logger->notice('Server not found, redirecting to destination.', ['gsid' => $contact['gsid'], 'dest' => $dest]);
System::externalRedirect($dest);
}
$basepath = $gserver['url'];
} elseif (GServer::check($target)) { } elseif (GServer::check($target)) {
$basepath = (string)GServer::cleanUri(new Uri($target)); $gsid = GServer::getID($target);
} else { }
if (empty($gsid)) {
$this->logger->notice('The target is not a server path, redirecting to destination.', ['target' => $target]); $this->logger->notice('The target is not a server path, redirecting to destination.', ['target' => $target]);
System::externalRedirect($dest); System::externalRedirect($dest);
} }
$gserver = $this->dba->selectFirst('gserver', ['url', 'network', 'openwebauth'], ['id' => $gsid]);
if (empty($gserver)) {
$this->logger->notice('Server not found, redirecting to destination.', ['gsid' => $gsid, 'dest' => $dest]);
System::externalRedirect($dest);
}
$openwebauth = $gserver['openwebauth'];
// This part can be removed, when all server entries had been updated. So removing it in 2025 should be safe.
if (empty($openwebauth) && ($gserver['network'] == Protocol::DFRN)) {
$this->logger->notice('Open Web Auth path not provided. Assume default path', ['gsid' => $gsid, 'dest' => $dest]);
$openwebauth = $gserver['url'] . '/owa';
// Update contact to assign the path to the server
UpdateContact::add(Worker::PRIORITY_MEDIUM, $contact['id']);
}
if (empty($openwebauth)) {
$this->logger->debug('Server does not support open web auth, redirecting to destination.', ['gsid' => $gsid, 'dest' => $dest]);
System::externalRedirect($dest);
}
$header = [ $header = [
'Accept' => 'application/x-dfrn+json, application/x-zot+json', 'Accept' => 'application/x-zot+json',
'X-Open-Web-Auth' => Strings::getRandomHex() 'X-Open-Web-Auth' => Strings::getRandomHex()
]; ];
@ -141,13 +160,13 @@ class Magic extends BaseModule
'acct:' . $owner['addr'] 'acct:' . $owner['addr']
); );
$this->logger->info('Fetch from remote system', ['basepath' => $basepath, 'headers' => $header]); $this->logger->info('Fetch from remote system', ['openwebauth' => $openwebauth, 'headers' => $header]);
// Try to get an authentication token from the other instance. // Try to get an authentication token from the other instance.
try { try {
$curlResult = $this->httpClient->request('get', $basepath . '/owa', [HttpClientOptions::HEADERS => $header]); $curlResult = $this->httpClient->request('get', $openwebauth, [HttpClientOptions::HEADERS => $header]);
} catch (Exception $exception) { } catch (Exception $exception) {
$this->logger->notice('URL is invalid, redirecting to destination.', ['url' => $basepath, 'error' => $exception, 'dest' => $dest]); $this->logger->notice('URL is invalid, redirecting to destination.', ['url' => $openwebauth, 'error' => $exception, 'dest' => $dest]);
System::externalRedirect($dest); System::externalRedirect($dest);
} }
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {

View file

@ -121,7 +121,7 @@ class Xrd extends BaseModule
'aliases' => [$owner['url']], 'aliases' => [$owner['url']],
'links' => [ 'links' => [
[ [
'rel' => 'http://webfinger.net/rel/profile-page', 'rel' => ActivityNamespace::WEBFINGERPROFILE,
'type' => 'text/html', 'type' => 'text/html',
'href' => $owner['url'], 'href' => $owner['url'],
], ],
@ -131,7 +131,7 @@ class Xrd extends BaseModule
'href' => $owner['url'], 'href' => $owner['url'],
], ],
[ [
'rel' => 'http://ostatus.org/schema/1.0/subscribe', 'rel' => ActivityNamespace::OSTATUSSUB,
'template' => $baseURL . '/contact/follow?url={uri}', 'template' => $baseURL . '/contact/follow?url={uri}',
], ],
[ [
@ -144,12 +144,12 @@ class Xrd extends BaseModule
'href' => $baseURL . '/salmon/' . $owner['nickname'], 'href' => $baseURL . '/salmon/' . $owner['nickname'],
], ],
[ [
'rel' => 'http://microformats.org/profile/hcard', 'rel' => ActivityNamespace::HCARD,
'type' => 'text/html', 'type' => 'text/html',
'href' => $baseURL . '/hcard/' . $owner['nickname'], 'href' => $baseURL . '/hcard/' . $owner['nickname'],
], ],
[ [
'rel' => 'http://joindiaspora.com/seed_location', 'rel' => ActivityNamespace::DIASPORA_SEED,
'type' => 'text/html', 'type' => 'text/html',
'href' => $baseURL, 'href' => $baseURL,
], ],
@ -171,7 +171,7 @@ class Xrd extends BaseModule
], ],
'links' => [ 'links' => [
[ [
'rel' => ActivityNamespace::DFRN , 'rel' => ActivityNamespace::DFRN,
'href' => $owner['url'], 'href' => $owner['url'],
], ],
[ [
@ -180,7 +180,7 @@ class Xrd extends BaseModule
'href' => $owner['poll'], 'href' => $owner['poll'],
], ],
[ [
'rel' => 'http://webfinger.net/rel/profile-page', 'rel' => ActivityNamespace::WEBFINGERPROFILE,
'type' => 'text/html', 'type' => 'text/html',
'href' => $owner['url'], 'href' => $owner['url'],
], ],
@ -190,17 +190,17 @@ class Xrd extends BaseModule
'href' => $owner['url'], 'href' => $owner['url'],
], ],
[ [
'rel' => 'http://microformats.org/profile/hcard', 'rel' => ActivityNamespace::HCARD,
'type' => 'text/html', 'type' => 'text/html',
'href' => $baseURL . '/hcard/' . $owner['nickname'], 'href' => $baseURL . '/hcard/' . $owner['nickname'],
], ],
[ [
'rel' => 'http://webfinger.net/rel/avatar', 'rel' => ActivityNamespace::WEBFINGERAVATAR,
'type' => $avatar['type'], 'type' => $avatar['type'],
'href' => User::getAvatarUrl($owner), 'href' => User::getAvatarUrl($owner),
], ],
[ [
'rel' => 'http://joindiaspora.com/seed_location', 'rel' => ActivityNamespace::DIASPORA_SEED,
'type' => 'text/html', 'type' => 'text/html',
'href' => $baseURL, 'href' => $baseURL,
], ],
@ -217,7 +217,7 @@ class Xrd extends BaseModule
'href' => $baseURL . '/salmon/' . $owner['nickname'] . '/mention', 'href' => $baseURL . '/salmon/' . $owner['nickname'] . '/mention',
], ],
[ [
'rel' => 'http://ostatus.org/schema/1.0/subscribe', 'rel' => ActivityNamespace::OSTATUSSUB,
'template' => $baseURL . '/contact/follow?url={uri}', 'template' => $baseURL . '/contact/follow?url={uri}',
], ],
[ [
@ -225,7 +225,7 @@ class Xrd extends BaseModule
'href' => 'data:application/magic-public-key,' . Salmon::salmonKey($owner['spubkey']), 'href' => 'data:application/magic-public-key,' . Salmon::salmonKey($owner['spubkey']),
], ],
[ [
'rel' => 'http://purl.org/openwebauth/v1', 'rel' => ActivityNamespace::OPENWEBAUTH,
'type' => 'application/x-zot+json', 'type' => 'application/x-zot+json',
'href' => $baseURL . '/owa', 'href' => $baseURL . '/owa',
], ],
@ -263,28 +263,28 @@ class Xrd extends BaseModule
], ],
'3:link' => [ '3:link' => [
'@attributes' => [ '@attributes' => [
'rel' => 'http://webfinger.net/rel/profile-page', 'rel' => ActivityNamespace::WEBFINGERPROFILE,
'type' => 'text/html', 'type' => 'text/html',
'href' => $owner['url'] 'href' => $owner['url']
] ]
], ],
'4:link' => [ '4:link' => [
'@attributes' => [ '@attributes' => [
'rel' => 'http://microformats.org/profile/hcard', 'rel' => ActivityNamespace::HCARD,
'type' => 'text/html', 'type' => 'text/html',
'href' => $baseURL . '/hcard/' . $owner['nickname'] 'href' => $baseURL . '/hcard/' . $owner['nickname']
] ]
], ],
'5:link' => [ '5:link' => [
'@attributes' => [ '@attributes' => [
'rel' => 'http://webfinger.net/rel/avatar', 'rel' => ActivityNamespace::WEBFINGERAVATAR,
'type' => $avatar['type'], 'type' => $avatar['type'],
'href' => User::getAvatarUrl($owner) 'href' => User::getAvatarUrl($owner)
] ]
], ],
'6:link' => [ '6:link' => [
'@attributes' => [ '@attributes' => [
'rel' => 'http://joindiaspora.com/seed_location', 'rel' => ActivityNamespace::DIASPORA_SEED,
'type' => 'text/html', 'type' => 'text/html',
'href' => $baseURL 'href' => $baseURL
] ]
@ -309,7 +309,7 @@ class Xrd extends BaseModule
], ],
'10:link' => [ '10:link' => [
'@attributes' => [ '@attributes' => [
'rel' => 'http://ostatus.org/schema/1.0/subscribe', 'rel' => ActivityNamespace::OSTATUSSUB,
'template' => $baseURL . '/contact/follow?url={uri}' 'template' => $baseURL . '/contact/follow?url={uri}'
] ]
], ],
@ -321,7 +321,7 @@ class Xrd extends BaseModule
], ],
'12:link' => [ '12:link' => [
'@attributes' => [ '@attributes' => [
'rel' => 'http://purl.org/openwebauth/v1', 'rel' => ActivityNamespace::OPENWEBAUTH,
'type' => 'application/x-zot+json', 'type' => 'application/x-zot+json',
'href' => $baseURL . '/owa' 'href' => $baseURL . '/owa'
] ]

View file

@ -117,7 +117,7 @@ class Probe
'photo', 'photo_medium', 'photo_small', 'header', 'photo', 'photo_medium', 'photo_small', 'header',
'account-type', 'community', 'keywords', 'location', 'about', 'xmpp', 'matrix', 'account-type', 'community', 'keywords', 'location', 'about', 'xmpp', 'matrix',
'hide', 'batch', 'notify', 'poll', 'request', 'confirm', 'subscribe', 'poco', 'hide', 'batch', 'notify', 'poll', 'request', 'confirm', 'subscribe', 'poco',
'following', 'followers', 'inbox', 'outbox', 'sharedinbox', 'openwebauth', 'following', 'followers', 'inbox', 'outbox', 'sharedinbox',
'priority', 'network', 'pubkey', 'manually-approve', 'baseurl', 'gsid' 'priority', 'network', 'pubkey', 'manually-approve', 'baseurl', 'gsid'
]; ];
@ -384,6 +384,12 @@ class Probe
unset($data['networks']); unset($data['networks']);
if (!empty($data['network'])) { if (!empty($data['network'])) {
$networks[$data['network']] = $data; $networks[$data['network']] = $data;
$ap_profile['guid'] = $ap_profile['guid'] ?? $data['guid'] ?? null;
$ap_profile['about'] = $ap_profile['about'] ?? $data['about'] ?? null;
$ap_profile['keywords'] = $data['keywords'] ?? null;
$ap_profile['location'] = $data['location'] ?? null;
$ap_profile['poco'] = $data['poco'] ?? null;
$ap_profile['openwebauth'] = $data['openwebauth'] ?? null;
} }
$data = $ap_profile; $data = $ap_profile;
$data['networks'] = $networks; $data['networks'] = $networks;
@ -524,6 +530,8 @@ class Probe
foreach ($webfinger['links'] as $link) { foreach ($webfinger['links'] as $link) {
if (!empty($link['template']) && ($link['rel'] === ActivityNamespace::OSTATUSSUB)) { if (!empty($link['template']) && ($link['rel'] === ActivityNamespace::OSTATUSSUB)) {
$result['subscribe'] = $link['template']; $result['subscribe'] = $link['template'];
} elseif (!empty($link['href']) && ($link['rel'] === ActivityNamespace::OPENWEBAUTH) && ($link['type'] === 'application/x-zot+json')) {
$result['openwebauth'] = $link['href'];
} }
} }
@ -855,7 +863,7 @@ class Probe
} }
foreach ($webfinger['links'] as $link) { foreach ($webfinger['links'] as $link) {
if (($link['rel'] == 'http://webfinger.net/rel/avatar') && !empty($link['href'])) { if (($link['rel'] == ActivityNamespace::WEBFINGERAVATAR) && !empty($link['href'])) {
$data['photo'] = $link['href']; $data['photo'] = $link['href'];
} elseif (($link['rel'] == 'http://openid.net/specs/connect/1.0/issuer') && !empty($link['href'])) { } elseif (($link['rel'] == 'http://openid.net/specs/connect/1.0/issuer') && !empty($link['href'])) {
$data['baseurl'] = trim($link['href'], '/'); $data['baseurl'] = trim($link['href'], '/');
@ -1178,17 +1186,17 @@ class Probe
$data['network'] = Protocol::DFRN; $data['network'] = Protocol::DFRN;
} elseif (($link['rel'] == ActivityNamespace::FEED) && !empty($link['href'])) { } elseif (($link['rel'] == ActivityNamespace::FEED) && !empty($link['href'])) {
$data['poll'] = $link['href']; $data['poll'] = $link['href'];
} elseif (($link['rel'] == 'http://webfinger.net/rel/profile-page') && (($link['type'] ?? '') == 'text/html') && !empty($link['href'])) { } elseif (($link['rel'] == ActivityNamespace::WEBFINGERPROFILE) && (($link['type'] ?? '') == 'text/html') && !empty($link['href'])) {
$data['url'] = $link['href']; $data['url'] = $link['href'];
} elseif (($link['rel'] == 'http://microformats.org/profile/hcard') && !empty($link['href'])) { } elseif (($link['rel'] == ActivityNamespace::HCARD) && !empty($link['href'])) {
$hcard_url = $link['href']; $hcard_url = $link['href'];
} elseif (($link['rel'] == ActivityNamespace::POCO) && !empty($link['href'])) { } elseif (($link['rel'] == ActivityNamespace::POCO) && !empty($link['href'])) {
$data['poco'] = $link['href']; $data['poco'] = $link['href'];
} elseif (($link['rel'] == 'http://webfinger.net/rel/avatar') && !empty($link['href'])) { } elseif (($link['rel'] == ActivityNamespace::WEBFINGERAVATAR) && !empty($link['href'])) {
$data['photo'] = $link['href']; $data['photo'] = $link['href'];
} elseif (($link['rel'] == 'http://joindiaspora.com/seed_location') && !empty($link['href'])) { } elseif (($link['rel'] == ActivityNamespace::DIASPORA_SEED) && !empty($link['href'])) {
$data['baseurl'] = trim($link['href'], '/'); $data['baseurl'] = trim($link['href'], '/');
} elseif (($link['rel'] == 'http://joindiaspora.com/guid') && !empty($link['href'])) { } elseif (($link['rel'] == ActivityNamespace::DIASPORA_GUID) && !empty($link['href'])) {
$data['guid'] = $link['href']; $data['guid'] = $link['href'];
} elseif (($link['rel'] == 'diaspora-public-key') && !empty($link['href'])) { } elseif (($link['rel'] == 'diaspora-public-key') && !empty($link['href'])) {
$data['pubkey'] = base64_decode($link['href']); $data['pubkey'] = base64_decode($link['href']);
@ -1361,15 +1369,15 @@ class Probe
// The array is reversed to take into account the order of preference for same-rel links // The array is reversed to take into account the order of preference for same-rel links
// See: https://tools.ietf.org/html/rfc7033#section-4.4.4 // See: https://tools.ietf.org/html/rfc7033#section-4.4.4
foreach (array_reverse($webfinger['links']) as $link) { foreach (array_reverse($webfinger['links']) as $link) {
if (($link['rel'] == 'http://microformats.org/profile/hcard') && !empty($link['href'])) { if (($link['rel'] == ActivityNamespace::HCARD) && !empty($link['href'])) {
$hcard_url = $link['href']; $hcard_url = $link['href'];
} elseif (($link['rel'] == 'http://joindiaspora.com/seed_location') && !empty($link['href'])) { } elseif (($link['rel'] == ActivityNamespace::DIASPORA_SEED) && !empty($link['href'])) {
$data['baseurl'] = trim($link['href'], '/'); $data['baseurl'] = trim($link['href'], '/');
} elseif (($link['rel'] == 'http://joindiaspora.com/guid') && !empty($link['href'])) { } elseif (($link['rel'] == ActivityNamespace::DIASPORA_GUID) && !empty($link['href'])) {
$data['guid'] = $link['href']; $data['guid'] = $link['href'];
} elseif (($link['rel'] == 'http://webfinger.net/rel/profile-page') && (($link['type'] ?? '') == 'text/html') && !empty($link['href'])) { } elseif (($link['rel'] == ActivityNamespace::WEBFINGERPROFILE) && (($link['type'] ?? '') == 'text/html') && !empty($link['href'])) {
$data['url'] = $link['href']; $data['url'] = $link['href'];
} elseif (($link['rel'] == 'http://webfinger.net/rel/profile-page') && empty($link['type']) && !empty($link['href'])) { } elseif (($link['rel'] == ActivityNamespace::WEBFINGERPROFILE) && empty($link['type']) && !empty($link['href'])) {
$profile_url = $link['href']; $profile_url = $link['href'];
} elseif (($link['rel'] == ActivityNamespace::FEED) && !empty($link['href'])) { } elseif (($link['rel'] == ActivityNamespace::FEED) && !empty($link['href'])) {
$data['poll'] = $link['href']; $data['poll'] = $link['href'];
@ -1472,7 +1480,7 @@ class Probe
// The array is reversed to take into account the order of preference for same-rel links // The array is reversed to take into account the order of preference for same-rel links
// See: https://tools.ietf.org/html/rfc7033#section-4.4.4 // See: https://tools.ietf.org/html/rfc7033#section-4.4.4
foreach (array_reverse($webfinger['links']) as $link) { foreach (array_reverse($webfinger['links']) as $link) {
if (($link['rel'] == 'http://webfinger.net/rel/profile-page') if (($link['rel'] == ActivityNamespace::WEBFINGERPROFILE)
&& (($link['type'] ?? '') == 'text/html') && (($link['type'] ?? '') == 'text/html')
&& ($link['href'] != '') && ($link['href'] != '')
) { ) {
@ -2066,6 +2074,7 @@ class Probe
'hide' => !$owner['net-publish'], 'batch' => '', 'notify' => $owner['notify'], 'hide' => !$owner['net-publish'], 'batch' => '', 'notify' => $owner['notify'],
'poll' => $owner['poll'], 'poll' => $owner['poll'],
'subscribe' => $approfile['generator']['url'] . '/contact/follow?url={uri}', 'poco' => $owner['poco'], 'subscribe' => $approfile['generator']['url'] . '/contact/follow?url={uri}', 'poco' => $owner['poco'],
'openwebauth' => $approfile['generator']['url'] . '/owa',
'following' => $approfile['following'], 'followers' => $approfile['followers'], 'following' => $approfile['following'], 'followers' => $approfile['followers'],
'inbox' => $approfile['inbox'], 'outbox' => $approfile['outbox'], 'inbox' => $approfile['inbox'], 'outbox' => $approfile['outbox'],
'sharedinbox' => $approfile['endpoints']['sharedInbox'], 'network' => Protocol::DFRN, 'sharedinbox' => $approfile['endpoints']['sharedInbox'], 'network' => Protocol::DFRN,

View file

@ -104,6 +104,39 @@ final class ActivityNamespace
* @var string * @var string
*/ */
const OSTATUSSUB = 'http://ostatus.org/schema/1.0/subscribe'; const OSTATUSSUB = 'http://ostatus.org/schema/1.0/subscribe';
/**
* Webfinger avatar
*
* @see https://webfinger.net/rel/#avatar
* @var string
*/
const WEBFINGERAVATAR = 'http://webfinger.net/rel/avatar';
/**
* Webfinger profile
*
* @see https://webfinger.net/rel/#profile-page
* @var string
*/
const WEBFINGERPROFILE = 'http://webfinger.net/rel/profile-page';
/**
* HCard
*
* @see http://microformats.org/wiki/hcard
* @var string
*/
const HCARD = 'http://microformats.org/profile/hcard';
/**
* Base url of the Diaspora installation
*
* @var string
*/
const DIASPORA_SEED = 'http://joindiaspora.com/seed_location';
/**
* Diaspora Guid
*
* @var string
*/
const DIASPORA_GUID = 'http://joindiaspora.com/guid';
/** /**
* GeoRSS was designed as a lightweight, community driven way to extend existing feeds with geographic information. * GeoRSS was designed as a lightweight, community driven way to extend existing feeds with geographic information.
* *
@ -120,6 +153,12 @@ final class ActivityNamespace
* @var string * @var string
*/ */
const POCO = 'http://portablecontacts.net/spec/1.0'; const POCO = 'http://portablecontacts.net/spec/1.0';
/**
* OpenWebAuth is used by Friendica and Hubzilla to authenticate at remote systems
*
* @var string
*/
const OPENWEBAUTH = 'http://purl.org/openwebauth/v1';
/** /**
* @var string * @var string
*/ */

View file

@ -56,7 +56,7 @@ use Friendica\Database\DBA;
// This file is required several times during the test in DbaDefinition which justifies this condition // This file is required several times during the test in DbaDefinition which justifies this condition
if (!defined('DB_UPDATE_VERSION')) { if (!defined('DB_UPDATE_VERSION')) {
define('DB_UPDATE_VERSION', 1560); define('DB_UPDATE_VERSION', 1561);
} }
return [ return [
@ -79,6 +79,7 @@ return [
"local-comments" => ["type" => "int unsigned", "comment" => "Number of local comments"], "local-comments" => ["type" => "int unsigned", "comment" => "Number of local comments"],
"directory-type" => ["type" => "tinyint", "default" => "0", "comment" => "Type of directory service (Poco, Mastodon)"], "directory-type" => ["type" => "tinyint", "default" => "0", "comment" => "Type of directory service (Poco, Mastodon)"],
"poco" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], "poco" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""],
"openwebauth" => ["type" => "varbinary(383)", "comment" => "Path to the OpenWebAuth endpoint"],
"noscrape" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""], "noscrape" => ["type" => "varbinary(383)", "not null" => "1", "default" => "", "comment" => ""],
"network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => ""], "network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => ""],
"protocol" => ["type" => "tinyint unsigned", "comment" => "The protocol of the server"], "protocol" => ["type" => "tinyint unsigned", "comment" => "The protocol of the server"],