[ActivityPub] Routes

ActivityPubPlugin:
- Update routes to properly use URLMapper
- Minor updates
This commit is contained in:
brunoccast 2019-07-15 16:22:34 +01:00 committed by Diogo Cordeiro
parent 2ad4fa99ed
commit 735a0023cc
2 changed files with 24 additions and 200 deletions

View File

@ -26,13 +26,9 @@
defined('GNUSOCIAL') || die(); defined('GNUSOCIAL') || die();
// Ensure proper timezone
date_default_timezone_set('GMT');
// Import required files by the plugin // Import required files by the plugin
require_once __DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'httpsignature.php'; require_once __DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'httpsignature.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'discoveryhints.php'; require_once __DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'discoveryhints.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'AcceptHeader.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'explorer.php'; require_once __DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'explorer.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'postman.php'; require_once __DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'postman.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'inbox_handler.php'; require_once __DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'inbox_handler.php';
@ -135,29 +131,32 @@ class ActivityPubPlugin extends Plugin
*/ */
public function onRouterInitialized(URLMapper $m) public function onRouterInitialized(URLMapper $m)
{ {
if (ActivityPubURLMapperOverwrite::should()) { $acceptHeaders = [
ActivityPubURLMapperOverwrite::variable( 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' => 0,
$m, 'application/activity+json' => 1,
'user/:id', 'application/json' => 2,
['id' => '[0-9]+'], 'application/ld+json' => 3
'apActorProfile' ];
);
// Special route for webfinger purposes $m->connect('user/:id',
ActivityPubURLMapperOverwrite::variable( ['action' => 'apActorProfile'],
$m, ['id' => '[0-9]+'],
':nickname', $acceptHeaders);
['nickname' => Nickname::DISPLAY_FMT],
'apActorProfile'
);
}
// No .json here for convenience purposes on Notice grabber $m->connect(':nickname',
$m->connect( ['action' => 'apActorProfile'],
'note/:id', ['nickname' => Nickname::DISPLAY_FMT],
['action' => 'apNotice'], $acceptHeaders);
['id' => '[0-9]+']
); $m->connect(':nickname/',
['action' => 'apActorProfile'],
['nickname' => Nickname::DISPLAY_FMT],
$acceptHeaders);
$m->connect('notice/:id',
['action' => 'apNotice'],
['id' => '[0-9]+'],
$acceptHeaders);
$m->connect( $m->connect(
'user/:id/liked.json', 'user/:id/liked.json',
@ -956,62 +955,3 @@ class ActivityPubReturn
exit; exit;
} }
} }
/**
* Overwrites variables in URL-mapping
*/
class ActivityPubURLMapperOverwrite extends URLMapper
{
/**
* Overwrites a route.
*
* @author Hannes Mannerheim <h@nnesmannerhe.im>
* @param URLMapper $m
* @param string $path
* @param string $paramPatterns
* @param string $newaction
* @return void
* @throws Exception
*/
public static function variable($m, $path, $paramPatterns, $newaction)
{
$m->connect($path, array('action' => $newaction), $paramPatterns);
$regex = self::makeRegex($path, $paramPatterns);
foreach ($m->variables as $n => $v) {
if ($v[1] == $regex) {
$m->variables[$n][0]['action'] = $newaction;
}
}
}
/**
* Determines whether the route should or not be overwrited.
* If ACCEPT header isn't set false will be returned.
*
* @author Diogo Cordeiro <diogo@fc.up.pt>
* @return boolean true if it should, false otherwise
*/
public static function should()
{
// Do not operate without Accept Header
if (!isset($_SERVER['HTTP_ACCEPT'])) {
return false;
}
$mimes = [
'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' => 0,
'application/activity+json' => 1,
'application/json' => 2,
'application/ld+json' => 3
];
$acceptheader = new AcceptHeader($_SERVER['HTTP_ACCEPT']);
foreach ($acceptheader as $ah) {
if (isset($mimes[$ah['raw']])) {
return true;
}
}
return false;
}
}

View File

@ -1,116 +0,0 @@
<?php
/**
* Note : Code is released under the GNU LGPL
*
* Please do not change the header of this file
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*/
/**
* The AcceptHeader page will parse and sort the different
* allowed types for the content negociations
*
* @author Pierrick Charron <pierrick@webstart.fr>
*/
class AcceptHeader extends \ArrayObject
{
/**
* Constructor
*
* @param string $header Value of the Accept header
* @return void
*/
public function __construct($header)
{
$acceptedTypes = $this->_parse($header);
usort($acceptedTypes, [$this, '_compare']);
parent::__construct($acceptedTypes);
}
/**
* Parse the accept header and return an array containing
* all the informations about the Accepted types
*
* @param string $data Value of the Accept header
* @return array
*/
private function _parse($data)
{
$array = [];
$items = explode(',', $data);
foreach ($items as $item) {
$elems = explode(';', $item);
$acceptElement = [];
$mime = current($elems);
list($type, $subtype) = explode('/', $mime);
$acceptElement['type'] = trim($type);
$acceptElement['subtype'] = trim($subtype);
$acceptElement['raw'] = $mime;
$acceptElement['params'] = [];
while (next($elems)) {
list($name, $value) = explode('=', current($elems));
$acceptElement['params'][trim($name)] = trim($value);
}
$array[] = $acceptElement;
}
return $array;
}
/**
* Compare two Accepted types with their parameters to know
* if one media type should be used instead of an other
*
* @param array $a The first media type and its parameters
* @param array $b The second media type and its parameters
* @return int
*/
private function _compare($a, $b)
{
$a_q = isset($a['params']['q']) ? floatval($a['params']['q']) : 1.0;
$b_q = isset($b['params']['q']) ? floatval($b['params']['q']) : 1.0;
if ($a_q === $b_q) {
$a_count = count($a['params']);
$b_count = count($b['params']);
if ($a_count === $b_count) {
if ($r = $this->_compareSubType($a['subtype'], $b['subtype'])) {
return $r;
} else {
return $this->_compareSubType($a['type'], $b['type']);
}
} else {
return $a_count < $b_count;
}
} else {
return $a_q < $b_q;
}
}
/**
* Compare two subtypes
*
* @param string $a First subtype to compare
* @param string $b Second subtype to compare
* @return int
*/
private function _compareSubType($a, $b)
{
if ($a === '*' && $b !== '*') {
return 1;
} elseif ($b === '*' && $a !== '*') {
return -1;
} else {
return 0;
}
}
}