Inbox Reinvented
This commit is contained in:
parent
de432cda88
commit
43ebdfa727
@ -38,6 +38,7 @@ require_once __DIR__ . DIRECTORY_SEPARATOR . 'utils' . DIRECTORY_SEPARATOR . 'd
|
||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'utils' . DIRECTORY_SEPARATOR . 'AcceptHeader.php';
|
||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'utils' . DIRECTORY_SEPARATOR . 'explorer.php';
|
||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'utils' . DIRECTORY_SEPARATOR . 'postman.php';
|
||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'utils' . DIRECTORY_SEPARATOR . 'inbox_handler.php';
|
||||
|
||||
// So that this isn't hardcoded everywhere
|
||||
define('ACTIVITYPUB_BASE_ACTOR_URI', common_root_url().'index.php/user/');
|
||||
@ -122,40 +123,9 @@ class ActivityPubPlugin extends Plugin
|
||||
$headers[] = 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"';
|
||||
$headers[] = 'User-Agent: GNUSocialBot v0.1 - https://gnu.io/social';
|
||||
$response = $client->get($url, $headers);
|
||||
$res = json_decode($response->getBody(), true);
|
||||
$settings = [];
|
||||
try {
|
||||
Activitypub_notice::validate_remote_notice($res);
|
||||
} catch (Exception $e) {
|
||||
common_debug('ActivityPubPlugin Notice Grabber: Invalid potential remote notice while processing id: '.$url. '. He returned the following: '.json_encode($res, JSON_UNESCAPED_SLASHES));
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if (isset($res->inReplyTo)) {
|
||||
$settings['inReplyTo'] = $res->inReplyTo;
|
||||
}
|
||||
if (isset($res->latitude)) {
|
||||
$settings['latitude'] = $res->latitude;
|
||||
}
|
||||
if (isset($res->longitude)) {
|
||||
$settings['longitude'] = $res->longitude;
|
||||
}
|
||||
try {
|
||||
return Activitypub_notice::create_notice(
|
||||
ActivityPub_explorer::get_profile_from_url($res['attributedTo']),
|
||||
$res['id'],
|
||||
$res['url'],
|
||||
$res['content'],
|
||||
$res['cc'],
|
||||
$settings
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
common_debug('ActivityPubPlugin Notice Grabber: failed to find: '.$url.' online.');
|
||||
throw $e;
|
||||
}
|
||||
|
||||
// When all the above failed in its quest of grabbing the Notice
|
||||
throw new Exception('Notice not found.');
|
||||
$object = json_decode($response->getBody(), true);
|
||||
Activitypub_notice::validate_note($object);
|
||||
return Activitypub_notice::create_notice($object);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -210,13 +180,13 @@ class ActivityPubPlugin extends Plugin
|
||||
|
||||
$m->connect(
|
||||
'user/:id/inbox.json',
|
||||
['action' => 'apActorInbox'],
|
||||
['action' => 'apInbox'],
|
||||
['id' => '[0-9]+']
|
||||
);
|
||||
|
||||
$m->connect(
|
||||
'inbox.json',
|
||||
['action' => 'apSharedInbox']
|
||||
['action' => 'apInbox']
|
||||
);
|
||||
}
|
||||
|
||||
@ -941,7 +911,7 @@ class ActivityPubReturn
|
||||
* @param int32 $code Status Code
|
||||
* @return void
|
||||
*/
|
||||
public static function error($m, $code = 500)
|
||||
public static function error($m, $code = 400)
|
||||
{
|
||||
http_response_code($code);
|
||||
header('Content-Type: application/activity+json');
|
||||
|
@ -1,130 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* GNU social - a federating social network
|
||||
*
|
||||
* ActivityPubPlugin implementation for GNU Social
|
||||
*
|
||||
* 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 Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actor's Inbox
|
||||
*
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://www.gnu.org/software/social/
|
||||
*/
|
||||
class apActorInboxAction extends ManagedAction
|
||||
{
|
||||
protected $needLogin = false;
|
||||
protected $canPost = true;
|
||||
|
||||
/**
|
||||
* Handle the Actor Inbox request
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @return void
|
||||
*/
|
||||
protected function handle()
|
||||
{
|
||||
try {
|
||||
$profile = Profile::getByID($this->trimmed('id'));
|
||||
} catch (Exception $e) {
|
||||
ActivityPubReturn::error('Invalid Actor URI.', 404);
|
||||
}
|
||||
|
||||
if (!$profile->isLocal()) {
|
||||
ActivityPubReturn::error('This is not a local user.');
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
ActivityPubReturn::error('C2S not implemented just yet.');
|
||||
}
|
||||
|
||||
common_debug('ActivityPub Inbox: Received a POST request.');
|
||||
$data = file_get_contents('php://input');
|
||||
common_debug('ActivityPub Inbox: Request contents: '.$data);
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
// Validate data
|
||||
if (!(isset($data['type']))) {
|
||||
ActivityPubReturn::error('Type was not specified.');
|
||||
}
|
||||
if (!isset($data['actor'])) {
|
||||
ActivityPubReturn::error('Actor was not specified.');
|
||||
}
|
||||
if (!isset($data['object'])) {
|
||||
ActivityPubReturn::error('Object was not specified.');
|
||||
}
|
||||
|
||||
// Get valid Actor object
|
||||
try {
|
||||
$actor_profile = ActivityPub_explorer::get_profile_from_url($data['actor']);
|
||||
} catch (Exception $e) {
|
||||
ActivityPubReturn::error($e->getMessage(), 404);
|
||||
}
|
||||
|
||||
$cc = [$profile];
|
||||
|
||||
// Process request
|
||||
define('INBOX_HANDLERS', __DIR__ . DIRECTORY_SEPARATOR . 'inbox' . DIRECTORY_SEPARATOR);
|
||||
switch ($data['type']) {
|
||||
// Data available:
|
||||
// Profile $actor_profile Actor performing the action
|
||||
// string|object $data->object Object to be handled
|
||||
// Array|String $cc Destinataries
|
||||
// Profile $profile Local user to whom this action is directed
|
||||
case 'Create':
|
||||
$cc = array_merge ([$profile], $data['object']['cc']);
|
||||
require_once INBOX_HANDLERS . 'Create.php';
|
||||
break;
|
||||
case 'Follow':
|
||||
require_once INBOX_HANDLERS . 'Follow.php';
|
||||
break;
|
||||
case 'Like':
|
||||
require_once INBOX_HANDLERS . 'Like.php';
|
||||
break;
|
||||
case 'Announce':
|
||||
require_once INBOX_HANDLERS . 'Announce.php';
|
||||
break;
|
||||
case 'Undo':
|
||||
require_once INBOX_HANDLERS . 'Undo.php';
|
||||
break;
|
||||
case 'Delete':
|
||||
require_once INBOX_HANDLERS . 'Delete.php';
|
||||
break;
|
||||
case 'Accept':
|
||||
require_once INBOX_HANDLERS . 'Accept.php';
|
||||
break;
|
||||
case 'Reject':
|
||||
require_once INBOX_HANDLERS . 'Reject.php';
|
||||
break;
|
||||
default:
|
||||
ActivityPubReturn::error('Invalid type value.');
|
||||
}
|
||||
}
|
||||
}
|
@ -29,30 +29,42 @@ if (!defined('GNUSOCIAL')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Validate data
|
||||
if (!isset($data['object']['type'])) {
|
||||
ActivityPubReturn::error("Type was not specified.");
|
||||
}
|
||||
/**
|
||||
* Inbox Request Handler
|
||||
*
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://www.gnu.org/software/social/
|
||||
*/
|
||||
class apInboxAction extends ManagedAction
|
||||
{
|
||||
protected $needLogin = false;
|
||||
protected $canPost = true;
|
||||
|
||||
switch ($data['object']['type']) {
|
||||
case "Follow":
|
||||
// Validate data
|
||||
if (!isset($data['object']['object'])) {
|
||||
ActivityPubReturn::error("Object Actor URL was not specified.");
|
||||
/**
|
||||
* Handle the Inbox request
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @return void
|
||||
*/
|
||||
protected function handle()
|
||||
{
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
ActivityPubReturn::error('Only POST requests allowed.');
|
||||
}
|
||||
// Get valid Object profile
|
||||
|
||||
common_debug('ActivityPub Shared Inbox: Received a POST request.');
|
||||
$data = file_get_contents('php://input');
|
||||
common_debug('ActivityPub Shared Inbox: Request contents: '.$data);
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
try {
|
||||
$object_profile = new Activitypub_explorer;
|
||||
$object_profile = $object_profile->lookup($data['object']['object'])[0];
|
||||
new Activitypub_inbox_handler($data);
|
||||
ActivityPubReturn::answer();
|
||||
} catch (Exception $e) {
|
||||
ActivityPubReturn::error("Invalid Object Actor URL.", 404);
|
||||
ActivityPubReturn::error($e->getMessage());
|
||||
}
|
||||
|
||||
$pending_list = new Activitypub_pending_follow_requests($actor_profile->getID(), $object_profile->getID());
|
||||
$pending_list->remove();
|
||||
ActivityPubReturn::answer(); // You are now being followed by this person.
|
||||
break;
|
||||
default:
|
||||
ActivityPubReturn::error("Invalid object type.");
|
||||
break;
|
||||
}
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* GNU social - a federating social network
|
||||
*
|
||||
* ActivityPubPlugin implementation for GNU Social
|
||||
*
|
||||
* 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 Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared Inbox Handler
|
||||
*
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://www.gnu.org/software/social/
|
||||
*/
|
||||
class apSharedInboxAction extends ManagedAction
|
||||
{
|
||||
protected $needLogin = false;
|
||||
protected $canPost = true;
|
||||
|
||||
/**
|
||||
* Handle the Shared Inbox request
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @return void
|
||||
*/
|
||||
protected function handle()
|
||||
{
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
ActivityPubReturn::error('Only POST requests allowed.');
|
||||
}
|
||||
|
||||
common_debug('ActivityPub Shared Inbox: Received a POST request.');
|
||||
$data = file_get_contents('php://input');
|
||||
common_debug('ActivityPub Shared Inbox: Request contents: '.$data);
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
// Validate data
|
||||
if (!isset($data['type'])) {
|
||||
ActivityPubReturn::error('Type was not specified.');
|
||||
}
|
||||
if (!isset($data['actor'])) {
|
||||
ActivityPubReturn::error('Actor was not specified.');
|
||||
}
|
||||
if (!isset($data['object'])) {
|
||||
ActivityPubReturn::error('Object was not specified.');
|
||||
}
|
||||
|
||||
// Get valid Actor object
|
||||
try {
|
||||
$actor_profile = ActivityPub_explorer::get_profile_from_url($data['actor']);
|
||||
} catch (Exception $e) {
|
||||
ActivityPubReturn::error($e->getMessage(), 404);
|
||||
}
|
||||
|
||||
$cc = [];
|
||||
|
||||
// Process request
|
||||
define('INBOX_HANDLERS', __DIR__ . DIRECTORY_SEPARATOR . 'inbox' . DIRECTORY_SEPARATOR);
|
||||
switch ($data['type']) {
|
||||
// Data available:
|
||||
// Profile $actor_profile Actor performing the action
|
||||
// string|object $data->object Object to be handled
|
||||
// Array|String $cc Destinataries
|
||||
// string|object $data->object
|
||||
case 'Create':
|
||||
$cc = $data['object']['cc'];
|
||||
$res = $data['object'];
|
||||
require_once INBOX_HANDLERS . 'Create.php';
|
||||
break;
|
||||
case 'Follow':
|
||||
require_once INBOX_HANDLERS . 'Follow.php';
|
||||
break;
|
||||
case 'Like':
|
||||
require_once INBOX_HANDLERS . 'Like.php';
|
||||
break;
|
||||
case 'Announce':
|
||||
require_once INBOX_HANDLERS . 'Announce.php';
|
||||
break;
|
||||
case 'Undo':
|
||||
require_once INBOX_HANDLERS . 'Undo.php';
|
||||
break;
|
||||
case 'Delete':
|
||||
require_once INBOX_HANDLERS . 'Delete.php';
|
||||
break;
|
||||
case 'Accept':
|
||||
require_once INBOX_HANDLERS . 'Accept.php';
|
||||
break;
|
||||
case 'Reject':
|
||||
require_once INBOX_HANDLERS . 'Reject.php';
|
||||
break;
|
||||
default:
|
||||
ActivityPubReturn::error('Invalid type value.');
|
||||
}
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* GNU social - a federating social network
|
||||
*
|
||||
* ActivityPubPlugin implementation for GNU Social
|
||||
*
|
||||
* 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 Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 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);
|
||||
}
|
||||
|
||||
try {
|
||||
try {
|
||||
$object_notice = ActivityPubPlugin::grab_notice_from_url($data['object']);
|
||||
} catch (Exception $e) {
|
||||
ActivityPubReturn::error('Invalid Object specified.');
|
||||
}
|
||||
$object_notice->repeat($actor_profile, 'ActivityPub');
|
||||
ActivityPubReturn::answer();
|
||||
} catch (Exception $e) {
|
||||
ActivityPubReturn::error($e->getMessage(), 403);
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* GNU social - a federating social network
|
||||
*
|
||||
* ActivityPubPlugin implementation for GNU Social
|
||||
*
|
||||
* 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 Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 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);
|
||||
}
|
||||
|
||||
$valid_object_types = ['Note'];
|
||||
|
||||
try {
|
||||
Activitypub_notice::validate_remote_notice($res);
|
||||
} catch (Exception $e) {
|
||||
common_debug('ActivityPub Inbox Create Note: Invalid note: '.$e->getMessage());
|
||||
ActivityPubReturn::error($e->getMessage());
|
||||
}
|
||||
|
||||
$settings = [];
|
||||
|
||||
if (isset($res['inReplyTo'])) {
|
||||
$settings['inReplyTo'] = $res['inReplyTo'];
|
||||
}
|
||||
if (isset($res['latitude'])) {
|
||||
$settings['latitude'] = $res['latitude'];
|
||||
}
|
||||
if (isset($res['longitude'])) {
|
||||
$settings['longitude'] = $res['longitude'];
|
||||
}
|
||||
if (isset($res['attachment'])) {
|
||||
$settings['attachment'] = $res['attachment'];
|
||||
}
|
||||
|
||||
try {
|
||||
Activitypub_notice::create_notice(
|
||||
$actor_profile,
|
||||
$res['id'],
|
||||
$res['url'],
|
||||
$res['content'],
|
||||
$cc,
|
||||
$settings
|
||||
);
|
||||
ActivityPubReturn::answer();
|
||||
} catch (AlreadyFulfilledException $e) {
|
||||
// Notice URI already exists
|
||||
common_debug('ActivityPub Inbox Create Note: Note already exists: '.$e->getMessage());
|
||||
ActivityPubReturn::error('Note already exists.', 202);
|
||||
} catch (Exception $e) {
|
||||
common_debug('ActivityPub Inbox Create Note: Failed Create Note: '.$e->getMessage());
|
||||
ActivityPubReturn::error($e->getMessage());
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* GNU social - a federating social network
|
||||
*
|
||||
* ActivityPubPlugin implementation for GNU Social
|
||||
*
|
||||
* 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 Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 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);
|
||||
}
|
||||
|
||||
try {
|
||||
$notice = ActivityPubPlugin::grab_notice_from_url($data['object']);
|
||||
$notice->deleteAs($actor_profile);
|
||||
ActivityPubReturn::answer();
|
||||
} catch (Exception $e) {
|
||||
ActivityPubReturn::error($e->getMessage(), 403);
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* GNU social - a federating social network
|
||||
*
|
||||
* ActivityPubPlugin implementation for GNU Social
|
||||
*
|
||||
* 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 Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 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);
|
||||
}
|
||||
|
||||
// Validate Object
|
||||
if (!filter_var($data['object'], FILTER_VALIDATE_URL)) {
|
||||
ActivityPubReturn::error('Invalid Object Actor URL.');
|
||||
}
|
||||
|
||||
// Ensure valid Object profile
|
||||
try {
|
||||
if (!isset($profile)) {
|
||||
$object_profile = new Activitypub_explorer;
|
||||
$object_profile = $object_profile->lookup($data['object'])[0];
|
||||
} else {
|
||||
$object_profile = $profile;
|
||||
unset($profile);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
ActivityPubReturn::error('Invalid Object Actor URL.', 404);
|
||||
}
|
||||
|
||||
// Get Actor's Aprofile
|
||||
$actor_aprofile = Activitypub_profile::from_profile($actor_profile);
|
||||
|
||||
if (!Subscription::exists($actor_profile, $object_profile)) {
|
||||
Subscription::start($actor_profile, $object_profile);
|
||||
common_debug('ActivityPubPlugin: Accepted Follow request from '.$data['actor'].' to '.$data['object']);
|
||||
|
||||
// Notify remote instance that we have accepted their request
|
||||
common_debug('ActivityPubPlugin: Notifying remote instance that we have accepted their Follow request request from '.$data['actor'].' to '.$data['object']);
|
||||
$postman = new Activitypub_postman($actor_profile, [$actor_aprofile]);
|
||||
$postman->follow();
|
||||
ActivityPubReturn::answer();
|
||||
} else {
|
||||
common_debug('ActivityPubPlugin: Received a repeated Follow request from '.$data['actor'].' to '.$data['object']);
|
||||
ActivityPubReturn::error('Already following.', 202);
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* GNU social - a federating social network
|
||||
*
|
||||
* ActivityPubPlugin implementation for GNU Social
|
||||
*
|
||||
* 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 Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 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);
|
||||
}
|
||||
|
||||
try {
|
||||
try {
|
||||
$object_notice = ActivityPubPlugin::grab_notice_from_url($data['object']);
|
||||
} catch (Exception $e) {
|
||||
ActivityPubReturn::error('Invalid Object specified.');
|
||||
}
|
||||
Fave::addNew($actor_profile, $object_notice);
|
||||
ActivityPubReturn::answer();
|
||||
} catch (Exception $e) {
|
||||
ActivityPubReturn::error($e->getMessage(), 403);
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* GNU social - a federating social network
|
||||
*
|
||||
* ActivityPubPlugin implementation for GNU Social
|
||||
*
|
||||
* 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 Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 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);
|
||||
}
|
||||
|
||||
// This is a dummy file as there is nothing to do if we fall in this case
|
@ -1,80 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* GNU social - a federating social network
|
||||
*
|
||||
* ActivityPubPlugin implementation for GNU Social
|
||||
*
|
||||
* 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 Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 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);
|
||||
}
|
||||
|
||||
// Validate data
|
||||
if (!isset($data['type'])) {
|
||||
ActivityPubReturn::error('Type was not specified.');
|
||||
}
|
||||
|
||||
switch ($data['object']['type']) {
|
||||
case 'Like':
|
||||
try {
|
||||
// Validate data
|
||||
if (!isset($data['object']['object'])) {
|
||||
ActivityPubReturn::error('Notice URI was not specified.');
|
||||
}
|
||||
Fave::removeEntry($actor_profile, ActivityPubPlugin::grab_notice_from_url($data['object']['object']));
|
||||
// Notice disfavorited successfully.
|
||||
ActivityPubReturn::answer();
|
||||
} catch (Exception $e) {
|
||||
ActivityPubReturn::error($e->getMessage(), 403);
|
||||
}
|
||||
break;
|
||||
case 'Follow':
|
||||
// Validate data
|
||||
if (!isset($data['object']['object'])) {
|
||||
ActivityPubReturn::error('Object Actor URL was not specified.');
|
||||
}
|
||||
// Get valid Object profile
|
||||
try {
|
||||
$object_profile = new Activitypub_explorer;
|
||||
$object_profile = $object_profile->lookup($data['object']['object'])[0];
|
||||
} catch (Exception $e) {
|
||||
ActivityPubReturn::error('Invalid Object Actor URL.', 404);
|
||||
}
|
||||
|
||||
if (Subscription::exists($actor_profile, $object_profile)) {
|
||||
Subscription::cancel($actor_profile, $object_profile);
|
||||
// You are no longer following this person.
|
||||
ActivityPubReturn::answer();
|
||||
} else {
|
||||
// 409: You are not following this person already.
|
||||
ActivityPubReturn::answer();
|
||||
}
|
||||
break;
|
||||
case 'Announce':
|
||||
// This is a dummy entry point as GNU Social doesn't allow Undo Announce
|
||||
ActivityPubReturn::answer();
|
||||
// no break
|
||||
default:
|
||||
ActivityPubReturn::error('Invalid object type.');
|
||||
break;
|
||||
}
|
@ -61,4 +61,32 @@ class Activitypub_accept extends Managed_DataObject
|
||||
];
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if a given object is acceptable for an Accept Activity.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param Array $object
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function validate_object($object)
|
||||
{
|
||||
if (!is_array($object)) {
|
||||
throw new Exception('Invalid Object Format for Accept Activity.');
|
||||
}
|
||||
if (!isset($object['type'])) {
|
||||
throw new Exception('Object type was not specified for Accept Activity.');
|
||||
}
|
||||
switch ($object['type']) {
|
||||
case 'Follow':
|
||||
// Validate data
|
||||
if (!filter_var($object['object'], FILTER_VALIDATE_URL)) {
|
||||
throw new Exception("Object is not a valid Object URI for Activity.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Exception('This is not a supported Object Type for Accept Activity.');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -49,11 +49,15 @@ class Activitypub_announce extends Managed_DataObject
|
||||
*/
|
||||
public static function announce_to_array($actor, $object)
|
||||
{
|
||||
$res = array("@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"type" => "Announce",
|
||||
"actor" => $actor,
|
||||
"object" => $object
|
||||
);
|
||||
$res = [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
"type" => "Announce",
|
||||
"actor" => $actor,
|
||||
"object" => $object
|
||||
];
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
@ -50,18 +50,22 @@ class Activitypub_attachment extends Managed_DataObject
|
||||
public static function attachment_to_array($attachment)
|
||||
{
|
||||
$res = [
|
||||
'type' => 'Document',
|
||||
'mediaType' => $attachment->mimetype,
|
||||
'url' => $attachment->getUrl(),
|
||||
'size' => intval($attachment->size), // $attachment->getSize ()
|
||||
'name' => $attachment->getTitle(),
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'type' => 'Document',
|
||||
'mediaType' => $attachment->mimetype,
|
||||
'url' => $attachment->getUrl(),
|
||||
'size' => intval($attachment->size), // $attachment->getSize ()
|
||||
'name' => $attachment->getTitle(),
|
||||
];
|
||||
|
||||
// Image
|
||||
if (substr($res["mediaType"], 0, 5) == "image") {
|
||||
$res["meta"]= [
|
||||
'width' => $attachment->width,
|
||||
'height' => $attachment->height
|
||||
'width' => $attachment->width,
|
||||
'height' => $attachment->height
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,10 @@ class Activitypub_create extends Managed_DataObject
|
||||
public static function create_to_array($id, $actor, $object)
|
||||
{
|
||||
$res = [
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'id' => $id.'/create',
|
||||
'type' => 'Create',
|
||||
'to' => $object['to'],
|
||||
@ -61,4 +64,29 @@ class Activitypub_create extends Managed_DataObject
|
||||
];
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if a given object is acceptable for a Create Activity.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param Array $object
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function validate_object($object)
|
||||
{
|
||||
if (!is_array($object)) {
|
||||
throw new Exception('Invalid Object Format for Create Activity.');
|
||||
}
|
||||
if (!isset($object['type'])) {
|
||||
throw new Exception('Object type was not specified for Create Activity.');
|
||||
}
|
||||
switch ($object['type']) {
|
||||
case 'Note':
|
||||
// Validate data
|
||||
Activitypub_notice::validate_note($object);
|
||||
break;
|
||||
default:
|
||||
throw new Exception('This is not a supported Object Type for Create Activity.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,10 @@ class Activitypub_delete extends Managed_DataObject
|
||||
public static function delete_to_array($actor, $object)
|
||||
{
|
||||
$res = [
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'id' => $object.'/delete',
|
||||
'type' => 'Delete',
|
||||
'actor' => $actor,
|
||||
|
@ -50,8 +50,8 @@ class Activitypub_error extends Managed_DataObject
|
||||
public static function error_message_to_array($m)
|
||||
{
|
||||
$res = [
|
||||
'error'=> $m
|
||||
];
|
||||
'error'=> $m
|
||||
];
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
@ -62,4 +62,34 @@ class Activitypub_follow extends Managed_DataObject
|
||||
];
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a Follow Activity received by our inbox.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param Profile $actor_profile Remote Actor
|
||||
* @param string $object Local Actor
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function follow($actor_profile, $object)
|
||||
{
|
||||
// Get Actor's Aprofile
|
||||
$actor_aprofile = Activitypub_profile::from_profile($actor_profile);
|
||||
|
||||
// Get Object profile
|
||||
$object_profile = new Activitypub_explorer;
|
||||
$object_profile = $object_profile->lookup($object)[0];
|
||||
|
||||
if (!Subscription::exists($actor_profile, $object_profile)) {
|
||||
Subscription::start($actor_profile, $object_profile);
|
||||
common_debug('ActivityPubPlugin: Accepted Follow request from '.ActivityPubPlugin::actor_uri($actor_profile).' to '.$object);
|
||||
} else {
|
||||
common_debug('ActivityPubPlugin: Received a repeated Follow request from '.ActivityPubPlugin::actor_uri($actor_profile).' to '.$object);
|
||||
}
|
||||
|
||||
// Notify remote instance that we have accepted their request
|
||||
common_debug('ActivityPubPlugin: Notifying remote instance that we have accepted their Follow request request from '.ActivityPubPlugin::actor_uri($actor_profile).' to '.$object);
|
||||
$postman = new Activitypub_postman($actor_profile, [$actor_aprofile]);
|
||||
$postman->accept_follow();
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,10 @@ class Activitypub_mention_tag extends Managed_DataObject
|
||||
public static function mention_tag_to_array_from_values($href, $name)
|
||||
{
|
||||
$res = [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
"type" => "Mention",
|
||||
"href" => $href,
|
||||
"name" => $name
|
||||
|
@ -72,12 +72,15 @@ class Activitypub_notice extends Managed_DataObject
|
||||
$to[]= 'https://www.w3.org/ns/activitystreams#Public';
|
||||
|
||||
$item = [
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'id' => $notice->getUrl(),
|
||||
'type' => 'Note',
|
||||
'published' => str_replace(' ', 'T', $notice->getCreated()).'Z',
|
||||
'url' => $notice->getUrl(),
|
||||
'atributtedTo' => ActivityPubPlugin::actor_uri($profile),
|
||||
'attributedTo' => ActivityPubPlugin::actor_uri($profile),
|
||||
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
|
||||
'cc' => $cc,
|
||||
'atomUri' => $notice->getUrl(),
|
||||
@ -107,21 +110,42 @@ class Activitypub_notice extends Managed_DataObject
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Notice via ActivityPub data.
|
||||
* Create a Notice via ActivityPub Note Object.
|
||||
* Returns created Notice.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param Profile $actor_profile
|
||||
* @param int32 $id
|
||||
* @param string $url
|
||||
* @param string $content
|
||||
* @param array|string $cc
|
||||
* @param array $settings possible keys: ['inReplyTo', 'latitude', 'longitude', 'attachment']
|
||||
* @param Array $object
|
||||
* @param Profile|null $actor_profile
|
||||
* @return Notice
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function create_notice($actor_profile, $id, $url, $content, $cc, $settings)
|
||||
public static function create_notice($object, $actor_profile = null)
|
||||
{
|
||||
$id = $object['id']; // int32
|
||||
$url = $object['url']; // string
|
||||
$content = $object['content']; // string
|
||||
$cc = $object['cc']; // array|string
|
||||
|
||||
// possible keys: ['inReplyTo', 'latitude', 'longitude', 'attachment']
|
||||
$settings = [];
|
||||
if (isset($object['inReplyTo'])) {
|
||||
$settings['inReplyTo'] = $object['inReplyTo'];
|
||||
}
|
||||
if (isset($object['latitude'])) {
|
||||
$settings['latitude'] = $object['latitude'];
|
||||
}
|
||||
if (isset($object['longitude'])) {
|
||||
$settings['longitude'] = $object['longitude'];
|
||||
}
|
||||
if (isset($object['attachment'])) {
|
||||
$settings['attachment'] = $object['attachment'];
|
||||
}
|
||||
|
||||
// Ensure Actor Profile
|
||||
if (is_null($actor_profile)) {
|
||||
$actor_profile = ActivityPub_explorer::get_profile_from_url($object['actor']);
|
||||
}
|
||||
|
||||
$act = new Activity();
|
||||
$act->verb = ActivityVerb::POST;
|
||||
$act->time = time();
|
||||
@ -150,6 +174,7 @@ class Activitypub_notice extends Managed_DataObject
|
||||
|
||||
$imagefile = new ImageFile(null, $temp_filename);
|
||||
$filename = hash(File::FILEHASH_ALG, $imgData).image_type_to_extension($imagefile->type);
|
||||
|
||||
unset($imgData); // No need to carry this in memory.
|
||||
rename($temp_filename, File::path($filename));
|
||||
common_debug('ActivityPub Create Notice: Moved image from: '.$temp_filename.' to '.$filename);
|
||||
@ -158,11 +183,9 @@ class Activitypub_notice extends Managed_DataObject
|
||||
} catch (Exception $e) {
|
||||
common_debug('ActivityPub Create Notice: Something went wrong while processing the image from: '.$attach_url.' details: '.$e->getMessage());
|
||||
unlink($temp_filename);
|
||||
$content .= ($content==='' ? '' : ' ') . $attach_url;
|
||||
}
|
||||
} else {
|
||||
$content .= ($content==='' ? '' : ' ') . $attach_url;
|
||||
}
|
||||
$content .= ($content==='' ? '' : ' ') . '<br><a href="'.$attach_url.'">Remote Attachment Source</a>';
|
||||
}
|
||||
|
||||
// Is this a reply?
|
||||
@ -181,12 +204,13 @@ class Activitypub_notice extends Managed_DataObject
|
||||
$discovery = new Activitypub_explorer;
|
||||
|
||||
// Generate Cc objects
|
||||
$cc_profiles = [];
|
||||
if (is_array($cc)) {
|
||||
// Remove duplicates from Cc actors set
|
||||
array_unique($cc);
|
||||
foreach ($cc as $cc_url) {
|
||||
try {
|
||||
$cc = array_merge($cc, $discovery->lookup($cc_url));
|
||||
$cc_profiles = array_merge($cc_profiles, $discovery->lookup($cc_url));
|
||||
} catch (Exception $e) {
|
||||
// Invalid actor found, just let it go. // TODO: Fallback to OStatus
|
||||
}
|
||||
@ -195,7 +219,7 @@ class Activitypub_notice extends Managed_DataObject
|
||||
// No need to do anything else at this point, let's just break out the if
|
||||
} else {
|
||||
try {
|
||||
$cc = array_merge($cc, $discovery->lookup($cc));
|
||||
$cc_profiles = $discovery->lookup($cc);
|
||||
} catch (Exception $e) {
|
||||
// Invalid actor found, just let it go. // TODO: Fallback to OStatus
|
||||
}
|
||||
@ -203,8 +227,8 @@ class Activitypub_notice extends Managed_DataObject
|
||||
|
||||
unset($discovery);
|
||||
|
||||
foreach ($cc as $tp) {
|
||||
$act->context->attention[ActivityPubPlugin::actor_uri($tp)] = 'http://activitystrea.ms/schema/1.0/person';
|
||||
foreach ($cc_profiles as $cp) {
|
||||
$act->context->attention[ActivityPubPlugin::actor_uri($cp)] = 'http://activitystrea.ms/schema/1.0/person';
|
||||
}
|
||||
|
||||
// Add location if that is set
|
||||
@ -224,56 +248,51 @@ class Activitypub_notice extends Managed_DataObject
|
||||
// Finally add the activity object to our activity
|
||||
$act->objects[] = $actobj;
|
||||
|
||||
try {
|
||||
$note = Notice::saveActivity($act, $actor_profile, $options);
|
||||
if (ActivityPubPlugin::$store_images_from_remote_notes_attachments && isset($mediaFile)) {
|
||||
$mediaFile->attachToNotice($note);
|
||||
}
|
||||
return $note;
|
||||
} catch (Exception $e) {
|
||||
throw $e;
|
||||
$note = Notice::saveActivity($act, $actor_profile, $options);
|
||||
if (ActivityPubPlugin::$store_images_from_remote_notes_attachments && isset($mediaFile)) {
|
||||
$mediaFile->attachToNotice($note);
|
||||
}
|
||||
return $note;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a remote notice.
|
||||
* Validates a note.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param Array $data
|
||||
* @return boolean true in case of success
|
||||
* @param Array $object
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function validate_remote_notice($data)
|
||||
public static function validate_note($object)
|
||||
{
|
||||
/*if (!isset($data['attributedTo'])) {
|
||||
if (!isset($object['attributedTo'])) {
|
||||
common_debug('ActivityPub Notice Validator: Rejected because attributedTo was not specified.');
|
||||
throw new Exception('No attributedTo specified.');
|
||||
}
|
||||
if (!isset($data['id'])) {
|
||||
if (!isset($object['id'])) {
|
||||
common_debug('ActivityPub Notice Validator: Rejected because Object ID was not specified.');
|
||||
throw new Exception('Object ID not specified.');
|
||||
} elseif (!filter_var($data['id'], FILTER_VALIDATE_URL)) {
|
||||
} elseif (!filter_var($object['id'], FILTER_VALIDATE_URL)) {
|
||||
common_debug('ActivityPub Notice Validator: Rejected because Object ID is invalid.');
|
||||
throw new Exception('Invalid Object ID.');
|
||||
}
|
||||
if (!isset($data['type']) || $data['type'] !== 'Note') {
|
||||
if (!isset($object['type']) || $object['type'] !== 'Note') {
|
||||
common_debug('ActivityPub Notice Validator: Rejected because of Type.');
|
||||
throw new Exception('Invalid Object type.');
|
||||
}
|
||||
if (!isset($data['content'])) {
|
||||
if (!isset($object['content'])) {
|
||||
common_debug('ActivityPub Notice Validator: Rejected because Content was not specified.');
|
||||
throw new Exception('Object content was not specified.');
|
||||
}
|
||||
if (!isset($data['url'])) {
|
||||
if (!isset($object['url'])) {
|
||||
throw new Exception('Object URL was not specified.');
|
||||
} elseif (!filter_var($data['url'], FILTER_VALIDATE_URL)) {
|
||||
} elseif (!filter_var($object['url'], FILTER_VALIDATE_URL)) {
|
||||
common_debug('ActivityPub Notice Validator: Rejected because Object URL is invalid.');
|
||||
throw new Exception('Invalid Object URL.');
|
||||
}
|
||||
if (!isset($data['cc'])) {
|
||||
if (!isset($object['cc'])) {
|
||||
common_debug('ActivityPub Notice Validator: Rejected because Object CC was not specified.');
|
||||
throw new Exception('Object CC was not specified.');
|
||||
}*/
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ class Activitypub_profile extends Managed_DataObject
|
||||
'following' => common_local_url("apActorFollowing", array("id" => $id)),
|
||||
'followers' => common_local_url("apActorFollowers", array("id" => $id)),
|
||||
'liked' => common_local_url("apActorLiked", array("id" => $id)),
|
||||
'inbox' => common_local_url("apActorInbox", array("id" => $id)),
|
||||
'inbox' => common_local_url("apInbox", array("id" => $id)),
|
||||
'preferredUsername' => $profile->getNickname(),
|
||||
'name' => $profile->getBestName(),
|
||||
'summary' => ($desc = $profile->getDescription()) == null ? "" : $desc,
|
||||
@ -128,7 +128,7 @@ class Activitypub_profile extends Managed_DataObject
|
||||
];
|
||||
|
||||
if ($profile->isLocal()) {
|
||||
$res['endpoints']['sharedInbox'] = common_local_url('apSharedInbox');
|
||||
$res['endpoints']['sharedInbox'] = common_local_url('apInbox');
|
||||
} else {
|
||||
$aprofile = new Activitypub_profile();
|
||||
$aprofile = $aprofile->from_profile($profile);
|
||||
|
@ -49,10 +49,14 @@ class Activitypub_reject extends Managed_DataObject
|
||||
*/
|
||||
public static function reject_to_array($object)
|
||||
{
|
||||
$res = array("@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"type" => "Reject",
|
||||
"object" => $object
|
||||
);
|
||||
$res = [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
"type" => "Reject",
|
||||
"object" => $object
|
||||
];
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
@ -50,16 +50,13 @@ class Activitypub_tag extends Managed_DataObject
|
||||
public static function tag_to_array($tag)
|
||||
{
|
||||
$res = [
|
||||
'@context' => [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
[
|
||||
"@language" => "en"
|
||||
]
|
||||
],
|
||||
'name' => $tag,
|
||||
'url' => common_local_url('tag', array('tag' => $tag))
|
||||
];
|
||||
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'name' => $tag,
|
||||
'url' => common_local_url('tag', ['tag' => $tag])
|
||||
];
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
@ -61,4 +61,33 @@ class Activitypub_undo extends Managed_DataObject
|
||||
];
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if a given object is acceptable for a Undo Activity.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param Array $object
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function validate_object($object)
|
||||
{
|
||||
if (!is_array($object)) {
|
||||
throw new Exception('Invalid Object Format for Undo Activity.');
|
||||
}
|
||||
if (!isset($object['type'])) {
|
||||
throw new Exception('Object type was not specified for Undo Activity.');
|
||||
}
|
||||
switch ($object['type']) {
|
||||
case 'Follow':
|
||||
case 'Like':
|
||||
// Validate data
|
||||
if (!filter_var($object['object'], FILTER_VALIDATE_URL)) {
|
||||
throw new Exception('Object is not a valid Object URI for Activity.');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Exception('This is not a supported Object Type for Undo Activity.');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
102
utils/Activitypub_activityverb2.php
Normal file
102
utils/Activitypub_activityverb2.php
Normal file
@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/**
|
||||
* GNU social - a federating social network
|
||||
*
|
||||
* ActivityPubPlugin implementation for GNU Social
|
||||
*
|
||||
* 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 Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility class to hold a bunch of constant defining default verb types
|
||||
*
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://www.gnu.org/software/social/
|
||||
*/
|
||||
class Activitypub_activityverb2 extends Managed_DataObject
|
||||
{
|
||||
const FULL_LIST =
|
||||
[
|
||||
'Accept' => 'https://www.w3.org/ns/activitystreams#Accept',
|
||||
'TentativeAccept' => 'https://www.w3.org/ns/activitystreams#TentativeAccept',
|
||||
'Add' => 'https://www.w3.org/ns/activitystreams#Add',
|
||||
'Arrive' => 'https://www.w3.org/ns/activitystreams#Arrive',
|
||||
'Create' => 'https://www.w3.org/ns/activitystreams#Create',
|
||||
'Delete' => 'https://www.w3.org/ns/activitystreams#Delete',
|
||||
'Follow' => 'https://www.w3.org/ns/activitystreams#Follow',
|
||||
'Ignore' => 'https://www.w3.org/ns/activitystreams#Ignore',
|
||||
'Join' => 'https://www.w3.org/ns/activitystreams#Join',
|
||||
'Leave' => 'https://www.w3.org/ns/activitystreams#Leave',
|
||||
'Like' => 'https://www.w3.org/ns/activitystreams#Like',
|
||||
'Offer' => 'https://www.w3.org/ns/activitystreams#Offer',
|
||||
'Invite' => 'https://www.w3.org/ns/activitystreams#Invite',
|
||||
'Reject' => 'https://www.w3.org/ns/activitystreams#Reject',
|
||||
'TentativeReject' => 'https://www.w3.org/ns/activitystreams#TentativeReject',
|
||||
'Remove' => 'https://www.w3.org/ns/activitystreams#Remove',
|
||||
'Undo' => 'https://www.w3.org/ns/activitystreams#Undo',
|
||||
'Update' => 'https://www.w3.org/ns/activitystreams#Update',
|
||||
'View' => 'https://www.w3.org/ns/activitystreams#View',
|
||||
'Listen' => 'https://www.w3.org/ns/activitystreams#Listen',
|
||||
'Read' => 'https://www.w3.org/ns/activitystreams#Read',
|
||||
'Move' => 'https://www.w3.org/ns/activitystreams#Move',
|
||||
'Travel' => 'https://www.w3.org/ns/activitystreams#Travel',
|
||||
'Announce' => 'https://www.w3.org/ns/activitystreams#Announce',
|
||||
'Block' => 'https://www.w3.org/ns/activitystreams#Block',
|
||||
'Flag' => 'https://www.w3.org/ns/activitystreams#Flag',
|
||||
'Dislike' => 'https://www.w3.org/ns/activitystreams#Dislike',
|
||||
'Question' => 'https://www.w3.org/ns/activitystreams#Question'
|
||||
];
|
||||
|
||||
const KNOWN =
|
||||
[
|
||||
'Accept',
|
||||
'Create',
|
||||
'Delete',
|
||||
'Follow',
|
||||
'Like',
|
||||
'Undo',
|
||||
'Announce'
|
||||
];
|
||||
|
||||
/**
|
||||
* Converts canonical into verb.
|
||||
*
|
||||
* @author GNU Social
|
||||
* @param string $verb
|
||||
* @return string
|
||||
*/
|
||||
public static function canonical($verb)
|
||||
{
|
||||
$ns = 'https://www.w3.org/ns/activitystreams#';
|
||||
if (substr($verb, 0, mb_strlen($ns)) == $ns) {
|
||||
return substr($verb, mb_strlen($ns));
|
||||
} else {
|
||||
return $verb;
|
||||
}
|
||||
}
|
||||
}
|
@ -32,9 +32,9 @@ class DiscoveryHints
|
||||
{
|
||||
public static function fromXRD(XML_XRD $xrd)
|
||||
{
|
||||
$hints = array();
|
||||
$hints = [];
|
||||
|
||||
if (Event::handle('StartDiscoveryHintsFromXRD', array($xrd, &$hints))) {
|
||||
if (Event::handle('StartDiscoveryHintsFromXRD', [$xrd, &$hints])) {
|
||||
foreach ($xrd->links as $link) {
|
||||
switch ($link->rel) {
|
||||
case WebFingerResource_Profile::PROFILEPAGE:
|
||||
@ -55,7 +55,7 @@ class DiscoveryHints
|
||||
break;
|
||||
}
|
||||
}
|
||||
Event::handle('EndDiscoveryHintsFromXRD', array($xrd, &$hints));
|
||||
Event::handle('EndDiscoveryHintsFromXRD', [$xrd, &$hints]);
|
||||
}
|
||||
|
||||
return $hints;
|
||||
@ -88,10 +88,10 @@ class DiscoveryHints
|
||||
$hcard = self::_hcard($body, $url);
|
||||
|
||||
if (empty($hcard)) {
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
|
||||
$hints = array();
|
||||
$hints = [];
|
||||
|
||||
// XXX: don't copy stuff into an array and then copy it again
|
||||
|
||||
@ -131,7 +131,7 @@ class DiscoveryHints
|
||||
return null;
|
||||
}
|
||||
|
||||
$hcards = array();
|
||||
$hcards = [];
|
||||
|
||||
foreach ($mf2['items'] as $item) {
|
||||
if (!in_array('h-card', $item['type'])) {
|
||||
|
296
utils/inbox_handler.php
Normal file
296
utils/inbox_handler.php
Normal file
@ -0,0 +1,296 @@
|
||||
<?php
|
||||
/**
|
||||
* GNU social - a federating social network
|
||||
*
|
||||
* ActivityPubPlugin implementation for GNU Social
|
||||
*
|
||||
* 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 Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* ActivityPub Inbox Handler
|
||||
*
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://www.gnu.org/software/social/
|
||||
*/
|
||||
class Activitypub_inbox_handler
|
||||
{
|
||||
private $activity;
|
||||
private $actor;
|
||||
private $object;
|
||||
|
||||
/**
|
||||
* Create a Inbox Handler to receive something from someone.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param Array $activity Activity we are receiving
|
||||
*/
|
||||
public function __construct($activity)
|
||||
{
|
||||
$this->activity = $activity;
|
||||
$this->object = $activity['object'];
|
||||
|
||||
// Validate Activity
|
||||
$this->validate_activity();
|
||||
|
||||
// Get Actor's Profile
|
||||
$this->actor = ActivityPub_explorer::get_profile_from_url($this->activity['actor']);
|
||||
|
||||
// Handle the Activity
|
||||
$this->process();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates if a given Activity is valid. Throws exception if not.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.upt.pt>
|
||||
* @throws Exception
|
||||
*/
|
||||
private function validate_activity()
|
||||
{
|
||||
// Activity validation
|
||||
// Validate data
|
||||
if (!(isset($this->activity['type']))) {
|
||||
throw new Exception('Activity Validation Failed: Type was not specified.');
|
||||
}
|
||||
if (!isset($this->activity['actor'])) {
|
||||
throw new Exception('Activity Validation Failed: Actor was not specified.');
|
||||
}
|
||||
if (!isset($this->activity['object'])) {
|
||||
throw new Exception('Activity Validation Failed: Object was not specified.');
|
||||
}
|
||||
|
||||
// Object validation
|
||||
switch ($this->activity['type']) {
|
||||
case 'Accept':
|
||||
Activitypub_accept::validate_object($this->object);
|
||||
break;
|
||||
case 'Create':
|
||||
Activitypub_create::validate_object($this->object);
|
||||
break;
|
||||
case 'Delete':
|
||||
case 'Follow':
|
||||
case 'Like':
|
||||
case 'Announce':
|
||||
if (!filter_var($this->object, FILTER_VALIDATE_URL)) {
|
||||
throw new Exception("Object is not a valid Object URI for Activity.");
|
||||
}
|
||||
break;
|
||||
case 'Undo':
|
||||
Activitypub_undo::validate_object($this->object);
|
||||
break;
|
||||
default:
|
||||
throw new Exception('Unknown Activity Type.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the Activity to proper handler in order to be processed.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.upt.pt>
|
||||
*/
|
||||
private function process()
|
||||
{
|
||||
switch ($this->activity['type']) {
|
||||
case 'Accept':
|
||||
$this->handle_accept($this->actor, $this->object);
|
||||
break;
|
||||
case 'Create':
|
||||
$this->handle_create($this->actor, $this->object);
|
||||
break;
|
||||
case 'Delete':
|
||||
$this->handle_delete($this->actor, $this->object);
|
||||
break;
|
||||
case 'Follow':
|
||||
$this->handle_follow($this->actor, $this->object);
|
||||
break;
|
||||
case 'Like':
|
||||
$this->handle_like($this->actor, $this->object);
|
||||
break;
|
||||
case 'Undo':
|
||||
$this->handle_undo($this->actor, $this->object);
|
||||
break;
|
||||
case 'Announce':
|
||||
$this->handle_announce($this->actor, $this->object);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an Accept Activity received by our inbox.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.upt.pt>
|
||||
* @param Profile $actor Actor
|
||||
* @param Array $object Activity
|
||||
*/
|
||||
private function handle_accept($actor, $object)
|
||||
{
|
||||
switch ($object['type']) {
|
||||
case 'Follow':
|
||||
$this->handle_accept_follow($actor, $object);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an Accept Follow Activity received by our inbox.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.upt.pt>
|
||||
* @param Profile $actor Actor
|
||||
* @param Array $object Activity
|
||||
*/
|
||||
private function handle_accept_follow($actor, $object)
|
||||
{
|
||||
// Get valid Object profile
|
||||
$object_profile = new Activitypub_explorer;
|
||||
$object_profile = $object_profile->lookup($object['object'])[0];
|
||||
|
||||
$pending_list = new Activitypub_pending_follow_requests($actor->getID(), $object_profile->getID());
|
||||
$pending_list->remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a Create Activity received by our inbox.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.upt.pt>
|
||||
* @param Profile $actor Actor
|
||||
* @param Array $object Activity
|
||||
*/
|
||||
private function handle_create($actor, $object)
|
||||
{
|
||||
switch ($object['type']) {
|
||||
case 'Note':
|
||||
Activitypub_notice::create_notice($object, $actor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a Delete Activity received by our inbox.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.upt.pt>
|
||||
* @param Profile $actor Actor
|
||||
* @param Array $object Activity
|
||||
*/
|
||||
private function handle_delete($actor, $object)
|
||||
{
|
||||
$notice = ActivityPubPlugin::grab_notice_from_url($object['object']);
|
||||
$notice->deleteAs($actor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a Follow Activity received by our inbox.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.upt.pt>
|
||||
* @param Profile $actor Actor
|
||||
* @param Array $object Activity
|
||||
*/
|
||||
private function handle_follow($actor, $object)
|
||||
{
|
||||
Activitypub_follow::follow($actor, $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a Like Activity received by our inbox.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.upt.pt>
|
||||
* @param Profile $actor Actor
|
||||
* @param Array $object Activity
|
||||
*/
|
||||
private function handle_like($actor, $object)
|
||||
{
|
||||
$notice = ActivityPubPlugin::grab_notice_from_url($object);
|
||||
Fave::addNew($actor, $notice);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a Undo Activity received by our inbox.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.upt.pt>
|
||||
* @param Profile $actor Actor
|
||||
* @param Array $object Activity
|
||||
*/
|
||||
private function handle_undo($actor, $object)
|
||||
{
|
||||
switch ($object['type']) {
|
||||
case 'Follow':
|
||||
$this->handle_undo_follow($actor, $object['object']);
|
||||
break;
|
||||
case 'Like':
|
||||
$this->handle_undo_like($actor, $object['object']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a Undo Like Activity received by our inbox.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.upt.pt>
|
||||
* @param Profile $actor Actor
|
||||
* @param Array $object Activity
|
||||
*/
|
||||
private function handle_undo_like($actor, $object)
|
||||
{
|
||||
$notice = ActivityPubPlugin::grab_notice_from_url($object);
|
||||
Fave::removeEntry($actor, $notice);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a Undo Follow Activity received by our inbox.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.upt.pt>
|
||||
* @param Profile $actor Actor
|
||||
* @param Array $object Activity
|
||||
*/
|
||||
private function handle_undo_follow($actor, $object)
|
||||
{
|
||||
// Get Object profile
|
||||
$object_profile = new Activitypub_explorer;
|
||||
$object_profile = $object_profile->lookup($object)[0];
|
||||
|
||||
if (Subscription::exists($actor, $object_profile)) {
|
||||
Subscription::cancel($actor, $object_profile);
|
||||
// You are no longer following this person.
|
||||
} else {
|
||||
// 409: You are not following this person already.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a Announce Activity received by our inbox.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.upt.pt>
|
||||
* @param Profile $actor Actor
|
||||
* @param Array $object Activity
|
||||
*/
|
||||
private function handle_announce($actor, $object)
|
||||
{
|
||||
$object_notice = ActivityPubPlugin::grab_notice_from_url($object);
|
||||
$object_notice->repeat($actor, 'ActivityPub');
|
||||
}
|
||||
}
|
@ -135,11 +135,39 @@ class Activitypub_postman
|
||||
public function undo_follow()
|
||||
{
|
||||
$data = Activitypub_undo::undo_to_array(
|
||||
Activitypub_follow::follow_to_array(
|
||||
ActivityPubPlugin::actor_uri($this->actor),
|
||||
$this->to[0]->getUrl()
|
||||
)
|
||||
);
|
||||
Activitypub_follow::follow_to_array(
|
||||
ActivityPubPlugin::actor_uri($this->actor),
|
||||
$this->to[0]->getUrl()
|
||||
)
|
||||
);
|
||||
$res = $this->send(json_encode($data, JSON_UNESCAPED_SLASHES), $this->to[0]->get_inbox());
|
||||
$res_body = json_decode($res->getBody()->getContents());
|
||||
|
||||
if ($res->getStatusCode() == 200 || $res->getStatusCode() == 202 || $res->getStatusCode() == 409) {
|
||||
$pending_list = new Activitypub_pending_follow_requests($this->actor->getID(), $this->to[0]->getID());
|
||||
$pending_list->remove();
|
||||
return true;
|
||||
}
|
||||
if (isset($res_body[0]->error)) {
|
||||
throw new Exception($res_body[0]->error);
|
||||
}
|
||||
throw new Exception("An unknown error occurred.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a Accept Follow notification to remote instance
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
*/
|
||||
public function accept_follow()
|
||||
{
|
||||
$data = Activitypub_accept::accept_to_array(
|
||||
Activitypub_follow::follow_to_array(
|
||||
$this->to[0]->getUrl(),
|
||||
ActivityPubPlugin::actor_uri($this->actor)
|
||||
|
||||
)
|
||||
);
|
||||
$res = $this->send(json_encode($data, JSON_UNESCAPED_SLASHES), $this->to[0]->get_inbox());
|
||||
$res_body = json_decode($res->getBody()->getContents());
|
||||
|
||||
@ -278,7 +306,7 @@ class Activitypub_postman
|
||||
foreach ($this->to as $to_profile) {
|
||||
$i = $to_profile->get_inbox();
|
||||
// Prevent delivering to self
|
||||
if ($i == [common_local_url('apSharedInbox')]) {
|
||||
if ($i == [common_local_url('apInbox')]) {
|
||||
continue;
|
||||
}
|
||||
$to_inboxes[] = $i;
|
||||
|
Reference in New Issue
Block a user