* - Remove
* - Undo Block
* - Undo Accept (Problem: This could invert a contact accept or an event accept)
- *
- * General:
- * - Possibly using the LD-JSON parser
*/
class Receiver
{
$trust_source = false;
}
- self::processActivity($activity, $ldactivity, $body, $uid, $trust_source);
+ self::processActivity($ldactivity, $body, $uid, $trust_source);
}
/**
- *
+ * Fetches the object type for a given object id
+ *
+ * @param array $activity
+ * @param string $object_id Object ID of the the provided object
+ *
+ * @return string with object type
+ */
+ private static function fetchObjectType($activity, $object_id)
+ {
+
+ $object_type = JsonLD::fetchElement($activity['as:object'], '@type');
+ if (!empty($object_type)) {
+ return $object_type;
+ }
+
+ if (Item::exists(['uri' => $object_id, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT]])) {
+ // We just assume "note" since it doesn't make a difference for the further processing
+ return 'as:Note';
+ }
+
+ $profile = APContact::getByURL($object_id);
+ if (!empty($profile['type'])) {
+ return 'as:' . $profile['type'];
+ }
+
+ $data = ActivityPub::fetchContent($object_id);
+ if (!empty($data)) {
+ $object = JsonLD::compact($data);
+ $type = JsonLD::fetchElement($object, '@type');
+ if (!empty($type)) {
+ return $type;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Prepare the object array
*
* @param array $activity
* @param integer $uid User ID
* @param $trust_source
*
- * @return
+ * @return array with object data
*/
- private static function prepareObjectData($activity, $ldactivity, $uid, &$trust_source)
+ private static function prepareObjectData($activity, $uid, &$trust_source)
{
- $actor = JsonLD::fetchElement($ldactivity, 'as:actor');
+ $actor = JsonLD::fetchElement($activity, 'as:actor');
if (empty($actor)) {
logger('Empty actor', LOGGER_DEBUG);
return [];
}
- $type = JsonLD::fetchElement($ldactivity, '@type');
+ $type = JsonLD::fetchElement($activity, '@type');
// Fetch all receivers from to, cc, bto and bcc
- $receivers = self::getReceivers($ldactivity, $actor);
+ $receivers = self::getReceivers($activity, $actor);
// When it is a delivery to a personal inbox we add that user to the receivers
if (!empty($uid)) {
logger('Receivers: ' . json_encode($receivers), LOGGER_DEBUG);
- $object_id = JsonLD::fetchElement($ldactivity, 'as:object');
+ $object_id = JsonLD::fetchElement($activity, 'as:object');
if (empty($object_id)) {
logger('No object found', LOGGER_DEBUG);
return [];
}
+ $object_type = self::fetchObjectType($activity, $object_id);
+
// Fetch the content only on activities where this matters
if (in_array($type, ['as:Create', 'as:Announce'])) {
- $object_data = self::fetchObject($object_id, $activity['object'], $ldactivity['as:object'], $trust_source);
+ if ($type == 'as:Announce') {
+ $trust_source = false;
+ }
+ $object_data = self::fetchObject($object_id, $activity['as:object'], $trust_source);
if (empty($object_data)) {
logger("Object data couldn't be processed", LOGGER_DEBUG);
return [];
} elseif (in_array($type, ['as:Like', 'as:Dislike'])) {
// Create a mostly empty array out of the activity data (instead of the object).
// This way we later don't have to check for the existence of ech individual array element.
- $object_data = self::processObject($ldactivity);
+ $object_data = self::processObject($activity);
$object_data['name'] = $type;
- $object_data['author'] = JsonLD::fetchElement($ldactivity, 'as:actor');
- $object_data['object'] = $object_id;
+ $object_data['author'] = JsonLD::fetchElement($activity, 'as:actor');
+ $object_data['object_id'] = $object_id;
$object_data['object_type'] = ''; // Since we don't fetch the object, we don't know the type
} else {
$object_data = [];
- $object_data['id'] = JsonLD::fetchElement($ldactivity, '@id');
- $object_data['object'] = $activity['object'];
- $object_data['object_type'] = JsonLD::fetchElement($ldactivity, 'as:object', '@type');
+ $object_data['id'] = JsonLD::fetchElement($activity, '@id');
+ $object_data['object_id'] = JsonLD::fetchElement($activity, 'as:object');
+ $object_data['object_actor'] = JsonLD::fetchElement($activity['as:object'], 'as:actor');
+ $object_data['object_object'] = JsonLD::fetchElement($activity['as:object'], 'as:object');
+ $object_data['object_type'] = JsonLD::fetchElement($activity['as:object'], '@type');
}
$object_data = self::addActivityFields($object_data, $activity);
- $object_data['type'] = $activity['type'];
- $object_data['owner'] = $actor;
+ if (empty($object_data['object_type'])) {
+ $object_data['object_type'] = $object_type;
+ }
+
+ $object_data['type'] = $type;
+ $object_data['actor'] = $actor;
$object_data['receiver'] = array_merge(defaults($object_data, 'receiver', []), $receivers);
logger('Processing ' . $object_data['type'] . ' ' . $object_data['object_type'] . ' ' . $object_data['id'], LOGGER_DEBUG);
}
/**
- *
+ * Processes the activity object
*
- * @param array $activity
- * @param $body
- * @param integer $uid User ID
- * @param $trust_source
+ * @param array $activity Array with activity data
+ * @param string $body
+ * @param integer $uid User ID
+ * @param boolean $trust_source Do we trust the source?
*/
- public static function processActivity($activity, $ldactivity = '', $body = '', $uid = null, $trust_source = false)
+ public static function processActivity($activity, $body = '', $uid = null, $trust_source = false)
{
- if (empty($ldactivity)) {
- $ldactivity = JsonLD::compact($activity);
- }
-
- $type = JsonLD::fetchElement($ldactivity, '@type');
+ $type = JsonLD::fetchElement($activity, '@type');
if (!$type) {
logger('Empty type', LOGGER_DEBUG);
return;
}
- if (!JsonLD::fetchElement($ldactivity, 'as:object')) {
+ if (!JsonLD::fetchElement($activity, 'as:object')) {
logger('Empty object', LOGGER_DEBUG);
return;
}
- if (!JsonLD::fetchElement($ldactivity, 'as:actor')) {
+ if (!JsonLD::fetchElement($activity, 'as:actor')) {
logger('Empty actor', LOGGER_DEBUG);
return;
}
// $trust_source is called by reference and is set to true if the content was retrieved successfully
- $object_data = self::prepareObjectData($activity, $ldactivity, $uid, $trust_source);
+ $object_data = self::prepareObjectData($activity, $uid, $trust_source);
if (empty($object_data)) {
logger('No object data found', LOGGER_DEBUG);
return;
return;
}
+ // Internal flag for thread completion. See Processor.php
+ if (!empty($activity['thread-completion'])) {
+ $object_data['thread-completion'] = $activity['thread-completion'];
+ }
+
switch ($type) {
case 'as:Create':
case 'as:Announce':
private static function addActivityFields($object_data, $activity)
{
if (!empty($activity['published']) && empty($object_data['published'])) {
- $object_data['published'] = $activity['published'];
+ $object_data['published'] = JsonLD::fetchElement($activity, 'published', '@value');
}
if (!empty($activity['updated']) && empty($object_data['updated'])) {
- $object_data['updated'] = $activity['updated'];
+ $object_data['updated'] = JsonLD::fetchElement($activity, 'updated', '@value');
}
if (!empty($activity['diaspora:guid']) && empty($object_data['diaspora:guid'])) {
- $object_data['diaspora:guid'] = $activity['diaspora:guid'];
+ $object_data['diaspora:guid'] = JsonLD::fetchElement($activity, 'diaspora:guid');
}
if (!empty($activity['inReplyTo']) && empty($object_data['parent-uri'])) {
- $object_data['parent-uri'] = JsonLD::fetchElement($activity, 'inReplyTo', 'id');
+ $object_data['parent-uri'] = JsonLD::fetchElement($activity, 'inReplyTo');
}
if (!empty($activity['instrument'])) {
}
/**
- *
+ * Fetches the object data from external ressources if needed
*
- * @param $object_id
- * @param $object
- * @param $trust_source
+ * @param string $object_id Object ID of the the provided object
+ * @param array $object The provided object array
+ * @param boolean $trust_source Do we trust the provided object?
*
- * @return array with object data
+ * @return array with trusted and valid object data
*/
- private static function fetchObject($object_id, $object = [], $ldobject = [], $trust_source = false)
+ private static function fetchObject($object_id, $object = [], $trust_source = false)
{
- if (!$trust_source || is_string($object)) {
+ // By fetching the type we check if the object is complete.
+ $type = JsonLD::fetchElement($object, '@type');
+
+ if (!$trust_source || empty($type)) {
$data = ActivityPub::fetchContent($object_id);
- if (empty($data)) {
- logger('Empty content for ' . $object_id . ', check if content is available locally.', LOGGER_DEBUG);
- $data = $object_id;
- } else {
- $ldobject = JsonLD::compact($data);
+ if (!empty($data)) {
+ $object = JsonLD::compact($data);
logger('Fetched content for ' . $object_id, LOGGER_DEBUG);
+ } else {
+ logger('Empty content for ' . $object_id . ', check if content is available locally.', LOGGER_DEBUG);
+
+ $item = Item::selectFirst([], ['uri' => $object_id]);
+ if (!DBA::isResult($item)) {
+ logger('Object with url ' . $object_id . ' was not found locally.', LOGGER_DEBUG);
+ return false;
+ }
+ logger('Using already stored item for url ' . $object_id, LOGGER_DEBUG);
+ $data = ActivityPub\Transmitter::createNote($item);
+ $object = JsonLD::compact($data);
}
} else {
logger('Using original object for url ' . $object_id, LOGGER_DEBUG);
- $data = $object;
}
- if (is_string($data)) {
- $item = Item::selectFirst([], ['uri' => $data]);
- if (!DBA::isResult($item)) {
- logger('Object with url ' . $data . ' was not found locally.', LOGGER_DEBUG);
- return false;
- }
- logger('Using already stored item for url ' . $object_id, LOGGER_DEBUG);
- $data = ActivityPub\Transmitter::createNote($item);
- $ldobject = JsonLD::compact($data);
- }
+ $type = JsonLD::fetchElement($object, '@type');
- if (empty($data['type'])) {
+ if (empty($type)) {
logger('Empty type', LOGGER_DEBUG);
return false;
}
- if (in_array($data['type'], ActivityPub::CONTENT_TYPES)) {
- return self::processObject($ldobject);
+ if (in_array($type, self::CONTENT_TYPES)) {
+ return self::processObject($object);
}
- if ($data['type'] == 'Announce') {
- if (empty($data['object'])) {
+ if ($type == 'as:Announce') {
+ $object_id = JsonLD::fetchElement($object, 'object');
+ if (empty($object_id)) {
return false;
}
- return self::fetchObject($data['object']);
+ return self::fetchObject($object_id);
}
- logger('Unhandled object type: ' . $data['type'], LOGGER_DEBUG);
+ logger('Unhandled object type: ' . $type, LOGGER_DEBUG);
}
/**
private static function processTags($tags)
{
$taglist = [];
+
+ if (empty($tags)) {
+ return [];
+ }
+
foreach ($tags as $tag) {
+ if (empty($tag)) {
+ continue;
+ }
+
$taglist[] = ['type' => str_replace('as:', '', JsonLD::fetchElement($tag, '@type')),
'href' => JsonLD::fetchElement($tag, 'as:href'),
'name' => JsonLD::fetchElement($tag, 'as:name')];
private static function processAttachments($attachments)
{
$attachlist = [];
+
+ if (empty($attachments)) {
+ return [];
+ }
+
foreach ($attachments as $attachment) {
+ if (empty($attachment)) {
+ continue;
+ }
+
$attachlist[] = ['type' => str_replace('as:', '', JsonLD::fetchElement($attachment, '@type')),
'mediaType' => JsonLD::fetchElement($attachment, 'as:mediaType'),
'name' => JsonLD::fetchElement($attachment, 'as:name'),
$object_data['diaspora:guid'] = JsonLD::fetchElement($object, 'diaspora:guid');
$object_data['diaspora:comment'] = JsonLD::fetchElement($object, 'diaspora:comment');
- $object_data['owner'] = $object_data['author'] = $actor;
+ $object_data['actor'] = $object_data['author'] = $actor;
$object_data['context'] = JsonLD::fetchElement($object, 'as:context');
$object_data['conversation'] = JsonLD::fetchElement($object, 'ostatus:conversation');
$object_data['sensitive'] = JsonLD::fetchElement($object, 'as:sensitive');
}
}
- $object_data['receiver'] = self::getReceivers($object, $object_data['owner']);
+ $object_data['receiver'] = self::getReceivers($object, $object_data['actor']);
// Common object data: