]> git.mxchange.org Git - friendica.git/blobdiff - src/Protocol/ActivityPub/Receiver.php
Merge remote-tracking branch 'upstream/develop' into fetch-item
[friendica.git] / src / Protocol / ActivityPub / Receiver.php
index 7ae68cd4d1247238fc50a15ef6fa1030ff7d4463..bb676b396e338113ee517be084f8dfde49ec994e 100644 (file)
@@ -194,6 +194,11 @@ class Receiver
                        return [];
                }
 
+               if (!is_string($object_id)) {
+                       Logger::info('Invalid object id', ['object' => $object_id]);
+                       return [];
+               }
+
                $object_type = self::fetchObjectType($activity, $object_id, $uid);
 
                // Fetch the content only on activities where this matters
@@ -207,12 +212,17 @@ class Receiver
                                return [];
                        }
                        $object_data['object_id'] = $object_id;
-                       $object_data['directmessage'] = JsonLD::fetchElement($activity, 'litepub:directMessage');
+
+                       // Test if it is an answer to a mail
+                       if (DBA::exists('mail', ['uri' => $object_data['reply-to-id']])) {
+                               $object_data['directmessage'] = true;
+                       } else {
+                               $object_data['directmessage'] = JsonLD::fetchElement($activity, 'litepub:directMessage');
+                       }
 
                        // We had been able to retrieve the object data - so we can trust the source
                        $trust_source = true;
-               } elseif (in_array($type, ['as:Like', 'as:Dislike']) ||
-                       (($type == 'as:Follow') && in_array($object_type, self::CONTENT_TYPES))) {
+               } elseif (in_array($type, array_merge(self::ACTIVITY_TYPES, ['as:Follow'])) && in_array($object_type, self::CONTENT_TYPES)) {
                        // 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($activity);
@@ -220,6 +230,13 @@ class Receiver
                        $object_data['author'] = JsonLD::fetchElement($activity, 'as:actor', '@id');
                        $object_data['object_id'] = $object_id;
                        $object_data['object_type'] = ''; // Since we don't fetch the object, we don't know the type
+               } elseif (in_array($type, ['as:Add'])) {
+                       $object_data = [];
+                       $object_data['id'] = JsonLD::fetchElement($activity, '@id');
+                       $object_data['target_id'] = JsonLD::fetchElement($activity, 'as:target', '@id');
+                       $object_data['object_id'] = JsonLD::fetchElement($activity, 'as:object', '@id');
+                       $object_data['object_type'] = JsonLD::fetchElement($activity['as:object'], '@type');
+                       $object_data['object_content'] = JsonLD::fetchElement($activity['as:object'], 'as:content', '@type');
                } else {
                        $object_data = [];
                        $object_data['id'] = JsonLD::fetchElement($activity, '@id');
@@ -360,18 +377,23 @@ class Receiver
                                }
                                break;
 
