Add webfinger integration, bug fixes and minor changes ( #21 )
Added author credits in every function so that we know who to bother when something goes wrong Refer to issues #34 and #35
This commit is contained in:
parent
2d0f3de52a
commit
30c073538c
@ -1,5 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . DIRECTORY_SEPARATOR . "utils" . DIRECTORY_SEPARATOR . "postman.php";
|
|
||||||
/**
|
/**
|
||||||
* GNU social - a federating social network
|
* GNU social - a federating social network
|
||||||
*
|
*
|
||||||
@ -30,6 +29,11 @@ if (!defined ('GNUSOCIAL')) {
|
|||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Import required files by the plugin
|
||||||
|
require_once __DIR__ . DIRECTORY_SEPARATOR . "utils" . DIRECTORY_SEPARATOR . "discoveryhints.php";
|
||||||
|
require_once __DIR__ . DIRECTORY_SEPARATOR . "utils" . DIRECTORY_SEPARATOR . "explorer.php";
|
||||||
|
require_once __DIR__ . DIRECTORY_SEPARATOR . "utils" . DIRECTORY_SEPARATOR . "postman.php";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @category Plugin
|
* @category Plugin
|
||||||
* @package GNUsocial
|
* @package GNUsocial
|
||||||
@ -40,6 +44,50 @@ if (!defined ('GNUSOCIAL')) {
|
|||||||
*/
|
*/
|
||||||
class ActivityPubPlugin extends Plugin
|
class ActivityPubPlugin extends Plugin
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Get remote user's ActivityPub_profile via a identifier
|
||||||
|
* (https://www.w3.org/TR/activitypub/#obj-id)
|
||||||
|
*
|
||||||
|
* @author GNU Social
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
|
* @param string $arg A remote user identifier
|
||||||
|
* @return Activitypub_profile|null Valid profile in success | null otherwise
|
||||||
|
*/
|
||||||
|
protected function pull_remote_profile ($arg)
|
||||||
|
{
|
||||||
|
if (preg_match ('!^((?:\w+\.)*\w+@(?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+)$!', $arg)) {
|
||||||
|
// webfinger lookup
|
||||||
|
try {
|
||||||
|
return Activitypub_profile::ensure_web_finger ($arg);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
common_log(LOG_ERR, 'Webfinger lookup failed for ' .
|
||||||
|
$arg . ': ' . $e->getMessage ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for profile URLs, with or without scheme:
|
||||||
|
$urls = array ();
|
||||||
|
if (preg_match ('!^https?://((?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+(?:/\w+)+)$!', $arg)) {
|
||||||
|
$urls[] = $arg;
|
||||||
|
}
|
||||||
|
if (preg_match ('!^((?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+(?:/\w+)+)$!', $arg)) {
|
||||||
|
$schemes = array ('http', 'https');
|
||||||
|
foreach ($schemes as $scheme) {
|
||||||
|
$urls[] = "$scheme://$arg";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($urls as $url) {
|
||||||
|
try {
|
||||||
|
return Activitypub_profile::get_from_uri ($url);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
common_log(LOG_ERR, 'Profile lookup failed for ' .
|
||||||
|
$arg . ': ' . $e->getMessage ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Route/Reroute urls
|
* Route/Reroute urls
|
||||||
*
|
*
|
||||||
@ -77,7 +125,7 @@ class ActivityPubPlugin extends Plugin
|
|||||||
* Plugin version information
|
* Plugin version information
|
||||||
*
|
*
|
||||||
* @param array $versions
|
* @param array $versions
|
||||||
* @return boolean true
|
* @return boolean hook true
|
||||||
*/
|
*/
|
||||||
public function onPluginVersion (array &$versions)
|
public function onPluginVersion (array &$versions)
|
||||||
{
|
{
|
||||||
@ -94,6 +142,8 @@ class ActivityPubPlugin extends Plugin
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Make sure necessary tables are filled out.
|
* Make sure necessary tables are filled out.
|
||||||
|
*
|
||||||
|
* @return boolean hook true
|
||||||
*/
|
*/
|
||||||
function onCheckSchema ()
|
function onCheckSchema ()
|
||||||
{
|
{
|
||||||
@ -102,6 +152,251 @@ class ActivityPubPlugin extends Plugin
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************
|
||||||
|
* Discovery Events *
|
||||||
|
********************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Webfinger matches: @user@example.com or even @user--one.george_orwell@1984.biz
|
||||||
|
*
|
||||||
|
* @author GNU Social
|
||||||
|
* @param string $text The text from which to extract webfinger IDs
|
||||||
|
* @param string $preMention Character(s) that signals a mention ('@', '!'...)
|
||||||
|
* @return array The matching IDs (without $preMention) and each respective position in the given string.
|
||||||
|
*/
|
||||||
|
static function extractWebfingerIds ($text, $preMention='@')
|
||||||
|
{
|
||||||
|
$wmatches = array ();
|
||||||
|
$result = preg_match_all ('/(?<!\S)'.preg_quote ($preMention, '/').'('.Nickname::WEBFINGER_FMT.')/',
|
||||||
|
$text,
|
||||||
|
$wmatches,
|
||||||
|
PREG_OFFSET_CAPTURE);
|
||||||
|
if ($result === false) {
|
||||||
|
common_log (LOG_ERR, __METHOD__ . ': Error parsing webfinger IDs from text (preg_last_error=='.preg_last_error ().').');
|
||||||
|
} elseif (count ($wmatches)) {
|
||||||
|
common_debug (sprintf ('Found %d matches for WebFinger IDs: %s', count ($wmatches), _ve ($wmatches)));
|
||||||
|
}
|
||||||
|
return $wmatches[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Profile URL matches: @example.com/mublog/user
|
||||||
|
*
|
||||||
|
* @author GNU Social
|
||||||
|
* @param string $text The text from which to extract URL mentions
|
||||||
|
* @param string $preMention Character(s) that signals a mention ('@', '!'...)
|
||||||
|
* @return array The matching URLs (without @ or acct:) and each respective position in the given string.
|
||||||
|
*/
|
||||||
|
static function extractUrlMentions ($text, $preMention='@')
|
||||||
|
{
|
||||||
|
$wmatches = array ();
|
||||||
|
// In the regexp below we need to match / _before_ URL_REGEX_VALID_PATH_CHARS because it otherwise gets merged
|
||||||
|
// with the TLD before (but / is in URL_REGEX_VALID_PATH_CHARS anyway, it's just its positioning that is important)
|
||||||
|
$result = preg_match_all ('/(?:^|\s+)'.preg_quote ($preMention, '/').'('.URL_REGEX_DOMAIN_NAME.'(?:\/['.URL_REGEX_VALID_PATH_CHARS.']*)*)/',
|
||||||
|
$text,
|
||||||
|
$wmatches,
|
||||||
|
PREG_OFFSET_CAPTURE);
|
||||||
|
if ($result === false) {
|
||||||
|
common_log (LOG_ERR, __METHOD__ . ': Error parsing profile URL mentions from text (preg_last_error=='.preg_last_error ().').');
|
||||||
|
} elseif (count ($wmatches)) {
|
||||||
|
common_debug(sprintf('Found %d matches for profile URL mentions: %s', count ($wmatches), _ve ($wmatches)));
|
||||||
|
}
|
||||||
|
return $wmatches[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find any explicit remote mentions. Accepted forms:
|
||||||
|
* Webfinger: @user@example.com
|
||||||
|
* Profile link: @example.com/mublog/user
|
||||||
|
*
|
||||||
|
* @author GNU Social
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
|
* @param Profile $sender
|
||||||
|
* @param string $text input markup text
|
||||||
|
* @param array &$mention in/out param: set of found mentions
|
||||||
|
* @return boolean hook return value
|
||||||
|
*/
|
||||||
|
function onEndFindMentions(Profile $sender, $text, &$mentions)
|
||||||
|
{
|
||||||
|
$matches = array();
|
||||||
|
|
||||||
|
foreach (self::extractWebfingerIds($text, '@') as $wmatch) {
|
||||||
|
list($target, $pos) = $wmatch;
|
||||||
|
$this->log(LOG_INFO, "Checking webfinger person '$target'");
|
||||||
|
$profile = null;
|
||||||
|
try {
|
||||||
|
$aprofile = Activitypub_profile::ensure_web_finger($target);
|
||||||
|
$profile = $aprofile->local_profile();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->log(LOG_ERR, "Webfinger check failed: " . $e->getMessage());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
assert ($profile instanceof Profile);
|
||||||
|
|
||||||
|
$displayName = !empty ($profile->nickname) && mb_strlen ($profile->nickname) < mb_strlen ($target)
|
||||||
|
? $profile->getNickname () // TODO: we could do getBestName() or getFullname() here
|
||||||
|
: $target;
|
||||||
|
$url = $profile->getUri ();
|
||||||
|
if (!common_valid_http_url ($url)) {
|
||||||
|
$url = $profile->getUrl ();
|
||||||
|
}
|
||||||
|
$matches[$pos] = array('mentioned' => array ($profile),
|
||||||
|
'type' => 'mention',
|
||||||
|
'text' => $displayName,
|
||||||
|
'position' => $pos,
|
||||||
|
'length' => mb_strlen ($target),
|
||||||
|
'url' => $url);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (self::extractUrlMentions ($text) as $wmatch) {
|
||||||
|
list ($target, $pos) = $wmatch;
|
||||||
|
$schemes = array('https', 'http');
|
||||||
|
foreach ($schemes as $scheme) {
|
||||||
|
$url = "$scheme://$target";
|
||||||
|
$this->log(LOG_INFO, "Checking profile address '$url'");
|
||||||
|
try {
|
||||||
|
$aprofile = Activitypub_profile::get_from_uri ($url);
|
||||||
|
$profile = $aprofile->local_profile();
|
||||||
|
$displayName = !empty ($profile->nickname) && mb_strlen ($profile->nickname) < mb_strlen ($target) ?
|
||||||
|
$profile->nickname : $target;
|
||||||
|
$matches[$pos] = array('mentioned' => array ($profile),
|
||||||
|
'type' => 'mention',
|
||||||
|
'text' => $displayName,
|
||||||
|
'position' => $pos,
|
||||||
|
'length' => mb_strlen ($target),
|
||||||
|
'url' => $profile->getUrl());
|
||||||
|
break;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->log(LOG_ERR, "Profile check failed: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($mentions as $i => $other) {
|
||||||
|
// If we share a common prefix with a local user, override it!
|
||||||
|
$pos = $other['position'];
|
||||||
|
if (isset ($matches[$pos])) {
|
||||||
|
$mentions[$i] = $matches[$pos];
|
||||||
|
unset ($matches[$pos]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($matches as $mention) {
|
||||||
|
$mentions[] = $mention;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow remote profile references to be used in commands:
|
||||||
|
* sub update@status.net
|
||||||
|
* whois evan@identi.ca
|
||||||
|
* reply http://identi.ca/evan hey what's up
|
||||||
|
*
|
||||||
|
* @author GNU Social
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
|
* @param Command $command
|
||||||
|
* @param string $arg
|
||||||
|
* @param Profile &$profile
|
||||||
|
* @return hook return code
|
||||||
|
*/
|
||||||
|
function onStartCommandGetProfile ($command, $arg, &$profile)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$aprofile = $this->pull_remote_profile ($arg);
|
||||||
|
$profile = $aprofile->local_profile();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// No remote ActivityPub profile found
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Profile URI for remote profiles.
|
||||||
|
*
|
||||||
|
* @author GNU Social
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
|
* @param Profile $profile
|
||||||
|
* @param string $uri in/out
|
||||||
|
* @return mixed hook return code
|
||||||
|
*/
|
||||||
|
function onStartGetProfileUri ($profile, &$uri)
|
||||||
|
{
|
||||||
|
$aprofile = Activitypub_profile::getKV ('profile_id', $profile->id);
|
||||||
|
if ($aprofile instanceof Activitypub_profile) {
|
||||||
|
$uri = $aprofile->get_uri ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy string on AccountProfileBlock stating that ActivityPub is active
|
||||||
|
* this is more of a placeholder for eventual useful stuff ._.
|
||||||
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function onEndShowAccountProfileBlock (HTMLOutputter $out, Profile $profile)
|
||||||
|
{
|
||||||
|
if ($profile->isLocal()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$aprofile = Activitypub_profile::getKV ('profile_id', $profile->id);
|
||||||
|
} catch (NoResultException $e) {
|
||||||
|
// Not a remote ActivityPub_profile! Maybe some other network
|
||||||
|
// that has imported a non-local user (e.g.: OStatus)?
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$out->elementStart('dl', 'entity_tags activitypub_profile');
|
||||||
|
$out->element('dt', null, _m('ActivityPub'));
|
||||||
|
$out->element('dd', null, _m('Active'));
|
||||||
|
$out->elementEnd('dl');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Profile from URI.
|
||||||
|
*
|
||||||
|
* @author GNU Social
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
|
* @param string $uri
|
||||||
|
* @param Profile &$profile in/out param: Profile got from URI
|
||||||
|
* @return mixed hook return code
|
||||||
|
*/
|
||||||
|
function onStartGetProfileFromURI ($uri, &$profile)
|
||||||
|
{
|
||||||
|
// Don't want to do Web-based discovery on our own server,
|
||||||
|
// so we check locally first. This duplicates the functionality
|
||||||
|
// in the Profile class, since the plugin always runs before
|
||||||
|
// that local lookup, but since we return false it won't run double.
|
||||||
|
|
||||||
|
$user = User::getKV ('uri', $uri);
|
||||||
|
if ($user instanceof User) {
|
||||||
|
$profile = $user->getProfile();
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
$group = User_group::getKV ('uri', $uri);
|
||||||
|
if ($group instanceof User_group) {
|
||||||
|
$profile = $group->getProfile ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, check remotely
|
||||||
|
try {
|
||||||
|
$aprofile = Activitypub_profile::get_from_uri ($uri);
|
||||||
|
$profile = $aprofile->local_profile ();
|
||||||
|
return false;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return true; // It's not an ActivityPub profile as far as we know, continue event handling
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************
|
/********************************************************
|
||||||
* Delivery Events *
|
* Delivery Events *
|
||||||
********************************************************/
|
********************************************************/
|
||||||
@ -110,6 +405,7 @@ class ActivityPubPlugin extends Plugin
|
|||||||
* Having established a remote subscription, send a notification to the
|
* Having established a remote subscription, send a notification to the
|
||||||
* remote ActivityPub profile's endpoint.
|
* remote ActivityPub profile's endpoint.
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Profile $profile subscriber
|
* @param Profile $profile subscriber
|
||||||
* @param Profile $other subscribee
|
* @param Profile $other subscribee
|
||||||
* @return hook return value
|
* @return hook return value
|
||||||
@ -137,6 +433,7 @@ class ActivityPubPlugin extends Plugin
|
|||||||
/**
|
/**
|
||||||
* Notify remote server on unsubscribe.
|
* Notify remote server on unsubscribe.
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Profile $profile
|
* @param Profile $profile
|
||||||
* @param Profile $other
|
* @param Profile $other
|
||||||
* @return hook return value
|
* @return hook return value
|
||||||
@ -163,6 +460,7 @@ class ActivityPubPlugin extends Plugin
|
|||||||
/**
|
/**
|
||||||
* Notify remote users when their notices get favorited.
|
* Notify remote users when their notices get favorited.
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Profile $profile of local user doing the faving
|
* @param Profile $profile of local user doing the faving
|
||||||
* @param Notice $notice Notice being favored
|
* @param Notice $notice Notice being favored
|
||||||
* @return hook return value
|
* @return hook return value
|
||||||
@ -221,6 +519,7 @@ class ActivityPubPlugin extends Plugin
|
|||||||
/**
|
/**
|
||||||
* Notify remote users when their notices get de-favorited.
|
* Notify remote users when their notices get de-favorited.
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Profile $profile of local user doing the de-faving
|
* @param Profile $profile of local user doing the de-faving
|
||||||
* @param Notice $notice Notice being favored
|
* @param Notice $notice Notice being favored
|
||||||
* @return hook return value
|
* @return hook return value
|
||||||
@ -279,6 +578,7 @@ class ActivityPubPlugin extends Plugin
|
|||||||
/**
|
/**
|
||||||
* Notify remote users when their notices get deleted
|
* Notify remote users when their notices get deleted
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @return boolean hook flag
|
* @return boolean hook flag
|
||||||
*/
|
*/
|
||||||
public function onEndDeleteOwnNotice ($user, $notice)
|
public function onEndDeleteOwnNotice ($user, $notice)
|
||||||
@ -331,6 +631,7 @@ class ActivityPubPlugin extends Plugin
|
|||||||
/**
|
/**
|
||||||
* Insert notifications for replies, mentions and repeats
|
* Insert notifications for replies, mentions and repeats
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @return boolean hook flag
|
* @return boolean hook flag
|
||||||
*/
|
*/
|
||||||
function onStartNoticeDistribute ($notice)
|
function onStartNoticeDistribute ($notice)
|
||||||
@ -416,6 +717,7 @@ class ActivityPubPlugin extends Plugin
|
|||||||
* Override the "from ActivityPub" bit in notice lists to link to the
|
* Override the "from ActivityPub" bit in notice lists to link to the
|
||||||
* original post and show the domain it came from.
|
* original post and show the domain it came from.
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Notice in $notice
|
* @param Notice in $notice
|
||||||
* @param string out &$name
|
* @param string out &$name
|
||||||
* @param string out &$url
|
* @param string out &$url
|
||||||
@ -451,23 +753,6 @@ class ActivityPubPlugin extends Plugin
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Profile URI for remote profiles.
|
|
||||||
*
|
|
||||||
* @param Profile $profile
|
|
||||||
* @param string $uri in/out
|
|
||||||
* @return mixed hook return code
|
|
||||||
*/
|
|
||||||
function onStartGetProfileUri ($profile, &$uri)
|
|
||||||
{
|
|
||||||
$aprofile = Activitypub_profile::getKV ('profile_id', $profile->id);
|
|
||||||
if ($aprofile instanceof Activitypub_profile) {
|
|
||||||
$uri = $aprofile->uri;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -504,6 +789,7 @@ class ActivityPubReturn
|
|||||||
/**
|
/**
|
||||||
* Return a valid answer
|
* Return a valid answer
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param array $res
|
* @param array $res
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
@ -517,6 +803,7 @@ class ActivityPubReturn
|
|||||||
/**
|
/**
|
||||||
* Return an error
|
* Return an error
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param string $m
|
* @param string $m
|
||||||
* @param int32 $code
|
* @param int32 $code
|
||||||
* @return void
|
* @return void
|
||||||
|
@ -46,6 +46,7 @@ class apActorFollowersAction extends ManagedAction
|
|||||||
/**
|
/**
|
||||||
* Handle the Followers Collection request
|
* Handle the Followers Collection request
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function handle ()
|
protected function handle ()
|
||||||
|
@ -46,6 +46,7 @@ class apActorFollowingAction extends ManagedAction
|
|||||||
/**
|
/**
|
||||||
* Handle the Following Collection request
|
* Handle the Following Collection request
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function handle ()
|
protected function handle ()
|
||||||
|
@ -46,6 +46,7 @@ class apActorInboxAction extends ManagedAction
|
|||||||
/**
|
/**
|
||||||
* Handle the Actor Inbox request
|
* Handle the Actor Inbox request
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function handle ()
|
protected function handle ()
|
||||||
|
@ -46,6 +46,7 @@ class apActorLikedCollectionAction extends ManagedAction
|
|||||||
/**
|
/**
|
||||||
* Handle the Liked Collection request
|
* Handle the Liked Collection request
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function handle ()
|
protected function handle ()
|
||||||
@ -99,6 +100,7 @@ class apActorLikedCollectionAction extends ManagedAction
|
|||||||
* Take a fave object and turns it in a pretty array to be used
|
* Take a fave object and turns it in a pretty array to be used
|
||||||
* as a plugin answer
|
* as a plugin answer
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Fave $fave_object
|
* @param Fave $fave_object
|
||||||
* @return array pretty array representating a Fave
|
* @return array pretty array representating a Fave
|
||||||
*/
|
*/
|
||||||
@ -114,6 +116,7 @@ class apActorLikedCollectionAction extends ManagedAction
|
|||||||
/**
|
/**
|
||||||
* Fetch faves
|
* Fetch faves
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param int32 $user_id
|
* @param int32 $user_id
|
||||||
* @param int32 $limit
|
* @param int32 $limit
|
||||||
* @param int32 $since_id
|
* @param int32 $since_id
|
||||||
|
@ -47,6 +47,7 @@ class apActorProfileAction extends ManagedAction
|
|||||||
/**
|
/**
|
||||||
* Handle the Actor Profile request
|
* Handle the Actor Profile request
|
||||||
*
|
*
|
||||||
|
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function handle()
|
protected function handle()
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once dirname (__DIR__) . DIRECTORY_SEPARATOR . "utils" . DIRECTORY_SEPARATOR . "explorer.php";
|
|
||||||
/**
|
/**
|
||||||
* GNU social - a federating social network
|
* GNU social - a federating social network
|
||||||
*
|
*
|
||||||
@ -47,6 +46,7 @@ class apSharedInboxAction extends ManagedAction
|
|||||||
/**
|
/**
|
||||||
* Handle the Shared Inbox request
|
* Handle the Shared Inbox request
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function handle ()
|
protected function handle ()
|
||||||
|
@ -40,6 +40,8 @@ if (!isset ($data->object->content)) {
|
|||||||
}
|
}
|
||||||
if (!isset ($data->object->url)) {
|
if (!isset ($data->object->url)) {
|
||||||
ActivityPubReturn::error ("Object url was not specified.");
|
ActivityPubReturn::error ("Object url was not specified.");
|
||||||
|
} else if (!filter_var ($data->object->url, FILTER_VALIDATE_URL)) {
|
||||||
|
ActivityPubReturn::error ("Invalid Object Url.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = $data->object->content;
|
$content = $data->object->content;
|
||||||
|
@ -43,6 +43,7 @@ class Activitypub_attachment extends Managed_DataObject
|
|||||||
/**
|
/**
|
||||||
* Generates a pretty array from an Attachment object
|
* Generates a pretty array from an Attachment object
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Attachment $attachment
|
* @param Attachment $attachment
|
||||||
* @return pretty array to be used in a response
|
* @return pretty array to be used in a response
|
||||||
*/
|
*/
|
||||||
|
@ -43,6 +43,7 @@ class Activitypub_error extends Managed_DataObject
|
|||||||
/**
|
/**
|
||||||
* Generates a pretty error from a string
|
* Generates a pretty error from a string
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param string $m
|
* @param string $m
|
||||||
* @return pretty array to be used in a response
|
* @return pretty array to be used in a response
|
||||||
*/
|
*/
|
||||||
|
@ -44,6 +44,8 @@ class Activitypub_notice extends Managed_DataObject
|
|||||||
/**
|
/**
|
||||||
* Generates a pretty notice from a Notice object
|
* Generates a pretty notice from a Notice object
|
||||||
*
|
*
|
||||||
|
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Notice $notice
|
* @param Notice $notice
|
||||||
* @return pretty array to be used in a response
|
* @return pretty array to be used in a response
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once dirname (__DIR__) . DIRECTORY_SEPARATOR . "utils" . DIRECTORY_SEPARATOR . "explorer.php";
|
|
||||||
/**
|
/**
|
||||||
* GNU social - a federating social network
|
* GNU social - a federating social network
|
||||||
*
|
*
|
||||||
@ -49,6 +48,7 @@ class Activitypub_profile extends Profile
|
|||||||
/**
|
/**
|
||||||
* Return table definition for Schema setup and DB_DataObject usage.
|
* Return table definition for Schema setup and DB_DataObject usage.
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @return array array of column definitions
|
* @return array array of column definitions
|
||||||
*/
|
*/
|
||||||
static function schemaDef ()
|
static function schemaDef ()
|
||||||
@ -76,6 +76,7 @@ class Activitypub_profile extends Profile
|
|||||||
/**
|
/**
|
||||||
* Generates a pretty profile from a Profile object
|
* Generates a pretty profile from a Profile object
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Profile $profile
|
* @param Profile $profile
|
||||||
* @return pretty array to be used in a response
|
* @return pretty array to be used in a response
|
||||||
*/
|
*/
|
||||||
@ -118,6 +119,7 @@ class Activitypub_profile extends Profile
|
|||||||
/**
|
/**
|
||||||
* Insert the current objects variables into the database
|
* Insert the current objects variables into the database
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @access public
|
* @access public
|
||||||
* @throws ServerException
|
* @throws ServerException
|
||||||
*/
|
*/
|
||||||
@ -154,6 +156,8 @@ class Activitypub_profile extends Profile
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch the locally stored profile for this Activitypub_profile
|
* Fetch the locally stored profile for this Activitypub_profile
|
||||||
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @return Profile
|
* @return Profile
|
||||||
* @throws NoProfileException if it was not found
|
* @throws NoProfileException if it was not found
|
||||||
*/
|
*/
|
||||||
@ -169,6 +173,7 @@ class Activitypub_profile extends Profile
|
|||||||
/**
|
/**
|
||||||
* Generates an Activitypub_profile from a Profile
|
* Generates an Activitypub_profile from a Profile
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Profile $profile
|
* @param Profile $profile
|
||||||
* @return Activitypub_profile
|
* @return Activitypub_profile
|
||||||
* @throws Exception if no Activitypub_profile exists for given Profile
|
* @throws Exception if no Activitypub_profile exists for given Profile
|
||||||
@ -177,14 +182,14 @@ class Activitypub_profile extends Profile
|
|||||||
{
|
{
|
||||||
$profile_id = $profile->getID ();
|
$profile_id = $profile->getID ();
|
||||||
|
|
||||||
$aprofile = Activitypub_profile::getKV ('profile_id', $profile_id);
|
$aprofile = self::getKV ('profile_id', $profile_id);
|
||||||
if (!$aprofile instanceof Activitypub_profile) {
|
if (!$aprofile instanceof Activitypub_profile) {
|
||||||
// No Activitypub_profile for this profile_id,
|
// No Activitypub_profile for this profile_id,
|
||||||
if (!$profile->isLocal ()) {
|
if (!$profile->isLocal ()) {
|
||||||
// create one!
|
// create one!
|
||||||
$aprofile = self::create_from_local_profile ($profile);
|
$aprofile = self::create_from_local_profile ($profile);
|
||||||
} else {
|
} else {
|
||||||
throw new Exception ('No Activitypub_profile for Profile ID: '.$profile_id. ', this probably is a local profile.');
|
throw new Exception ('No Activitypub_profile for Profile ID: '.$profile_id. ', this is a local user.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,6 +205,7 @@ class Activitypub_profile extends Profile
|
|||||||
* One must be careful not to give a user profile to this function
|
* One must be careful not to give a user profile to this function
|
||||||
* as only remote users have ActivityPub_profiles on local instance
|
* as only remote users have ActivityPub_profiles on local instance
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Profile $profile
|
* @param Profile $profile
|
||||||
* @return Activitypub_profile
|
* @return Activitypub_profile
|
||||||
*/
|
*/
|
||||||
@ -227,6 +233,7 @@ class Activitypub_profile extends Profile
|
|||||||
/**
|
/**
|
||||||
* Returns sharedInbox if possible, inbox otherwise
|
* Returns sharedInbox if possible, inbox otherwise
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @return string Inbox URL
|
* @return string Inbox URL
|
||||||
*/
|
*/
|
||||||
public function get_inbox ()
|
public function get_inbox ()
|
||||||
@ -237,4 +244,122 @@ class Activitypub_profile extends Profile
|
|||||||
|
|
||||||
return $this->sharedInboxuri;
|
return $this->sharedInboxuri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for uri property
|
||||||
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
|
* @return string URI
|
||||||
|
*/
|
||||||
|
public function get_uri ()
|
||||||
|
{
|
||||||
|
return $this->uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures a valid Activitypub_profile when provided with a valid URI.
|
||||||
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
|
* @param string $url
|
||||||
|
* @return Activitypub_profile
|
||||||
|
* @throws Exception if it isn't possible to return an Activitypub_profile
|
||||||
|
*/
|
||||||
|
public static function get_from_uri ($url)
|
||||||
|
{
|
||||||
|
$explorer = new Activitypub_explorer ();
|
||||||
|
$profiles_found = $explorer->lookup ($url);
|
||||||
|
if (!empty ($profiles_found)) {
|
||||||
|
return self::from_profile ($profiles_found[0]);
|
||||||
|
} else {
|
||||||
|
throw new Exception ('No valid ActivityPub profile found for given URI');
|
||||||
|
}
|
||||||
|
// If it doesn't return a valid Activitypub_profile an exception will
|
||||||
|
// have been thrown before getting to this point.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up, and if necessary create, an Activitypub_profile for the remote
|
||||||
|
* entity with the given webfinger address.
|
||||||
|
* This should never return null -- you will either get an object or
|
||||||
|
* an exception will be thrown.
|
||||||
|
*
|
||||||
|
* @author GNU Social
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
|
* @param string $addr webfinger address
|
||||||
|
* @return Activitypub_profile
|
||||||
|
* @throws Exception on error conditions
|
||||||
|
*/
|
||||||
|
public static function ensure_web_finger ($addr)
|
||||||
|
{
|
||||||
|
// Normalize $addr, i.e. add 'acct:' if missing
|
||||||
|
$addr = Discovery::normalize ($addr);
|
||||||
|
|
||||||
|
// Try the cache
|
||||||
|
$uri = self::cacheGet (sprintf ('activitypub_profile:webfinger:%s', $addr));
|
||||||
|
|
||||||
|
if ($uri !== false) {
|
||||||
|
if (is_null ($uri)) {
|
||||||
|
// Negative cache entry
|
||||||
|
// TRANS: Exception.
|
||||||
|
throw new Exception (_m ('Not a valid webfinger address (via cache).'));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return self::get_from_uri ($uri);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
common_log (LOG_ERR, sprintf (__METHOD__ . ': Webfinger address cache inconsistent with database, did not find Activitypub_profile uri==%s', $uri));
|
||||||
|
self::cacheSet (sprintf ('activitypub_profile:webfinger:%s', $addr), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, try some discovery
|
||||||
|
|
||||||
|
$disco = new Discovery ();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$xrd = $disco->lookup ($addr);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// Save negative cache entry so we don't waste time looking it up again.
|
||||||
|
// @todo FIXME: Distinguish temporary failures?
|
||||||
|
self::cacheSet (sprintf ('activitypub_profile:webfinger:%s', $addr), null);
|
||||||
|
// TRANS: Exception.
|
||||||
|
throw new Exception (_m ('Not a valid webfinger address.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$hints = array_merge (array ('webfinger' => $addr),
|
||||||
|
DiscoveryHints::fromXRD ($xrd));
|
||||||
|
|
||||||
|
// If there's an Hcard, let's grab its info
|
||||||
|
if (array_key_exists ('hcard', $hints)) {
|
||||||
|
if (!array_key_exists ('profileurl', $hints) ||
|
||||||
|
$hints['hcard'] != $hints['profileurl']) {
|
||||||
|
$hcardHints = DiscoveryHints::fromHcardUrl ($hints['hcard']);
|
||||||
|
$hints = array_merge ($hcardHints, $hints);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we got a profile page, try that!
|
||||||
|
$profileUrl = null;
|
||||||
|
if (array_key_exists ('profileurl', $hints)) {
|
||||||
|
$profileUrl = $hints['profileurl'];
|
||||||
|
try {
|
||||||
|
common_log (LOG_INFO, "Discovery on acct:$addr with profile URL $profileUrl");
|
||||||
|
$aprofile = self::get_from_uri ($hints['profileurl']);
|
||||||
|
self::cacheSet (sprintf ('activitypub_profile:webfinger:%s', $addr), $aprofile->get_uri ());
|
||||||
|
return $aprofile;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
common_log (LOG_WARNING, "Failed creating profile from profile URL '$profileUrl': " . $e->getMessage ());
|
||||||
|
// keep looking
|
||||||
|
//
|
||||||
|
// @todo FIXME: This means an error discovering from profile page
|
||||||
|
// may give us a corrupt entry using the webfinger URI, which
|
||||||
|
// will obscure the correct page-keyed profile later on.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: try hcard
|
||||||
|
// XXX: try FOAF
|
||||||
|
|
||||||
|
// TRANS: Exception. %s is a webfinger address.
|
||||||
|
throw new Exception (sprintf (_m ('Could not find a valid profile for "%s".'), $addr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ class Activitypub_tag extends Managed_DataObject
|
|||||||
/**
|
/**
|
||||||
* Generates a pretty tag from a Tag object
|
* Generates a pretty tag from a Tag object
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Tag $tag
|
* @param Tag $tag
|
||||||
* @return pretty array to be used in a response
|
* @return pretty array to be used in a response
|
||||||
*/
|
*/
|
||||||
|
154
utils/discoveryhints.php
Normal file
154
utils/discoveryhints.php
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* GNU social - a federating social network
|
||||||
|
*
|
||||||
|
* Some utilities for generating hint data
|
||||||
|
*
|
||||||
|
* LICENCE: 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @category Plugin
|
||||||
|
* @package GNUsocial
|
||||||
|
* @author GNUsocial
|
||||||
|
* @copyright 2010 Free Software Foundation http://fsf.org
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link https://www.gnu.org/software/social/
|
||||||
|
*/
|
||||||
|
if (!defined ('GNUSOCIAL')) {
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
class DiscoveryHints {
|
||||||
|
static function fromXRD(XML_XRD $xrd)
|
||||||
|
{
|
||||||
|
$hints = array();
|
||||||
|
|
||||||
|
if (Event::handle('StartDiscoveryHintsFromXRD', array($xrd, &$hints))) {
|
||||||
|
foreach ($xrd->links as $link) {
|
||||||
|
switch ($link->rel) {
|
||||||
|
case WebFingerResource_Profile::PROFILEPAGE:
|
||||||
|
$hints['profileurl'] = $link->href;
|
||||||
|
break;
|
||||||
|
$hints['salmon'] = $link->href;
|
||||||
|
break;
|
||||||
|
case Discovery::UPDATESFROM:
|
||||||
|
if (empty($link->type) || $link->type == 'application/atom+xml') {
|
||||||
|
$hints['feedurl'] = $link->href;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Discovery::HCARD:
|
||||||
|
case Discovery::MF2_HCARD:
|
||||||
|
$hints['hcard'] = $link->href;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::handle('EndDiscoveryHintsFromXRD', array($xrd, &$hints));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $hints;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function fromHcardUrl($url)
|
||||||
|
{
|
||||||
|
$client = new HTTPClient();
|
||||||
|
$client->setHeader('Accept', 'text/html,application/xhtml+xml');
|
||||||
|
try {
|
||||||
|
$response = $client->get($url);
|
||||||
|
|
||||||
|
if (!$response->isOk()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (HTTP_Request2_Exception $e) {
|
||||||
|
// Any HTTPClient error that might've been thrown
|
||||||
|
common_log(LOG_ERR, __METHOD__ . ':'.$e->getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::hcardHints($response->getBody(),
|
||||||
|
$response->getEffectiveUrl());
|
||||||
|
}
|
||||||
|
|
||||||
|
static function hcardHints($body, $url)
|
||||||
|
{
|
||||||
|
$hcard = self::_hcard($body, $url);
|
||||||
|
|
||||||
|
if (empty($hcard)) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$hints = array();
|
||||||
|
|
||||||
|
// XXX: don't copy stuff into an array and then copy it again
|
||||||
|
|
||||||
|
if (array_key_exists('nickname', $hcard) && !empty($hcard['nickname'][0])) {
|
||||||
|
$hints['nickname'] = $hcard['nickname'][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('name', $hcard) && !empty($hcard['name'][0])) {
|
||||||
|
$hints['fullname'] = $hcard['name'][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('photo', $hcard) && count($hcard['photo'])) {
|
||||||
|
$hints['avatar'] = $hcard['photo'][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('note', $hcard) && !empty($hcard['note'][0])) {
|
||||||
|
$hints['bio'] = $hcard['note'][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('adr', $hcard) && !empty($hcard['adr'][0])) {
|
||||||
|
$hints['location'] = $hcard['adr'][0]['value'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('url', $hcard) && !empty($hcard['url'][0])) {
|
||||||
|
$hints['homepage'] = $hcard['url'][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $hints;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function _hcard($body, $url)
|
||||||
|
{
|
||||||
|
$mf2 = new Mf2\Parser($body, $url);
|
||||||
|
$mf2 = $mf2->parse();
|
||||||
|
|
||||||
|
if (empty($mf2['items'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$hcards = array();
|
||||||
|
|
||||||
|
foreach ($mf2['items'] as $item) {
|
||||||
|
if (!in_array('h-card', $item['type'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We found a match, return it immediately
|
||||||
|
if (isset($item['properties']['url']) && in_array($url, $item['properties']['url'])) {
|
||||||
|
return $item['properties'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let's keep all the hcards for later, to return one of them at least
|
||||||
|
$hcards[] = $item['properties'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// No match immediately for the url we expected, but there were h-cards found
|
||||||
|
if (count($hcards) > 0) {
|
||||||
|
return $hcards[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -49,6 +49,7 @@ class Activitypub_explorer
|
|||||||
* This function cleans the $this->discovered_actor_profiles array
|
* This function cleans the $this->discovered_actor_profiles array
|
||||||
* so that there is no erroneous data
|
* so that there is no erroneous data
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param string $url User's url
|
* @param string $url User's url
|
||||||
* @return array of Profile objects
|
* @return array of Profile objects
|
||||||
*/
|
*/
|
||||||
@ -64,6 +65,7 @@ class Activitypub_explorer
|
|||||||
* This is a recursive function that will accumulate the results on
|
* This is a recursive function that will accumulate the results on
|
||||||
* $discovered_actor_profiles array
|
* $discovered_actor_profiles array
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param string $url User's url
|
* @param string $url User's url
|
||||||
* @return array of Profile objects
|
* @return array of Profile objects
|
||||||
*/
|
*/
|
||||||
@ -83,6 +85,7 @@ class Activitypub_explorer
|
|||||||
* Get a local user profiles from its URL and joins it on
|
* Get a local user profiles from its URL and joins it on
|
||||||
* $this->discovered_actor_profiles
|
* $this->discovered_actor_profiles
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param string $url User's url
|
* @param string $url User's url
|
||||||
* @return boolean success state
|
* @return boolean success state
|
||||||
*/
|
*/
|
||||||
@ -116,6 +119,7 @@ class Activitypub_explorer
|
|||||||
* Get a remote user(s) profile(s) from its URL and joins it on
|
* Get a remote user(s) profile(s) from its URL and joins it on
|
||||||
* $this->discovered_actor_profiles
|
* $this->discovered_actor_profiles
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param string $url User's url
|
* @param string $url User's url
|
||||||
* @return boolean success state
|
* @return boolean success state
|
||||||
*/
|
*/
|
||||||
@ -152,6 +156,7 @@ class Activitypub_explorer
|
|||||||
/**
|
/**
|
||||||
* Save remote user profile in local instance
|
* Save remote user profile in local instance
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param array $res remote response
|
* @param array $res remote response
|
||||||
* @return Profile remote Profile object
|
* @return Profile remote Profile object
|
||||||
*/
|
*/
|
||||||
@ -174,6 +179,7 @@ class Activitypub_explorer
|
|||||||
* Validates a remote response in order to determine whether this
|
* Validates a remote response in order to determine whether this
|
||||||
* response is a valid profile or not
|
* response is a valid profile or not
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param array $res remote response
|
* @param array $res remote response
|
||||||
* @return boolean success state
|
* @return boolean success state
|
||||||
*/
|
*/
|
||||||
@ -192,12 +198,13 @@ class Activitypub_explorer
|
|||||||
* potential ActivityPub remote profiles, as so it is important to use
|
* potential ActivityPub remote profiles, as so it is important to use
|
||||||
* this hacky workaround (at least for now)
|
* this hacky workaround (at least for now)
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param string $v URL
|
* @param string $v URL
|
||||||
* @return boolean|Profile false if fails | Profile object if successful
|
* @return boolean|Profile false if fails | Profile object if successful
|
||||||
*/
|
*/
|
||||||
static function get_profile_by_url ($v)
|
public static function get_profile_by_url ($v)
|
||||||
{
|
{
|
||||||
$i = Managed_DataObject::getcached(Profile, "profileurl", $v);
|
$i = Managed_DataObject::getcached("Profile", "profileurl", $v);
|
||||||
if (empty ($i)) { // false = cache miss
|
if (empty ($i)) { // false = cache miss
|
||||||
$i = new Profile;
|
$i = new Profile;
|
||||||
$result = $i->get ("profileurl", $v);
|
$result = $i->get ("profileurl", $v);
|
||||||
@ -214,10 +221,11 @@ class Activitypub_explorer
|
|||||||
/**
|
/**
|
||||||
* Given a valid actor profile url returns its inboxes
|
* Given a valid actor profile url returns its inboxes
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param string $url of Actor profile
|
* @param string $url of Actor profile
|
||||||
* @return boolean|array false if fails | array with inbox and shared inbox if successful
|
* @return boolean|array false if fails | array with inbox and shared inbox if successful
|
||||||
*/
|
*/
|
||||||
static function get_actor_inboxes_uri ($url)
|
public static function get_actor_inboxes_uri ($url)
|
||||||
{
|
{
|
||||||
$client = new HTTPClient ();
|
$client = new HTTPClient ();
|
||||||
$headers = array();
|
$headers = array();
|
||||||
|
@ -51,6 +51,7 @@ class Activitypub_postman
|
|||||||
/**
|
/**
|
||||||
* Create a postman to deliver something to someone
|
* Create a postman to deliver something to someone
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Profile of sender
|
* @param Profile of sender
|
||||||
* @param Activitypub_profile $to array of destinataries
|
* @param Activitypub_profile $to array of destinataries
|
||||||
*/
|
*/
|
||||||
@ -66,6 +67,8 @@ class Activitypub_postman
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a follow notification to remote instance
|
* Send a follow notification to remote instance
|
||||||
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
*/
|
*/
|
||||||
public function follow ()
|
public function follow ()
|
||||||
{
|
{
|
||||||
@ -79,6 +82,8 @@ class Activitypub_postman
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a Undo Follow notification to remote instance
|
* Send a Undo Follow notification to remote instance
|
||||||
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
*/
|
*/
|
||||||
public function undo_follow ()
|
public function undo_follow ()
|
||||||
{
|
{
|
||||||
@ -97,6 +102,7 @@ class Activitypub_postman
|
|||||||
/**
|
/**
|
||||||
* Send a Like notification to remote instances holding the notice
|
* Send a Like notification to remote instances holding the notice
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Notice $notice
|
* @param Notice $notice
|
||||||
*/
|
*/
|
||||||
public function like ($notice)
|
public function like ($notice)
|
||||||
@ -114,6 +120,7 @@ class Activitypub_postman
|
|||||||
/**
|
/**
|
||||||
* Send a Undo Like notification to remote instances holding the notice
|
* Send a Undo Like notification to remote instances holding the notice
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Notice $notice
|
* @param Notice $notice
|
||||||
*/
|
*/
|
||||||
public function undo_like ($notice)
|
public function undo_like ($notice)
|
||||||
@ -135,6 +142,7 @@ class Activitypub_postman
|
|||||||
/**
|
/**
|
||||||
* Send a Announce notification to remote instances
|
* Send a Announce notification to remote instances
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Notice $notice
|
* @param Notice $notice
|
||||||
*/
|
*/
|
||||||
public function announce ($notice)
|
public function announce ($notice)
|
||||||
@ -156,6 +164,7 @@ class Activitypub_postman
|
|||||||
/**
|
/**
|
||||||
* Send a Create notification to remote instances
|
* Send a Create notification to remote instances
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Notice $notice
|
* @param Notice $notice
|
||||||
*/
|
*/
|
||||||
public function create ($notice)
|
public function create ($notice)
|
||||||
@ -183,6 +192,7 @@ class Activitypub_postman
|
|||||||
/**
|
/**
|
||||||
* Send a Delete notification to remote instances holding the notice
|
* Send a Delete notification to remote instances holding the notice
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Notice $notice
|
* @param Notice $notice
|
||||||
*/
|
*/
|
||||||
public function delete ($notice)
|
public function delete ($notice)
|
||||||
@ -201,6 +211,7 @@ class Activitypub_postman
|
|||||||
/**
|
/**
|
||||||
* Clean list of inboxes to deliver messages
|
* Clean list of inboxes to deliver messages
|
||||||
*
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @return array To Inbox URLs
|
* @return array To Inbox URLs
|
||||||
*/
|
*/
|
||||||
private function to_inbox ()
|
private function to_inbox ()
|
||||||
|
Reference in New Issue
Block a user