3 * @copyright Copyright (C) 2010-2022, the Friendica project
5 * @license GNU AGPL version 3 or any later version
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 namespace Friendica\Module\Debug;
24 use Friendica\BaseModule;
25 use Friendica\Content\Text;
26 use Friendica\Core\Logger;
27 use Friendica\Core\Renderer;
29 use Friendica\Model\Item;
30 use Friendica\Model\Tag;
31 use Friendica\Protocol\ActivityPub;
32 use Friendica\Util\JsonLD;
33 use Friendica\Util\XML;
35 class ActivityPubConversion extends BaseModule
37 protected function content(array $request = []): string
39 function visible_whitespace($s)
41 return '<pre>' . htmlspecialchars($s) . '</pre>';
45 if (!empty($_REQUEST['source'])) {
47 $source = json_decode($_REQUEST['source'], true);
53 throw new \Exception('Failed to decode source JSON');
56 $formatted = json_encode($source, JSON_PRETTY_PRINT);
58 'title' => DI::l10n()->t('Formatted'),
59 'content' => visible_whitespace(trim(var_export($formatted, true), "'")),
62 'title' => DI::l10n()->t('Source'),
63 'content' => visible_whitespace(var_export($source, true))
65 $activity = JsonLD::compact($source);
67 throw new \Exception('Failed to compact JSON');
70 'title' => DI::l10n()->t('Activity'),
71 'content' => visible_whitespace(var_export($activity, true))
74 $type = JsonLD::fetchElement($activity, '@type');
77 throw new \Exception('Empty type');
80 if (!JsonLD::fetchElement($activity, 'as:object', '@id')) {
81 throw new \Exception('Empty object');
84 if (!JsonLD::fetchElement($activity, 'as:actor', '@id')) {
85 throw new \Exception('Empty actor');
88 // Don't trust the source if "actor" differs from "attributedTo". The content could be forged.
89 if ($trust_source && ($type == 'as:Create') && is_array($activity['as:object'])) {
90 $actor = JsonLD::fetchElement($activity, 'as:actor', '@id');
91 $attributed_to = JsonLD::fetchElement($activity['as:object'], 'as:attributedTo', '@id');
92 $trust_source = ($actor == $attributed_to);
94 throw new \Exception('Not trusting actor: ' . $actor . '. It differs from attributedTo: ' . $attributed_to);
98 // $trust_source is called by reference and is set to true if the content was retrieved successfully
99 $object_data = ActivityPub\Receiver::prepareObjectData($activity, $uid, $push, $trust_source);
100 if (empty($object_data)) {
101 throw new \Exception('No object data found');
104 if (!$trust_source) {
105 throw new \Exception('No trust for activity type "' . $type . '", so we quit now.');
108 if (!empty($body) && empty($object_data['raw'])) {
109 $object_data['raw'] = $body;
112 // Internal flag for thread completion. See Processor.php
113 if (!empty($activity['thread-completion'])) {
114 $object_data['thread-completion'] = $activity['thread-completion'];
117 if (!empty($activity['completion-mode'])) {
118 $object_data['completion-mode'] = $activity['completion-mode'];
122 'title' => DI::l10n()->t('Object data'),
123 'content' => visible_whitespace(var_export($object_data, true))
126 $item = ActivityPub\Processor::createItem($object_data);
129 'title' => DI::l10n()->t('Result Item'),
130 'content' => visible_whitespace(var_export($item, true))
132 } catch (\Throwable $e) {
134 'title' => DI::l10n()->t('Error'),
135 'content' => $e->getMessage(),
140 $tpl = Renderer::getMarkupTemplate('debug/activitypubconversion.tpl');
141 $o = Renderer::replaceMacros($tpl, [
142 '$title' => DI::l10n()->t('ActivityPub Conversion'),
143 '$source' => ['source', DI::l10n()->t('Source activity'), $_REQUEST['source'] ?? '', ''],
144 '$results' => $results,
145 '$submit' => DI::l10n()->t('Submit'),