+                       case 'as:Add':
+                               if ($object_data['object_type'] == 'as:tag') {
+                                       ActivityPub\Processor::addTag($object_data);
+                               }
+                               break;
+
                        case 'as:Announce':
                                if (in_array($object_data['object_type'], self::CONTENT_TYPES)) {
                                        $profile = APContact::getByURL($object_data['actor']);
-                                       if ($profile['type'] == 'Person') {
-                                               // Reshared posts from persons appear as summary at the bottom
-                                               // If this isn't set, then a single reshare appears on top. This is used for groups.
-                                               $object_data['thread-completion'] = true;
-                                       }
+                                       // Reshared posts from persons appear as summary at the bottom
+                                       // If this isn't set, then a single reshare appears on top. This is used for groups.
+                                       $object_data['thread-completion'] = ($profile['type'] != 'Group');
+
                                        ActivityPub\Processor::createItem($object_data);
 
                                        // Add the bottom reshare information only for persons
-                                       if ($profile['type'] == 'Person') {
+                                       if ($profile['type'] != 'Group') {
                                                $announce_object_data = self::processObject($activity);
                                                $announce_object_data['name'] = $type;
                                                $announce_object_data['author'] = JsonLD::fetchElement($activity, 'as:actor', '@id');
@@ -533,7 +555,7 @@ class Receiver
                                // Check if the potential receiver is following the actor
                                // Exception: The receiver is targetted via "to" or this is a comment
                                if ((($element != 'as:to') && empty($replyto)) || ($contact['contact-type'] == Contact::TYPE_COMMUNITY)) {
-                                       $networks = [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS];
+                                       $networks = Protocol::FEDERATED;
                                        $condition = ['nurl' => Strings::normaliseLink($actor), 'rel' => [Contact::SHARING, Contact::FRIEND],
                                                'network' => $networks, 'archive' => false, 'pending' => false, 'uid' => $contact['uid']];
 
@@ -568,7 +590,7 @@ class Receiver
        public static function getReceiverForActor($actor, $tags)
        {
                $receivers = [];
-               $networks = [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS];
+               $networks = Protocol::FEDERATED;
                $condition = ['nurl' => Strings::normaliseLink($actor), 'rel' => [Contact::SHARING, Contact::FRIEND, Contact::FOLLOWER],
                        'network' => $networks, 'archive' => false, 'pending' => false];
                $contacts = DBA::select('contact', ['uid', 'rel'], $condition);
@@ -634,27 +656,14 @@ class Receiver
         */
        public static function switchContact($cid, $uid, $url)
        {
-               $profile = ActivityPub::probeProfile($url);
-               if (empty($profile)) {
-                       return;
-               }
-
-               Logger::log('Switch contact ' . $cid . ' (' . $profile['url'] . ') for user ' . $uid . ' to ActivityPub');
+               Contact::updateFromProbe($cid, '', true);
 
-               $photo = defaults($profile, 'photo', null);
-               unset($profile['photo']);
-               unset($profile['baseurl']);
-               unset($profile['guid']);
-
-               $profile['nurl'] = Strings::normaliseLink($profile['url']);
-               DBA::update('contact', $profile, ['id' => $cid]);
-
-               Contact::updateAvatar($photo, $uid, $cid);
+               Logger::log('Switch contact ' . $cid . ' (' . $url . ') for user ' . $uid . ' to ActivityPub');
 
                // Send a new follow request to be sure that the connection still exists
                if (($uid != 0) && DBA::exists('contact', ['id' => $cid, 'rel' => [Contact::SHARING, Contact::FRIEND]])) {
-                       ActivityPub\Transmitter::sendActivity('Follow', $profile['url'], $uid);
-                       Logger::log('Send a new follow request to ' . $profile['url'] . ' for user ' . $uid, Logger::DEBUG);
+                       ActivityPub\Transmitter::sendActivity('Follow', $url, $uid);
+                       Logger::log('Send a new follow request to ' . $url . ' for user ' . $uid, Logger::DEBUG);
                }
        }
 
@@ -717,11 +726,11 @@ class Receiver
         * @param boolean $trust_source Do we trust the provided object?
         * @param integer $uid          User ID for the signature that we use to fetch data
         *
-        * @return array with trusted and valid object data
+        * @return array|false with trusted and valid object data
         * @throws \Friendica\Network\HTTPException\InternalServerErrorException
         * @throws \ImagickException
         */
-       private static function fetchObject($object_id, $object = [], $trust_source = false, $uid = 0)
+       private static function fetchObject(string $object_id, array $object = [], bool $trust_source = false, int $uid = 0)
        {
                // By fetching the type we check if the object is complete.
                $type = JsonLD::fetchElement($object, '@type');
@@ -760,13 +769,14 @@ class Receiver
 
                if ($type == 'as:Announce') {
                        $object_id = JsonLD::fetchElement($object, 'object', '@id');
-                       if (empty($object_id)) {
+                       if (empty($object_id) || !is_string($object_id)) {
                                return false;
                        }
                        return self::fetchObject($object_id, [], false, $uid);
                }
 
                Logger::log('Unhandled object type: ' . $type, Logger::DEBUG);
+               return false;
        }
 
        /**
@@ -936,11 +946,6 @@ class Receiver
 
                $object_data['receiver'] = self::getReceivers($object, $object_data['actor'], $object_data['tags']);
 
-               // Test if it is an answer to a mail
-               if (DBA::exists('mail', ['uri' => $object_data['reply-to-id']])) {
-                       $object_data['directmessage'] = true;
-               }
-
                // Common object data:
 
                // Unhandled