From 567292533eedfc49a738b6fef6bec79a8c12b6d0 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 10 May 2024 17:14:05 +0000 Subject: [PATCH] Issue 11963: Set Permissions for attachments --- mod/item.php | 7 ++--- src/Content/Item.php | 44 +++++--------------------------- src/Model/Attach.php | 55 ++++++++++++++++++++++++++++++++++------ src/Model/Item.php | 6 ++--- src/Model/Post/Media.php | 43 +++++++++++++++++++++---------- 5 files changed, 90 insertions(+), 65 deletions(-) diff --git a/mod/item.php b/mod/item.php index c34c4ec017..6af1e2d221 100644 --- a/mod/item.php +++ b/mod/item.php @@ -45,7 +45,8 @@ use Friendica\Model\Post; use Friendica\Network\HTTPException; use Friendica\Util\DateTimeFormat; -function item_post(App $a) { +function item_post(App $a) +{ $uid = DI::userSession()->getLocalUserId(); if (!$uid) { @@ -248,7 +249,7 @@ function item_process(array $post, array $request, bool $preview, string $return $post['body'] .= DI::contentItem()->storeAttachmentFromRequest($request); } - $post = DI::contentItem()->finalizePost($post); + $post = DI::contentItem()->finalizePost($post, $preview); if (!strlen($post['body'])) { if ($preview) { @@ -286,7 +287,7 @@ function item_process(array $post, array $request, bool $preview, string $return System::jsonExit(['preview' => $o]); } - Hook::callAll('post_local',$post); + Hook::callAll('post_local', $post); unset($post['edit']); unset($post['self']); diff --git a/src/Content/Item.php b/src/Content/Item.php index aa8662705c..41879b75b9 100644 --- a/src/Content/Item.php +++ b/src/Content/Item.php @@ -48,7 +48,6 @@ use Friendica\Model\User; use Friendica\Network\HTTPException; use Friendica\Object\EMail\ItemCCEMail; use Friendica\Protocol\Activity; -use Friendica\Protocol\ActivityPub; use Friendica\Util\ACLFormatter; use Friendica\Util\DateTimeFormat; use Friendica\Util\Emailer; @@ -912,40 +911,6 @@ class Item return $post; } - public function moveAttachmentsFromBodyToAttach(array $post): array - { - if (!preg_match_all('/(\[attachment\]([0-9]+)\[\/attachment\])/', $post['body'], $match)) { - return $post; - } - - foreach ($match[2] as $attachment_id) { - $attachment = Attach::selectFirst(['id', 'uid', 'filename', 'filesize', 'filetype'], ['id' => $attachment_id, 'uid' => $post['uid']]); - if (empty($attachment)) { - continue; - } - if ($post['attach']) { - $post['attach'] .= ','; - } - $post['attach'] .= Post\Media::getAttachElement( - $this->baseURL . '/attach/' . $attachment['id'], - $attachment['filesize'], - $attachment['filetype'], - $attachment['filename'] ?? '' - ); - - $fields = [ - 'allow_cid' => $post['allow_cid'], 'allow_gid' => $post['allow_gid'], - 'deny_cid' => $post['deny_cid'], 'deny_gid' => $post['deny_gid'] - ]; - $condition = ['id' => $attachment_id]; - Attach::update($fields, $condition); - } - - $post['body'] = str_replace($match[1], '', $post['body']); - - return $post; - } - private function setObjectType(array $post): array { if (empty($post['post-type'])) { @@ -1025,8 +990,13 @@ class Item return $post; } - public function finalizePost(array $post): array + public function finalizePost(array $post, bool $preview): array { + if ($preview) { + $post['body'] = Attach::addAttachmentToBody($post['body'], $post['uid']); + } else { + Attach::setPermissionFromBody($post); + } if (preg_match("/\[attachment\](.*?)\[\/attachment\]/ism", $post['body'], $matches)) { $post['body'] = preg_replace("/\[attachment].*?\[\/attachment\]/ism", PageInfo::getFooterFromUrl($matches[1]), $post['body']); } @@ -1080,7 +1050,7 @@ class Item $to_author = DBA::selectFirst('account-view', ['ap-followers'], ['id' => $to['author-id']]); $parent = Post::selectFirstPost(['author-id'], ['uri-id' => $parentUriId]); $parent_author = DBA::selectFirst('account-view', ['ap-followers'], ['id' => $parent['author-id']]); - + $followers = ''; foreach (array_column(Tag::getByURIId($parentUriId, [Tag::TO, Tag::CC, Tag::BCC]), 'url') as $url) { if ($url == $parent_author['ap-followers']) { diff --git a/src/Model/Attach.php b/src/Model/Attach.php index cf0913c5e3..a43062691d 100644 --- a/src/Model/Attach.php +++ b/src/Model/Attach.php @@ -30,6 +30,7 @@ use Friendica\Object\Image; use Friendica\Util\DateTimeFormat; use Friendica\Util\Mimetype; use Friendica\Security\Security; +use Friendica\Util\Network; /** * Class to handle attach database table @@ -109,16 +110,17 @@ class Attach /** * Retrieve a single record given the ID * - * @param int $id Row id of the record + * @param int $id Row id of the record + * @param int $uid User-Id * * @return bool|array * * @throws \Exception * @see \Friendica\Database\DBA::select */ - public static function getById(int $id) + public static function getById(int $id, int $uid) { - return self::selectFirst([], ['id' => $id]); + return self::selectFirst([], ['id' => $id, 'uid' => $uid]); } /** @@ -197,7 +199,7 @@ class Attach * @return boolean|integer Row id on success, False on errors * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public static function store(string $data, int $uid, string $filename, string $filetype = '' , int $filesize = null, string $allow_cid = '', string $allow_gid = '', string $deny_cid = '', string $deny_gid = '') + public static function store(string $data, int $uid, string $filename, string $filetype = '', int $filesize = null, string $allow_cid = '', string $allow_gid = '', string $deny_cid = '', string $deny_gid = '') { if ($filetype === '') { $filetype = Mimetype::getContentType($filename); @@ -279,9 +281,9 @@ class Attach { if (!is_null($img)) { // get items to update - $items = self::selectToArray(['backend-class','backend-ref'], $conditions); + $items = self::selectToArray(['backend-class', 'backend-ref'], $conditions); - foreach($items as $item) { + foreach ($items as $item) { try { $backend_class = DI::storageManager()->getWritableStorageByName($item['backend-class'] ?? ''); $fields['backend-ref'] = $backend_class->put($img->asString(), $item['backend-ref'] ?? ''); @@ -313,9 +315,9 @@ class Attach public static function delete(array $conditions, array $options = []): bool { // get items to delete data info - $items = self::selectToArray(['backend-class','backend-ref'], $conditions); + $items = self::selectToArray(['backend-class', 'backend-ref'], $conditions); - foreach($items as $item) { + foreach ($items as $item) { try { $backend_class = DI::storageManager()->getWritableStorageByName($item['backend-class'] ?? ''); $backend_class->delete($item['backend-ref'] ?? ''); @@ -328,4 +330,41 @@ class Attach return DBA::delete('attach', $conditions, $options); } + + public static function setPermissionFromBody(array $post) + { + preg_match_all("/\[attachment\](.*?)\[\/attachment\]/ism", $post['body'], $matches, PREG_SET_ORDER); + foreach ($matches as $attachment) { + if (Network::isLocalLink($attachment[1]) && preg_match('|.*?/attach/(\d+)|', $attachment[1], $match)) { + $fields = [ + 'allow_cid' => $post['allow_cid'], 'allow_gid' => $post['allow_gid'], + 'deny_cid' => $post['deny_cid'], 'deny_gid' => $post['deny_gid'] + ]; + self::update($fields, ['id' => $match[1], 'uid' => $post['uid']]); + } + } + } + + public static function addAttachmentToBody(string $body, int $uid): string + { + preg_match_all("/\[attachment\](.*?)\[\/attachment\]/ism", $body, $matches, PREG_SET_ORDER); + foreach ($matches as $attachment) { + if (Network::isLocalLink($attachment[1]) && preg_match('|.*?/attach/(\d+)|', $attachment[1], $match)) { + $attach = self::getById($match[1], $uid); + if (empty($attach)) { + return $body; + } + $media = [ + 'type' => Post\Media::DOCUMENT, + 'url' => $attachment[1], + 'size' => $attach['filesize'], + 'mimetype' => $attach['filetype'], + 'description' => $attach['filename'] + ]; + $media = Post\Media::addType($media); + $body = str_replace($attachment[0], Post\Media::addAttachmentToBody($media, ''), $body); + } + } + return $body; + } } diff --git a/src/Model/Item.php b/src/Model/Item.php index cf057eed59..730ec84f76 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -848,7 +848,7 @@ class Item private static function prepareOriginPost(array $item): array { $item = DI::contentItem()->initializePost($item); - $item = DI::contentItem()->finalizePost($item); + $item = DI::contentItem()->finalizePost($item, false); return $item; } @@ -1044,7 +1044,7 @@ class Item $item['deny_gid'] = $store_permissions ? $toplevel_parent['deny_gid'] : ''; } - $parent_origin = $toplevel_parent['origin']; + $parent_origin = $toplevel_parent['origin']; // Don't federate received participation messages if ($item['verb'] != Activity::FOLLOW) { @@ -1088,8 +1088,6 @@ class Item ) { $item['object-type'] = Activity\ObjectType::IMAGE; } - - $item = DI::contentItem()->moveAttachmentsFromBodyToAttach($item); } $item['parent-uri-id'] = ItemURI::getIdByURI($item['parent-uri']); diff --git a/src/Model/Post/Media.php b/src/Model/Post/Media.php index 0b8a971803..5d9d512f8f 100644 --- a/src/Model/Post/Media.php +++ b/src/Model/Post/Media.php @@ -28,6 +28,7 @@ use Friendica\Core\Protocol; use Friendica\Database\Database; use Friendica\Database\DBA; use Friendica\DI; +use Friendica\Model\Attach; use Friendica\Model\Contact; use Friendica\Model\Item; use Friendica\Model\ItemURI; @@ -389,6 +390,16 @@ class Media */ private static function fetchLocalData(array $media): array { + if (preg_match('|.*?/attach/(\d+)|', $media['url'] ?? '', $matches)) { + $attachment = Attach::selectFirst(['filename', 'filetype', 'filesize'], ['id' => $matches[1]]); + if (!empty($attachment)) { + $media['name'] = $attachment['filename']; + $media['mimetype'] = $attachment['filetype']; + $media['size'] = $attachment['filesize']; + } + return $media; + } + if (!preg_match('|.*?/photo/(.*[a-fA-F0-9])\-(.*[0-9])\..*[\w]|', $media['url'] ?? '', $matches)) { return $media; } @@ -902,19 +913,7 @@ class Media $body = BBCode::removeAttachment($body); foreach (self::getByURIId($uriid, $types) as $media) { - if (Item::containsLink($body, $media['preview'] ?? $media['url'], $media['type'])) { - continue; - } - - if ($media['type'] == self::IMAGE) { - $body .= "\n" . Images::getBBCodeByUrl($media['url'], $media['preview'], $media['description'] ?? ''); - } elseif ($media['type'] == self::AUDIO) { - $body .= "\n[audio]" . $media['url'] . "[/audio]\n"; - } elseif ($media['type'] == self::VIDEO) { - $body .= "\n[video]" . $media['url'] . "[/video]\n"; - } else { - $body .= "\n[url]" . $media['url'] . "[/url]\n"; - } + $body = self::addAttachmentToBody($media, $body); } if (preg_match("/.*(\[attachment.*?\].*?\[\/attachment\]).*/ism", $original_body, $match)) { @@ -924,6 +923,24 @@ class Media return $body; } + public static function addAttachmentToBody(array $media, string $body): string + { + if (Item::containsLink($body, $media['preview'] ?? $media['url'], $media['type'])) { + return $body; + } + + if ($media['type'] == self::IMAGE) { + $body .= "\n" . Images::getBBCodeByUrl($media['url'], $media['preview'], $media['description'] ?? ''); + } elseif ($media['type'] == self::AUDIO) { + $body .= "\n[audio]" . $media['url'] . "[/audio]\n"; + } elseif ($media['type'] == self::VIDEO) { + $body .= "\n[video]" . $media['url'] . "[/video]\n"; + } else { + $body .= "\n[url]" . $media['url'] . "[/url]\n"; + } + return $body; + } + /** * Add an [attachment] element to the body for a given uri-id with a HTML media element *