]> git.mxchange.org Git - friendica.git/commitdiff
Issue 12603: Support quote in the api / Issue 12654: prevent privacy leakage
authorMichael <heluecht@pirati.ca>
Mon, 23 Jan 2023 21:24:50 +0000 (21:24 +0000)
committerMichael <heluecht@pirati.ca>
Mon, 23 Jan 2023 21:24:50 +0000 (21:24 +0000)
src/Factory/Api/Mastodon/Status.php
src/Module/Api/Mastodon/Statuses.php
src/Object/Api/Mastodon/Status.php

index bac9d18035324ba9858df9676ee7064ab2e8a5e5..a72406788ba07e5cf54ac28280994529defc1339 100644 (file)
@@ -24,6 +24,7 @@ namespace Friendica\Factory\Api\Mastodon;
 use Friendica\BaseFactory;
 use Friendica\Content\ContactSelector;
 use Friendica\Content\Item as ContentItem;
+use Friendica\Content\Text\BBCode;
 use Friendica\Database\Database;
 use Friendica\Database\DBA;
 use Friendica\Model\Item;
@@ -76,15 +77,16 @@ class Status extends BaseFactory
        }
 
        /**
-        * @param int  $uriId  Uri-ID of the item
-        * @param int  $uid    Item user
-        * @param bool $reblog Check for reblogged post
+        * @param int  $uriId           Uri-ID of the item
+        * @param int  $uid             Item user
+        * @param bool $reblog          Check for reblogged post
+        * @param bool $in_reply_status Add an "in_reply_status" element
         *
         * @return \Friendica\Object\Api\Mastodon\Status
         * @throws HTTPException\InternalServerErrorException
         * @throws ImagickException|HTTPException\NotFoundException
         */
-       public function createFromUriId(int $uriId, int $uid = 0, bool $reblog = true): \Friendica\Object\Api\Mastodon\Status
+       public function createFromUriId(int $uriId, int $uid = 0, bool $reblog = true, bool $in_reply_status = true, bool $diplay_quote = false): \Friendica\Object\Api\Mastodon\Status
        {
                $fields = ['uri-id', 'uid', 'author-id', 'causer-id', 'author-uri-id', 'author-link', 'causer-uri-id', 'post-reason', 'starred', 'app', 'title', 'body', 'raw-body', 'content-warning', 'question-id',
                        'created', 'network', 'thr-parent-id', 'parent-author-id', 'language', 'uri', 'plink', 'private', 'vid', 'gravity', 'featured', 'has-media', 'quote-uri-id'];
@@ -222,25 +224,67 @@ class Status extends BaseFactory
                        }
                }
 
