diff options
Diffstat (limited to 'lib/public/Collaboration/Reference')
4 files changed, 77 insertions, 17 deletions
diff --git a/lib/public/Collaboration/Reference/IPublicReferenceProvider.php b/lib/public/Collaboration/Reference/IPublicReferenceProvider.php new file mode 100644 index 00000000000..db6c3d3828b --- /dev/null +++ b/lib/public/Collaboration/Reference/IPublicReferenceProvider.php @@ -0,0 +1,33 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\Collaboration\Reference; + +/** + * @since 30.0.0 + */ +interface IPublicReferenceProvider extends IReferenceProvider { + /** + * Return a reference with its metadata for a given reference identifier and sharingToken + * + * @since 30.0.0 + */ + public function resolveReferencePublic(string $referenceText, string $sharingToken): ?IReference; + + /** + * Return a custom cache key to be used for caching the metadata + * This could be for example the current sharingToken if the reference + * access permissions are different for each share + * + * Should return null, if the cache is only related to the + * reference id and has no further dependency + * + * @since 30.0.0 + */ + public function getCacheKeyPublic(string $referenceId, string $sharingToken): ?string; +} diff --git a/lib/public/Collaboration/Reference/IReferenceManager.php b/lib/public/Collaboration/Reference/IReferenceManager.php index 4a7de266435..c3cf7ca8e7b 100644 --- a/lib/public/Collaboration/Reference/IReferenceManager.php +++ b/lib/public/Collaboration/Reference/IReferenceManager.php @@ -27,8 +27,9 @@ interface IReferenceManager { * but may still return null in case this is disabled or the fetching fails * * @since 25.0.0 + * @since 30.0.0 optional arguments `$public` and `$sharingToken` */ - public function resolveReference(string $referenceId): ?IReference; + public function resolveReference(string $referenceId, bool $public = false, string $sharingToken = ''): ?IReference; /** * Get a reference by its cache key @@ -42,8 +43,9 @@ interface IReferenceManager { * the cache can then be filled with a separate request from the frontend * * @since 25.0.0 + * @since 30.0.0 optional arguments `$public` and `$sharingToken` */ - public function getReferenceFromCache(string $referenceId): ?IReference; + public function getReferenceFromCache(string $referenceId, bool $public = false, string $sharingToken = ''): ?IReference; /** * Invalidate all cache entries with a prefix or just one if the cache key is provided diff --git a/lib/public/Collaboration/Reference/LinkReferenceProvider.php b/lib/public/Collaboration/Reference/LinkReferenceProvider.php index 79b5164950c..65bdcecb577 100644 --- a/lib/public/Collaboration/Reference/LinkReferenceProvider.php +++ b/lib/public/Collaboration/Reference/LinkReferenceProvider.php @@ -9,7 +9,6 @@ declare(strict_types=1); namespace OCP\Collaboration\Reference; use Fusonic\OpenGraph\Consumer; -use GuzzleHttp\Exception\GuzzleException; use GuzzleHttp\Psr7\LimitStream; use GuzzleHttp\Psr7\Utils; use OC\Security\RateLimiting\Exception\RateLimitExceededException; @@ -26,7 +25,7 @@ use Psr\Log\LoggerInterface; /** * @since 29.0.0 */ -class LinkReferenceProvider implements IReferenceProvider { +class LinkReferenceProvider implements IReferenceProvider, IPublicReferenceProvider { /** * for image size and webpage header @@ -88,6 +87,14 @@ class LinkReferenceProvider implements IReferenceProvider { } /** + * @inheritDoc + * @since 30.0.0 + */ + public function resolveReferencePublic(string $referenceText, string $sharingToken): ?IReference { + return $this->resolveReference($referenceText); + } + + /** * Populates the reference with OpenGraph data * * @param Reference $reference @@ -107,15 +114,15 @@ class LinkReferenceProvider implements IReferenceProvider { $client = $this->clientService->newClient(); try { - $headResponse = $client->head($reference->getId(), [ 'timeout' => 10 ]); + $headResponse = $client->head($reference->getId(), [ 'timeout' => 3 ]); } catch (\Exception $e) { $this->logger->debug('Failed to perform HEAD request to get target metadata', ['exception' => $e]); return; } $linkContentLength = $headResponse->getHeader('Content-Length'); - if (is_numeric($linkContentLength) && (int) $linkContentLength > self::MAX_CONTENT_LENGTH) { - $this->logger->debug('Skip resolving links pointing to content length > 5 MiB'); + if (is_numeric($linkContentLength) && (int)$linkContentLength > self::MAX_CONTENT_LENGTH) { + $this->logger->debug('[Head] Skip resolving links pointing to content length > 5 MiB'); return; } @@ -129,18 +136,28 @@ class LinkReferenceProvider implements IReferenceProvider { } try { - $response = $client->get($reference->getId(), [ 'timeout' => 10 ]); + $response = $client->get($reference->getId(), [ 'timeout' => 3, 'stream' => true ]); } catch (\Exception $e) { $this->logger->debug('Failed to fetch link for obtaining open graph data', ['exception' => $e]); return; } - $responseBody = (string)$response->getBody(); + $body = $response->getBody(); + if (is_resource($body)) { + $responseContent = fread($body, self::MAX_CONTENT_LENGTH); + if (!feof($body)) { + $this->logger->debug('[Get] Skip resolving links pointing to content length > 5 MiB'); + return; + } + } else { + $this->logger->error('[Get] Impossible to check content length'); + return; + } // OpenGraph handling $consumer = new Consumer(); $consumer->useFallbackMode = true; - $object = $consumer->loadHtml($responseBody); + $object = $consumer->loadHtml($responseContent); $reference->setUrl($reference->getId()); @@ -167,7 +184,7 @@ class LinkReferenceProvider implements IReferenceProvider { $folder = $appData->newFolder('opengraph'); } - $response = $client->get($object->images[0]->url, ['timeout' => 10]); + $response = $client->get($object->images[0]->url, ['timeout' => 3]); $contentType = $response->getHeader('Content-Type'); $contentLength = $response->getHeader('Content-Length'); @@ -178,10 +195,8 @@ class LinkReferenceProvider implements IReferenceProvider { $folder->newFile(md5($reference->getId()), $bodyStream->getContents()); $reference->setImageUrl($this->urlGenerator->linkToRouteAbsolute('core.Reference.preview', ['referenceId' => md5($reference->getId())])); } - } catch (GuzzleException $e) { - $this->logger->info('Failed to fetch and store the open graph image for ' . $reference->getId(), ['exception' => $e]); - } catch (\Throwable $e) { - $this->logger->error('Failed to fetch and store the open graph image for ' . $reference->getId(), ['exception' => $e]); + } catch (\Exception $e) { + $this->logger->debug('Failed to fetch and store the open graph image for ' . $reference->getId(), ['exception' => $e]); } } } @@ -201,4 +216,12 @@ class LinkReferenceProvider implements IReferenceProvider { public function getCacheKey(string $referenceId): ?string { return null; } + + /** + * @inheritDoc + * @since 30.0.0 + */ + public function getCacheKeyPublic(string $referenceId, string $sharingToken): ?string { + return null; + } } diff --git a/lib/public/Collaboration/Reference/RenderReferenceEvent.php b/lib/public/Collaboration/Reference/RenderReferenceEvent.php index 09778a20d2a..692098dbf60 100644 --- a/lib/public/Collaboration/Reference/RenderReferenceEvent.php +++ b/lib/public/Collaboration/Reference/RenderReferenceEvent.php @@ -11,8 +11,10 @@ namespace OCP\Collaboration\Reference; use OCP\EventDispatcher\Event; /** - * Event that apps can emit on their page rendering to trigger loading of aditional - * scripts for reference widget rendering + * Event emitted when apps might render references like link previews or smart picker widgets. + * + * This can be used to inject scripts for extending that. + * Further details can be found in the :ref:`Reference providers` deep dive. * * @since 25.0.0 */ |