Skip to content
Prev Previous commit
Next Next commit
Cleanup
Signed-off-by: Julius Härtl <[email protected]>
  • Loading branch information
juliusknorr committed Aug 31, 2022
commit a392235e23c3b8af1d0eba4dbac18b18de826a1c
19 changes: 8 additions & 11 deletions core/Controller/ReferenceApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,19 @@
namespace OC\Core\Controller;

use OCP\AppFramework\Http\DataResponse;
use OC\Collaboration\Reference\ReferenceManager;
use OCP\Collaboration\Reference\IReferenceManager;
use OCP\IRequest;

class ReferenceApiController extends \OCP\AppFramework\OCSController {
private ReferenceManager $referenceManager;
private IReferenceManager $referenceManager;

public function __construct($appName, IRequest $request, ReferenceManager $referenceManager) {
public function __construct(string $appName, IRequest $request, IReferenceManager $referenceManager) {
parent::__construct($appName, $request);
$this->referenceManager = $referenceManager;
}

/**
* @NoAdminRequired
*
* @param string $text
* @param bool $resolve
* @return DataResponse
*/
public function extract(string $text, bool $resolve = false, int $limit = 1): DataResponse {
$references = $this->referenceManager->extractReferences($text);
Expand All @@ -63,16 +59,17 @@ public function extract(string $text, bool $resolve = false, int $limit = 1): Da
/**
* @NoAdminRequired
*
* @param array $references
* @return DataResponse
* @param string[] $references
*/
public function resolve(array $references, int $limit = 1): DataResponse {
$result = [];
$index = 0;
foreach ($references as $reference) {
if ($index++ < $limit) {
$result[$reference] = $this->referenceManager->resolveReference($reference);
if ($index++ >= $limit) {
break;
}

$result[$reference] = $this->referenceManager->resolveReference($reference);
}

return new DataResponse([
Expand Down
19 changes: 10 additions & 9 deletions core/Controller/ReferenceController.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,21 @@

namespace OC\Core\Controller;

use OC\Collaboration\Reference\ReferenceManager;
use OCP\Collaboration\Reference\IReferenceManager;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataDownloadResponse;
use OCP\AppFramework\Http\DataResponse;
use OCP\Files\AppData\IAppDataFactory;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\IRequest;

class ReferenceController extends \OCP\AppFramework\Controller {
private ReferenceManager $referenceManager;
class ReferenceController extends Controller {
private IReferenceManager $referenceManager;
private IAppDataFactory $appDataFactory;

public function __construct($appName, IRequest $request, ReferenceManager $referenceManager, IAppDataFactory $appDataFactory) {
public function __construct(string $appName, IRequest $request, IReferenceManager $referenceManager, IAppDataFactory $appDataFactory) {
parent::__construct($appName, $request);
$this->referenceManager = $referenceManager;
$this->appDataFactory = $appDataFactory;
Expand All @@ -44,10 +47,8 @@ public function __construct($appName, IRequest $request, ReferenceManager $refer
/**
* @PublicPage
* @NoCSRFRequired
* @param $referenceId
* @throws \OCP\Files\NotFoundException
*/
public function preview($referenceId) {
public function preview(string $referenceId) {
$reference = $this->referenceManager->getReferenceByCacheKey($referenceId);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get a hit here locally so I don't have any previews. Is there something else needed to configure? Is a Redis required? Or is the method not loading the providers or something?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, would require redis/apcu in its current state. I'd need to think how we can make this work without, as currently we have no reference from the hashed reference that is used for the preview to the original one.

if ($reference === null) {
return new DataResponse('', Http::STATUS_NOT_FOUND);
Expand All @@ -57,9 +58,9 @@ public function preview($referenceId) {
$appData = $this->appDataFactory->get('core');
$folder = $appData->getFolder('opengraph');
$file = $folder->getFile($referenceId);
} catch (NotFoundException $e) {
return new DataDownloadResponse($file->getContent(), $referenceId, $reference->getImageContentType());
} catch (NotFoundException|NotPermittedException $e) {
return new DataResponse('', Http::STATUS_NOT_FOUND);
}
return new DataDownloadResponse($file->getContent(), $referenceId, $reference->getImageContentType());
}
}
2 changes: 2 additions & 0 deletions core/src/OCP/comments.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import $ from 'jquery'
*
* The downside: anything not ascii is excluded. Not sure how common it is in areas using different
* alphabets… the upside: fake domains with similar looking characters won't be formatted as links
*
* This is a copy of the backend regex in IURLGenerator, make sure to adjust both when changing
*/
const urlRegex = /(\s|^)(https?:\/\/)?((?:[-A-Z0-9+_]+\.)+[-A-Z]+(?:\/[-A-Z0-9+&@#%?=~_|!:,.;()]*)*)(\s|$)/ig

Expand Down
2 changes: 1 addition & 1 deletion dist/core-main.js.map

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions lib/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@
'OCP\\Collaboration\\Collaborators\\ISearchPlugin' => $baseDir . '/lib/public/Collaboration/Collaborators/ISearchPlugin.php',
'OCP\\Collaboration\\Collaborators\\ISearchResult' => $baseDir . '/lib/public/Collaboration/Collaborators/ISearchResult.php',
'OCP\\Collaboration\\Collaborators\\SearchResultType' => $baseDir . '/lib/public/Collaboration/Collaborators/SearchResultType.php',
'OCP\\Collaboration\\Reference\\IReference' => $baseDir . '/lib/public/Collaboration/Reference/IReference.php',
'OCP\\Collaboration\\Reference\\IReferenceManager' => $baseDir . '/lib/public/Collaboration/Reference/IReferenceManager.php',
'OCP\\Collaboration\\Reference\\IReferenceProvider' => $baseDir . '/lib/public/Collaboration/Reference/IReferenceProvider.php',
'OCP\\Collaboration\\Resources\\CollectionException' => $baseDir . '/lib/public/Collaboration/Resources/CollectionException.php',
'OCP\\Collaboration\\Resources\\ICollection' => $baseDir . '/lib/public/Collaboration/Resources/ICollection.php',
'OCP\\Collaboration\\Resources\\IManager' => $baseDir . '/lib/public/Collaboration/Resources/IManager.php',
Expand Down Expand Up @@ -823,6 +826,10 @@
'OC\\Collaboration\\Collaborators\\Search' => $baseDir . '/lib/private/Collaboration/Collaborators/Search.php',
'OC\\Collaboration\\Collaborators\\SearchResult' => $baseDir . '/lib/private/Collaboration/Collaborators/SearchResult.php',
'OC\\Collaboration\\Collaborators\\UserPlugin' => $baseDir . '/lib/private/Collaboration/Collaborators/UserPlugin.php',
'OC\\Collaboration\\Reference\\FileReferenceProvider' => $baseDir . '/lib/private/Collaboration/Reference/FileReferenceProvider.php',
'OC\\Collaboration\\Reference\\LinkReferenceProvider' => $baseDir . '/lib/private/Collaboration/Reference/LinkReferenceProvider.php',
'OC\\Collaboration\\Reference\\Reference' => $baseDir . '/lib/private/Collaboration/Reference/Reference.php',
'OC\\Collaboration\\Reference\\ReferenceManager' => $baseDir . '/lib/private/Collaboration/Reference/ReferenceManager.php',
'OC\\Collaboration\\Resources\\Collection' => $baseDir . '/lib/private/Collaboration/Resources/Collection.php',
'OC\\Collaboration\\Resources\\Listener' => $baseDir . '/lib/private/Collaboration/Resources/Listener.php',
'OC\\Collaboration\\Resources\\Manager' => $baseDir . '/lib/private/Collaboration/Resources/Manager.php',
Expand Down Expand Up @@ -975,6 +982,8 @@
'OC\\Core\\Controller\\ProfileApiController' => $baseDir . '/core/Controller/ProfileApiController.php',
'OC\\Core\\Controller\\ProfilePageController' => $baseDir . '/core/Controller/ProfilePageController.php',
'OC\\Core\\Controller\\RecommendedAppsController' => $baseDir . '/core/Controller/RecommendedAppsController.php',
'OC\\Core\\Controller\\ReferenceApiController' => $baseDir . '/core/Controller/ReferenceApiController.php',
'OC\\Core\\Controller\\ReferenceController' => $baseDir . '/core/Controller/ReferenceController.php',
'OC\\Core\\Controller\\SearchController' => $baseDir . '/core/Controller/SearchController.php',
'OC\\Core\\Controller\\SetupController' => $baseDir . '/core/Controller/SetupController.php',
'OC\\Core\\Controller\\TwoFactorChallengeController' => $baseDir . '/core/Controller/TwoFactorChallengeController.php',
Expand Down
9 changes: 9 additions & 0 deletions lib/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Collaboration\\Collaborators\\ISearchPlugin' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Collaborators/ISearchPlugin.php',
'OCP\\Collaboration\\Collaborators\\ISearchResult' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Collaborators/ISearchResult.php',
'OCP\\Collaboration\\Collaborators\\SearchResultType' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Collaborators/SearchResultType.php',
'OCP\\Collaboration\\Reference\\IReference' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Reference/IReference.php',
'OCP\\Collaboration\\Reference\\IReferenceManager' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Reference/IReferenceManager.php',
'OCP\\Collaboration\\Reference\\IReferenceProvider' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Reference/IReferenceProvider.php',
'OCP\\Collaboration\\Resources\\CollectionException' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Resources/CollectionException.php',
'OCP\\Collaboration\\Resources\\ICollection' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Resources/ICollection.php',
'OCP\\Collaboration\\Resources\\IManager' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Resources/IManager.php',
Expand Down Expand Up @@ -856,6 +859,10 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Collaboration\\Collaborators\\Search' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/Search.php',
'OC\\Collaboration\\Collaborators\\SearchResult' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/SearchResult.php',
'OC\\Collaboration\\Collaborators\\UserPlugin' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/UserPlugin.php',
'OC\\Collaboration\\Reference\\FileReferenceProvider' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Reference/FileReferenceProvider.php',
'OC\\Collaboration\\Reference\\LinkReferenceProvider' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Reference/LinkReferenceProvider.php',
'OC\\Collaboration\\Reference\\Reference' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Reference/Reference.php',
'OC\\Collaboration\\Reference\\ReferenceManager' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Reference/ReferenceManager.php',
'OC\\Collaboration\\Resources\\Collection' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Resources/Collection.php',
'OC\\Collaboration\\Resources\\Listener' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Resources/Listener.php',
'OC\\Collaboration\\Resources\\Manager' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Resources/Manager.php',
Expand Down Expand Up @@ -1008,6 +1015,8 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Core\\Controller\\ProfileApiController' => __DIR__ . '/../../..' . '/core/Controller/ProfileApiController.php',
'OC\\Core\\Controller\\ProfilePageController' => __DIR__ . '/../../..' . '/core/Controller/ProfilePageController.php',
'OC\\Core\\Controller\\RecommendedAppsController' => __DIR__ . '/../../..' . '/core/Controller/RecommendedAppsController.php',
'OC\\Core\\Controller\\ReferenceApiController' => __DIR__ . '/../../..' . '/core/Controller/ReferenceApiController.php',
'OC\\Core\\Controller\\ReferenceController' => __DIR__ . '/../../..' . '/core/Controller/ReferenceController.php',
'OC\\Core\\Controller\\SearchController' => __DIR__ . '/../../..' . '/core/Controller/SearchController.php',
'OC\\Core\\Controller\\SetupController' => __DIR__ . '/../../..' . '/core/Controller/SetupController.php',
'OC\\Core\\Controller\\TwoFactorChallengeController' => __DIR__ . '/../../..' . '/core/Controller/TwoFactorChallengeController.php',
Expand Down
62 changes: 36 additions & 26 deletions lib/private/Collaboration/Reference/FileReferenceProvider.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php

declare(strict_types=1);
/**
* @copyright Copyright (c) 2022 Julius Härtl <[email protected]>
*
Expand All @@ -22,23 +24,29 @@

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;

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 {
Expand All @@ -52,6 +60,7 @@ public function resolveReference(string $referenceText): ?IReference {
try {
$this->fetchReference($reference);
} catch (NotFoundException $e) {
$reference->setRichObject('file', null);
$reference->setAccessible(false);
}
return $reference;
Expand All @@ -61,10 +70,7 @@ public function resolveReference(string $referenceText): ?IReference {
}

/**
* @throws \OCP\Files\NotPermittedException
* @throws \OCP\Files\InvalidPathException
* @throws NotFoundException
* @throws \OC\User\NoUserException
*/
private function fetchReference(Reference $reference) {
if ($this->userId === null) {
Expand All @@ -74,37 +80,41 @@ private function fetchReference(Reference $reference) {
$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 {
return false;
}

public function getCacheKey(string $referenceId): string {
return $this->userId;
return $this->userId ?? '';
}
}
23 changes: 18 additions & 5 deletions lib/private/Collaboration/Reference/LinkReferenceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
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;
Expand All @@ -37,7 +39,6 @@
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 = [
Expand All @@ -54,21 +55,23 @@ 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 {
if ($this->systemConfig->getValue('reference_opengraph', true) !== true) {
return false;
}

return (bool)preg_match(self::URL_PATTERN, $referenceText);
return (bool)preg_match(IURLGenerator::URL_REGEX, $referenceText);
}

public function resolveReference(string $referenceText): ?IReference {
Expand All @@ -82,6 +85,17 @@ public function resolveReference(string $referenceText): ?IReference {
}

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 ]);
Expand Down Expand Up @@ -118,12 +132,11 @@ private function fetchReference(Reference $reference) {
$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) {
Expand Down
Loading