-               $item['body'] = $this->contentItem->addSharedPost($item);
+               if ($diplay_quote) {
+                       $quote = self::createQuote($item, $uid);
 
-               if (!is_null($item['raw-body'])) {
-                       $item['raw-body'] = $this->contentItem->addSharedPost($item, $item['raw-body']);
+                       $item['body'] = BBCode::removeSharedData($item['body']);
+
+                       if (!is_null($item['raw-body'])) {
+                               $item['raw-body'] = BBCode::removeSharedData($item['raw-body']);
+                       }
+               } else {
+                       // We can always safely add attached activities. Real quotes are added to the body via "addSharedPost".
+                       if (empty($item['quote-uri-id'])) {
+                               $quote = self::createQuote($item, $uid);
+                       }
+
+                       $item['body'] = $this->contentItem->addSharedPost($item);
+
+                       if (!is_null($item['raw-body'])) {
+                               $item['raw-body'] = $this->contentItem->addSharedPost($item, $item['raw-body']);
+                       }
                }
 
                if ($is_reshare) {
-                       $reshare = $this->createFromUriId($uriId, $uid, false)->toArray();
+                       $reshare = $this->createFromUriId($uriId, $uid, false, false)->toArray();
                } else {
                        $reshare = [];
                }
 
-               if (!empty($item['quote-uri-id'])) {
-                       $quote = $this->createFromUriId($item['quote-uri-id'], $uid, false)->toArray();
+               if ($in_reply_status && ($item['gravity'] == Item::GRAVITY_COMMENT)) {
+                       $in_reply = $this->createFromUriId($item['thr-parent-id'], $uid, false, false)->toArray();
                } else {
-                       $quote = [];
+                       $in_reply = [];
                }
 
-               return new \Friendica\Object\Api\Mastodon\Status($item, $account, $counts, $userAttributes, $sensitive, $application, $mentions, $tags, $card, $attachments, $reshare, $quote, $poll);
+               return new \Friendica\Object\Api\Mastodon\Status($item, $account, $counts, $userAttributes, $sensitive, $application, $mentions, $tags, $card, $attachments, $in_reply, $reshare, $quote, $poll);
+       }
+
+       /**
+        * Create a quote status object
+        *
+        * @param array $item
+        * @param integer $uid
+        * @return array
+        */
+       private function createQuote(array $item, int $uid): array
+       {
+               if (empty($item['quote-uri-id'])) {
+                       $media = Post\Media::getByURIId($item['uri-id'], [Post\Media::ACTIVITY]);
+                       if (!empty($media)) {
+                               $shared_item = Post::selectFirst(['uri-id'], ['plink' => $media[0]['url'], 'uid' => [$uid, 0]]);
+                               $quote_id = $shared_item['uri-id'];
+                       }
+               } else {
+                       $quote_id = $item['quote-uri-id'];
+               }
+
+               if (!empty($quote_id)) {
+                       $quote = $this->createFromUriId($quote_id, $uid, false, false)->toArray();
+               } else {
+                       $quote = [];
+               }
+               return $quote;
        }
 
        /**
@@ -271,8 +315,9 @@ class Status extends BaseFactory
                $tags        = [];
                $card        = new \Friendica\Object\Api\Mastodon\Card([]);
                $attachments = [];
+               $in_reply    = [];
                $reshare     = [];
 
-               return new \Friendica\Object\Api\Mastodon\Status($item, $account, $counts, $userAttributes, $sensitive, $application, $mentions, $tags, $card, $attachments, $reshare);
+               return new \Friendica\Object\Api\Mastodon\Status($item, $account, $counts, $userAttributes, $sensitive, $application, $mentions, $tags, $card, $attachments, $in_reply, $reshare);
        }
 }
index 71681968db2c6cddeb3952de509bba74cf52dc14..7419cccb38b6e2aa4c1e980c1a84d1160ea81425 100644 (file)
@@ -101,6 +101,7 @@ class Statuses extends BaseApi
                        'media_ids'      => [],    // Array of Attachment ids to be attached as media. If provided, status becomes optional, and poll cannot be used.
                        'poll'           => [],    // Poll data. If provided, media_ids cannot be used, and poll[expires_in] must be provided.
                        'in_reply_to_id' => 0,     // ID of the status being replied to, if status is a reply
+                       'quote_id'       => 0,     // ID of the message to quote
                        'sensitive'      => false, // Mark status and attached media as sensitive?
                        'spoiler_text'   => '',    // Text to be shown as a warning or subject before the actual content. Statuses are generally collapsed behind this field.
                        'visibility'     => '',    // Visibility of the posted status. One of: "public", "unlisted", "private" or "direct".
@@ -153,6 +154,7 @@ class Statuses extends BaseApi
                                $item['private'] = Item::PRIVATE;
                                break;
                        case 'direct':
+                               $item['private'] = Item::PRIVATE;
                                // The permissions are assigned in "expandTags"
                                break;
                        default:
@@ -183,11 +185,15 @@ class Statuses extends BaseApi
                }
 
                if ($request['in_reply_to_id']) {
-                       $parent = Post::selectFirst(['uri'], ['uri-id' => $request['in_reply_to_id'], 'uid' => [0, $uid]]);
+                       $parent = Post::selectFirst(['uri', 'private'], ['uri-id' => $request['in_reply_to_id'], 'uid' => [0, $uid]]);
 
                        $item['thr-parent']  = $parent['uri'];
                        $item['gravity']     = Item::GRAVITY_COMMENT;
                        $item['object-type'] = Activity\ObjectType::COMMENT;
+
+                       if (in_array($parent['private'], [Item::UNLISTED, Item::PUBLIC]) && ($item['private'] == Item::PRIVATE)) {
+                               throw new HTTPException\NotImplementedException('Private replies for public posts are not implemented.');
+                       }
                } else {
                        self::checkThrottleLimit();
 
@@ -195,6 +201,13 @@ class Statuses extends BaseApi
                        $item['object-type'] = Activity\ObjectType::NOTE;
                }
 
+               if ($request['quote_id']) {
+                       if (!Post::exists(['uri-id' => $request['quote_id'], 'uid' => [0, $uid]])) {
+                               throw new HTTPException\NotFoundException('Item with URI ID ' . $request['quote_id'] . ' not found for user ' . $uid . '.');
+                       }
+                       $item['quote-uri-id'] = $request['quote_id'];
+               }
+
                if (!empty($request['spoiler_text'])) {
                        if (!$request['in_reply_to_id'] && DI::pConfig()->get($uid, 'system', 'api_spoiler_title', true)) {
                                $item['title'] = $request['spoiler_text'];
index 2fcbb10e3a7fa6d23c12b63ed9f6d5c85bea1aa2..e3f322778d13a36ead639f2b40372fc20f666da8 100644 (file)
@@ -41,6 +41,8 @@ class Status extends BaseDataTransferObject
        protected $created_at;
        /** @var string|null */
        protected $in_reply_to_id = null;
+       /** @var Status|null - Fedilab extension, see issue https://github.com/friendica/friendica/issues/12672 */
+       protected $in_reply_to_status = null;
        /** @var string|null */
        protected $in_reply_to_account_id = null;
        /** @var bool */
@@ -75,7 +77,7 @@ class Status extends BaseDataTransferObject
        protected $content;
        /** @var Status|null */
        protected $reblog = null;
-       /** @var Status|null */
+       /** @var Status|null - Akkoma extension, see issue https://github.com/friendica/friendica/issues/12603 */
        protected $quote = null;
        /** @var Application */
        protected $application = null;
@@ -100,13 +102,14 @@ class Status extends BaseDataTransferObject
         * @param array   $item
         * @throws \Friendica\Network\HTTPException\InternalServerErrorException
         */
-       public function __construct(array $item, Account $account, Counts $counts, UserAttributes $userAttributes, bool $sensitive, Application $application, array $mentions, array $tags, Card $card, array $attachments, array $reblog, array $quote = null, array $poll = null)
+       public function __construct(array $item, Account $account, Counts $counts, UserAttributes $userAttributes, bool $sensitive, Application $application, array $mentions, array $tags, Card $card, array $attachments, array $in_reply, array $reblog, array $quote = null, array $poll = null)
        {
                $this->id         = (string)$item['uri-id'];
                $this->created_at = DateTimeFormat::utc($item['created'], DateTimeFormat::JSON);
 
                if ($item['gravity'] == Item::GRAVITY_COMMENT) {
                        $this->in_reply_to_id         = (string)$item['thr-parent-id'];
+                       $this->in_reply_to_status     = $in_reply;
                        $this->in_reply_to_account_id = (string)$item['parent-author-id'];
                }
 
@@ -172,6 +175,10 @@ class Status extends BaseDataTransferObject
                        $status['quote'] = null;
                }
 
+               if (empty($status['in_reply_to_status'])) {
+                       $status['in_reply_to_status'] = null;
+               }
+
                return $status;
        }
 }