diff options
author | Julius Härtl <jus@bitgrid.net> | 2022-08-28 20:54:21 +0200 |
---|---|---|
committer | Julius Härtl <jus@bitgrid.net> | 2022-08-31 16:24:33 +0200 |
commit | a392235e23c3b8af1d0eba4dbac18b18de826a1c (patch) | |
tree | c983c213d99937bb53463e759d703d85861fb631 /lib/private/Collaboration | |
parent | bee8fd2408b053756e052a2b96899935c1adf872 (diff) | |
download | nextcloud-server-a392235e23c3b8af1d0eba4dbac18b18de826a1c.tar.gz nextcloud-server-a392235e23c3b8af1d0eba4dbac18b18de826a1c.zip |
Cleanup
Signed-off-by: Julius Härtl <jus@bitgrid.net>
Diffstat (limited to 'lib/private/Collaboration')
4 files changed, 73 insertions, 41 deletions
diff --git a/lib/private/Collaboration/Reference/FileReferenceProvider.php b/lib/private/Collaboration/Reference/FileReferenceProvider.php index 9a4bd65249f..358092ff508 100644 --- a/lib/private/Collaboration/Reference/FileReferenceProvider.php +++ b/lib/private/Collaboration/Reference/FileReferenceProvider.php @@ -1,4 +1,6 @@ <?php + +declare(strict_types=1); /** * @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net> * @@ -22,11 +24,15 @@ namespace OC\Collaboration\Reference; +use OC\User\NoUserException; use OCP\Collaboration\Reference\IReference; use OCP\Collaboration\Reference\IReferenceProvider; +use OCP\Files\InvalidPathException; use OCP\Files\IRootFolder; use OCP\Files\Node; use OCP\Files\NotFoundException; +use OCP\Files\NotPermittedException; +use OCP\IPreview; use OCP\IURLGenerator; use OCP\IUserSession; @@ -34,11 +40,13 @@ class FileReferenceProvider implements IReferenceProvider { private IURLGenerator $urlGenerator; private IRootFolder $rootFolder; private ?string $userId; + private IPreview $previewManager; - public function __construct(IURLGenerator $urlGenerator, IRootFolder $rootFolder, IUserSession $userSession) { + public function __construct(IURLGenerator $urlGenerator, IRootFolder $rootFolder, IUserSession $userSession, IPreview $previewManager) { $this->urlGenerator = $urlGenerator; $this->rootFolder = $rootFolder; $this->userId = $userSession->getUser() ? $userSession->getUser()->getUID() : null; + $this->previewManager = $previewManager; } public function matchReference(string $referenceText): bool { @@ -52,6 +60,7 @@ class FileReferenceProvider implements IReferenceProvider { try { $this->fetchReference($reference); } catch (NotFoundException $e) { + $reference->setRichObject('file', null); $reference->setAccessible(false); } return $reference; @@ -61,10 +70,7 @@ class FileReferenceProvider implements IReferenceProvider { } /** - * @throws \OCP\Files\NotPermittedException - * @throws \OCP\Files\InvalidPathException * @throws NotFoundException - * @throws \OC\User\NoUserException */ private function fetchReference(Reference $reference) { if ($this->userId === null) { @@ -74,30 +80,34 @@ class FileReferenceProvider implements IReferenceProvider { $fileId = str_replace($this->urlGenerator->getAbsoluteURL('/index.php/f/'), '', $reference->getId()); $fileId = str_replace($this->urlGenerator->getAbsoluteURL('/f/'), '', $fileId); - $userFolder = $this->rootFolder->getUserFolder($this->userId); - $files = $userFolder->getById((int)$fileId); + try { + $userFolder = $this->rootFolder->getUserFolder($this->userId); + $files = $userFolder->getById((int)$fileId); + + if (empty($files)) { + throw new NotFoundException(); + } - if (empty($files)) { + /** @var Node $file */ + $file = array_shift($files); + + $reference->setTitle($file->getName()); + $reference->setDescription($file->getMimetype()); + $reference->setUrl($this->urlGenerator->getAbsoluteURL('/index.php/f/' . $fileId)); + $reference->setImageUrl($this->urlGenerator->linkToRouteAbsolute('core.Preview.getPreviewByFileId', ['x' => 1600, 'y' => 630, 'fileId' => $fileId])); + + $reference->setRichObject('file', [ + 'id' => $file->getId(), + 'name' => $file->getName(), + 'size' => $file->getSize(), + 'path' => $file->getPath(), + 'link' => $reference->getUrl(), + 'mimetype' => $file->getMimetype(), + 'preview-available' => $this->previewManager->isAvailable($file) + ]); + } catch (InvalidPathException|NotFoundException|NotPermittedException|NoUserException $e) { throw new NotFoundException(); } - - /** @var Node $file */ - $file = array_shift($files); - - $reference->setTitle($file->getName()); - $reference->setDescription($file->getMimetype()); - $reference->setUrl($this->urlGenerator->getAbsoluteURL('/index.php/f/' . $fileId)); - $reference->setImageUrl($this->urlGenerator->linkToRouteAbsolute('core.Preview.getPreviewByFileId', ['x' => 1600, 'y' => 630, 'fileId' => $fileId])); - - $reference->setRichObject('file', [ - 'id' => $file->getId(), - 'name' => $file->getName(), - 'size' => $file->getSize(), - 'path' => $file->getPath(), - 'link' => $reference->getUrl(), - 'mimetype' => $file->getMimetype(), - 'preview-available' => false - ]); } public function isGloballyCacheable(): bool { @@ -105,6 +115,6 @@ class FileReferenceProvider implements IReferenceProvider { } public function getCacheKey(string $referenceId): string { - return $this->userId; + return $this->userId ?? ''; } } diff --git a/lib/private/Collaboration/Reference/LinkReferenceProvider.php b/lib/private/Collaboration/Reference/LinkReferenceProvider.php index 74eb21b8785..7ac6aca5f89 100644 --- a/lib/private/Collaboration/Reference/LinkReferenceProvider.php +++ b/lib/private/Collaboration/Reference/LinkReferenceProvider.php @@ -27,6 +27,8 @@ namespace OC\Collaboration\Reference; use Fusonic\OpenGraph\Consumer; use GuzzleHttp\Psr7\LimitStream; use GuzzleHttp\Psr7\Utils; +use OC\Security\RateLimiting\Exception\RateLimitExceededException; +use OC\Security\RateLimiting\Limiter; use OC\SystemConfig; use OCP\Collaboration\Reference\IReference; use OCP\Collaboration\Reference\IReferenceProvider; @@ -37,7 +39,6 @@ use OCP\IURLGenerator; use Psr\Log\LoggerInterface; class LinkReferenceProvider implements IReferenceProvider { - public const URL_PATTERN = '/(\s|^)(https?:\/\/)?((?:[-A-Z0-9+_]+\.)+[-A-Z]+(?:\/[-A-Z0-9+&@#%?=~_|!:,.;()]*)*)(\s|$)/i'; public const MAX_PREVIEW_SIZE = 1024 * 1024; public const ALLOWED_CONTENT_TYPES = [ @@ -54,13 +55,15 @@ class LinkReferenceProvider implements IReferenceProvider { private SystemConfig $systemConfig; private IAppDataFactory $appDataFactory; private IURLGenerator $urlGenerator; + private Limiter $limiter; - public function __construct(IClientService $clientService, LoggerInterface $logger, SystemConfig $systemConfig, IAppDataFactory $appDataFactory, IURLGenerator $urlGenerator) { + public function __construct(IClientService $clientService, LoggerInterface $logger, SystemConfig $systemConfig, IAppDataFactory $appDataFactory, IURLGenerator $urlGenerator, Limiter $limiter) { $this->clientService = $clientService; $this->logger = $logger; $this->systemConfig = $systemConfig; $this->appDataFactory = $appDataFactory; $this->urlGenerator = $urlGenerator; + $this->limiter = $limiter; } public function matchReference(string $referenceText): bool { @@ -68,7 +71,7 @@ class LinkReferenceProvider implements IReferenceProvider { return false; } - return (bool)preg_match(self::URL_PATTERN, $referenceText); + return (bool)preg_match(IURLGenerator::URL_REGEX, $referenceText); } public function resolveReference(string $referenceText): ?IReference { @@ -82,6 +85,17 @@ class LinkReferenceProvider implements IReferenceProvider { } private function fetchReference(Reference $reference) { + try { + $user = \OC::$server->getUserSession()->getUser(); + if ($user) { + $this->limiter->registerUserRequest('opengraph', 10, 120, $user); + } else { + $this->limiter->registerAnonRequest('opengraph', 10, 120, \OC::$server->getRequest()->getRemoteAddress()); + } + } catch (RateLimitExceededException $e) { + return; + } + $client = $this->clientService->newClient(); try { $response = $client->get($reference->getId(), [ 'timeout' => 10 ]); @@ -118,12 +132,11 @@ class LinkReferenceProvider implements IReferenceProvider { $contentType = $response->getHeader('Content-Type'); $contentLength = $response->getHeader('Content-Length'); - if (in_array($contentType, self::ALLOWED_CONTENT_TYPES, true) && $contentLength < self::MAX_PREVIEW_SIZE) { $stream = Utils::streamFor($response->getBody()); $bodyStream = new LimitStream($stream, self::MAX_PREVIEW_SIZE, 0); $reference->setImageContentType($contentType); - $folder->newFile(md5($reference->getId()), $bodyStream); + $folder->newFile(md5($reference->getId()), $bodyStream->getContents()); $reference->setImageUrl($this->urlGenerator->linkToRouteAbsolute('core.Reference.preview', ['referenceId' => md5($reference->getId())])); } } catch (\Throwable $e) { diff --git a/lib/private/Collaboration/Reference/Reference.php b/lib/private/Collaboration/Reference/Reference.php index 69ce7fc9597..22dc57782d8 100644 --- a/lib/private/Collaboration/Reference/Reference.php +++ b/lib/private/Collaboration/Reference/Reference.php @@ -53,6 +53,10 @@ class Reference implements IReference { $this->accessible = $accessible; } + public function getAccessible(): bool { + return $this->accessible; + } + public function setTitle(string $title): void { $this->title = $title; } @@ -93,20 +97,20 @@ class Reference implements IReference { return $this->url; } - public function setRichObject(string $type, array $richObject): void { + public function setRichObject(string $type, ?array $richObject): void { $this->richObjectType = $type; $this->richObject = $richObject; } public function getRichObjectType(): string { - if (!$this->richObjectType) { + if ($this->richObjectType === null) { return 'open-graph'; } return $this->richObjectType; } public function getRichObject(): array { - if (!$this->richObject) { + if ($this->richObject === null) { return $this->getOpenGraphObject(); } return $this->richObject; @@ -130,7 +134,7 @@ class Reference implements IReference { 'imageContentType' => $reference->getImageContentType(), 'description' => $reference->getDescription(), 'link' => $reference->getUrl(), - 'accessible' => $reference->accessible, + 'accessible' => $reference->getAccessible(), 'richObjectType' => $reference->getRichObjectType(), 'richObject' => $reference->getRichObject(), ]; diff --git a/lib/private/Collaboration/Reference/ReferenceManager.php b/lib/private/Collaboration/Reference/ReferenceManager.php index 1bd9bfac0b8..471f0efb3be 100644 --- a/lib/private/Collaboration/Reference/ReferenceManager.php +++ b/lib/private/Collaboration/Reference/ReferenceManager.php @@ -30,12 +30,12 @@ use OCP\Collaboration\Reference\IReferenceManager; use OCP\Collaboration\Reference\IReferenceProvider; use OCP\ICache; use OCP\ICacheFactory; +use OCP\IURLGenerator; use Psr\Container\ContainerInterface; +use Psr\Log\LoggerInterface; use Throwable; -use function OCP\Log\logger; class ReferenceManager implements IReferenceManager { - public const URL_PATTERN = '/(\s|\n|^)(https?:\/\/)?((?:[-A-Z0-9+_]+\.)+[-A-Z]+(?:\/[-A-Z0-9+&@#%?=~_|!:,.;()]*)*)(\s|\n|$)/mi'; public const CACHE_TTL = 60; /** @var IReferenceProvider[]|null */ @@ -43,16 +43,19 @@ class ReferenceManager implements IReferenceManager { private ICache $cache; private Coordinator $coordinator; private ContainerInterface $container; + private LinkReferenceProvider $linkReferenceProvider; + private LoggerInterface $logger; - public function __construct(LinkReferenceProvider $linkReferenceProvider, ICacheFactory $cacheFactory, Coordinator $coordinator, ContainerInterface $container) { + public function __construct(LinkReferenceProvider $linkReferenceProvider, ICacheFactory $cacheFactory, Coordinator $coordinator, ContainerInterface $container, LoggerInterface $logger) { $this->linkReferenceProvider = $linkReferenceProvider; $this->cache = $cacheFactory->createDistributed('reference'); $this->coordinator = $coordinator; $this->container = $container; + $this->logger = $logger; } public function extractReferences(string $text): array { - preg_match_all(self::URL_PATTERN, $text, $matches); + preg_match_all(IURLGenerator::URL_REGEX, $text, $matches); $references = $matches[0] ?? []; return array_map(function ($reference) { return trim($reference); @@ -94,6 +97,9 @@ class ReferenceManager implements IReferenceManager { $matchedProvider = null; foreach ($this->getProviders() as $provider) { $matchedProvider = $provider->matchReference($referenceId) ? $provider : null; + if ($matchedProvider !== null) { + break; + } } if ($matchedProvider === null && $this->linkReferenceProvider->matchReference($referenceId)) { @@ -141,7 +147,7 @@ class ReferenceManager implements IReferenceManager { /** @var IReferenceProvider $provider */ $provider = $this->container->get($registration->getService()); } catch (Throwable $e) { - logger()->error('Could not load reference provider ' . $registration->getService() . ': ' . $e->getMessage(), [ + $this->logger->error('Could not load reference provider ' . $registration->getService() . ': ' . $e->getMessage(), [ 'exception' => $e, ]); return null; @@ -150,7 +156,6 @@ class ReferenceManager implements IReferenceManager { return $provider; }, $context->getReferenceProviders())); - // TODO: Move to files app $this->providers[] = $this->container->get(FileReferenceProvider::class); } |