diff options
Diffstat (limited to 'apps/dav/lib/Direct')
-rw-r--r-- | apps/dav/lib/Direct/DirectFile.php | 100 | ||||
-rw-r--r-- | apps/dav/lib/Direct/DirectHome.php | 85 | ||||
-rw-r--r-- | apps/dav/lib/Direct/Server.php | 17 | ||||
-rw-r--r-- | apps/dav/lib/Direct/ServerFactory.php | 51 |
4 files changed, 253 insertions, 0 deletions
diff --git a/apps/dav/lib/Direct/DirectFile.php b/apps/dav/lib/Direct/DirectFile.php new file mode 100644 index 00000000000..7f41dd65f41 --- /dev/null +++ b/apps/dav/lib/Direct/DirectFile.php @@ -0,0 +1,100 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCA\DAV\Direct; + +use OCA\DAV\Db\Direct; +use OCA\DAV\Events\BeforeFileDirectDownloadedEvent; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\File; +use OCP\Files\IRootFolder; +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\IFile; + +class DirectFile implements IFile { + /** @var File */ + private $file; + + public function __construct( + private Direct $direct, + private IRootFolder $rootFolder, + private IEventDispatcher $eventDispatcher, + ) { + } + + public function put($data) { + throw new Forbidden(); + } + + public function get() { + $this->getFile(); + + $this->eventDispatcher->dispatchTyped(new BeforeFileDirectDownloadedEvent($this->file)); + + return $this->file->fopen('rb'); + } + + public function getContentType() { + $this->getFile(); + + return $this->file->getMimeType(); + } + + public function getETag() { + $this->getFile(); + + return $this->file->getEtag(); + } + + /** + * @psalm-suppress ImplementedReturnTypeMismatch \Sabre\DAV\IFile::getSize signature does not support 32bit + * @return int|float + */ + public function getSize() { + $this->getFile(); + + return $this->file->getSize(); + } + + public function delete() { + throw new Forbidden(); + } + + public function getName() { + return $this->direct->getToken(); + } + + public function setName($name) { + throw new Forbidden(); + } + + public function getLastModified() { + $this->getFile(); + + return $this->file->getMTime(); + } + + private function getFile() { + if ($this->file === null) { + $userFolder = $this->rootFolder->getUserFolder($this->direct->getUserId()); + $file = $userFolder->getFirstNodeById($this->direct->getFileId()); + + if (!$file) { + throw new NotFound(); + } + if (!$file instanceof File) { + throw new Forbidden('direct download not allowed on directories'); + } + + $this->file = $file; + } + + return $this->file; + } +} diff --git a/apps/dav/lib/Direct/DirectHome.php b/apps/dav/lib/Direct/DirectHome.php new file mode 100644 index 00000000000..ac411c9b52f --- /dev/null +++ b/apps/dav/lib/Direct/DirectHome.php @@ -0,0 +1,85 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCA\DAV\Direct; + +use OCA\DAV\Db\DirectMapper; +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\IRootFolder; +use OCP\IRequest; +use OCP\Security\Bruteforce\IThrottler; +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\Exception\MethodNotAllowed; +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\ICollection; + +class DirectHome implements ICollection { + + public function __construct( + private IRootFolder $rootFolder, + private DirectMapper $mapper, + private ITimeFactory $timeFactory, + private IThrottler $throttler, + private IRequest $request, + private IEventDispatcher $eventDispatcher, + ) { + } + + public function createFile($name, $data = null) { + throw new Forbidden(); + } + + public function createDirectory($name) { + throw new Forbidden(); + } + + public function getChild($name): DirectFile { + try { + $direct = $this->mapper->getByToken($name); + + // Expired + if ($direct->getExpiration() < $this->timeFactory->getTime()) { + throw new NotFound(); + } + + return new DirectFile($direct, $this->rootFolder, $this->eventDispatcher); + } catch (DoesNotExistException $e) { + // Since the token space is so huge only throttle on non-existing token + $this->throttler->registerAttempt('directlink', $this->request->getRemoteAddress()); + $this->throttler->sleepDelayOrThrowOnMax($this->request->getRemoteAddress(), 'directlink'); + + throw new NotFound(); + } + } + + public function getChildren() { + throw new MethodNotAllowed('Listing members of this collection is disabled'); + } + + public function childExists($name): bool { + return false; + } + + public function delete() { + throw new Forbidden(); + } + + public function getName(): string { + return 'direct'; + } + + public function setName($name) { + throw new Forbidden(); + } + + public function getLastModified(): int { + return 0; + } +} diff --git a/apps/dav/lib/Direct/Server.php b/apps/dav/lib/Direct/Server.php new file mode 100644 index 00000000000..957f6f99b34 --- /dev/null +++ b/apps/dav/lib/Direct/Server.php @@ -0,0 +1,17 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCA\DAV\Direct; + +class Server extends \Sabre\DAV\Server { + public function __construct($treeOrNode = null) { + parent::__construct($treeOrNode); + self::$exposeVersion = false; + $this->enablePropfindDepthInfinityf = false; + } +} diff --git a/apps/dav/lib/Direct/ServerFactory.php b/apps/dav/lib/Direct/ServerFactory.php new file mode 100644 index 00000000000..473439361c2 --- /dev/null +++ b/apps/dav/lib/Direct/ServerFactory.php @@ -0,0 +1,51 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCA\DAV\Direct; + +use OCA\DAV\Connector\Sabre\MaintenancePlugin; +use OCA\DAV\Db\DirectMapper; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\IRootFolder; +use OCP\IConfig; +use OCP\IL10N; +use OCP\IRequest; +use OCP\L10N\IFactory; +use OCP\Security\Bruteforce\IThrottler; + +class ServerFactory { + /** @var IL10N */ + private $l10n; + + public function __construct( + private IConfig $config, + IFactory $l10nFactory, + private IEventDispatcher $eventDispatcher, + ) { + $this->l10n = $l10nFactory->get('dav'); + } + + public function createServer(string $baseURI, + string $requestURI, + IRootFolder $rootFolder, + DirectMapper $mapper, + ITimeFactory $timeFactory, + IThrottler $throttler, + IRequest $request): Server { + $home = new DirectHome($rootFolder, $mapper, $timeFactory, $throttler, $request, $this->eventDispatcher); + $server = new Server($home); + + $server->httpRequest->setUrl($requestURI); + $server->setBaseUri($baseURI); + + $server->addPlugin(new MaintenancePlugin($this->config, $this->l10n)); + + return $server; + } +} |