Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 46 additions & 18 deletions apps/files_sharing/lib/Controller/ShareController.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use OCA\Files_Sharing\Event\ShareLinkAccessedEvent;
use OCP\Accounts\IAccountManager;
use OCP\AppFramework\AuthPublicShareController;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
use OCP\AppFramework\Http\Attribute\OpenAPI;
use OCP\AppFramework\Http\Attribute\PublicPage;
Expand All @@ -29,6 +30,7 @@
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\HintException;
use OCP\IConfig;
use OCP\IL10N;
Expand Down Expand Up @@ -360,49 +362,75 @@
$share = $this->shareManager->getShareByToken($token);

if (!($share->getPermissions() & Constants::PERMISSION_READ)) {
return new DataResponse('Share has no read permission');
return new DataResponse('Share has no read permission', Http::STATUS_FORBIDDEN);
}

$attributes = $share->getAttributes();
if ($attributes?->getAttribute('permissions', 'download') === false) {
return new DataResponse('Share has no download permission');
return new DataResponse('Share has no download permission', Http::STATUS_FORBIDDEN);
}

if (!$this->validateShare($share)) {
throw new NotFoundException();
}

if ($share->getHideDownload()) {
// download API does not work if hidden - use the DAV endpoint for previews
throw new NotFoundException();
}

$node = $share->getNode();
if ($node instanceof Folder) {
// Directory share
if ($path !== '') {
if (!$node instanceof Folder) {
return new NotFoundResponse();
}

// Try to get the path
if ($path !== '') {
try {
$node = $node->get($path);
} catch (NotFoundException|NotPermittedException) {
$this->emitAccessShareHook($share, 404, 'Share not found');
$this->emitShareAccessEvent($share, self::SHARE_DOWNLOAD, 404, 'Share not found');
return new NotFoundResponse();
}
}

if ($files !== null) {
if (!$node instanceof Folder) {
return new NotFoundResponse();
}

$filesParam = json_decode($files, true);
if (!is_array($filesParam)) {
try {
$node = $node->get($path);
} catch (NotFoundException $e) {
// legacy wise this allows also passing the filename
$node = $node->get($files);
$files = null;
} catch (NotFoundException|NotPermittedException) {
$this->emitAccessShareHook($share, 404, 'Share not found');
$this->emitShareAccessEvent($share, self::SHARE_DOWNLOAD, 404, 'Share not found');
return new NotFoundResponse();
}
}

if ($node instanceof Folder) {
if ($files === null || $files === '') {
if ($share->getHideDownload()) {
throw new NotFoundException('Downloading a folder');
}
}
}
}

$this->emitAccessShareHook($share);

Check failure on line 416 in apps/files_sharing/lib/Controller/ShareController.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

DeprecatedMethod

apps/files_sharing/lib/Controller/ShareController.php:416:10: DeprecatedMethod: The method OCA\Files_Sharing\Controller\ShareController::emitAccessShareHook has been marked as deprecated (see https://psalm.dev/001)
$this->emitShareAccessEvent($share, self::SHARE_DOWNLOAD);

$davUrl = '/public.php/dav/files/' . $token . '/?accept=zip';
$davPath = '';
if ($node !== $share->getNode()) {
$davPath = substr($node->getPath(), strlen($share->getNode()->getPath()));
}

$params = [];
if ($files !== null) {
$davUrl .= '&files=' . $files;
$params['files'] = $files;
}
if ($node instanceof Folder) {
$params['accept'] = 'zip';
}

$davUrl = '/public.php/dav/files/' . $token . $davPath;
$davUrl .= '?' . http_build_query($params);
return new RedirectResponse($this->urlGenerator->getAbsoluteURL($davUrl));
}
}
9 changes: 6 additions & 3 deletions apps/files_sharing/tests/Controller/ShareControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use OCP\Accounts\IAccountManager;
use OCP\Accounts\IAccountProperty;
use OCP\Activity\IManager;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\ContentSecurityPolicy;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\Template\ExternalShareMenuAction;
Expand Down Expand Up @@ -691,7 +692,9 @@ public function testShowShareInvalid(): void {
->with('token')
->willReturn($share);

$this->userManager->method('get')->with('ownerUID')->willReturn($owner);
$this->userManager->method('get')
->with('ownerUID')
->willReturn($owner);

$this->shareController->showShare();
}
Expand All @@ -712,7 +715,7 @@ public function testDownloadShareWithCreateOnlyShare(): void {

// Test with a password protected share and no authentication
$response = $this->shareController->downloadShare('validtoken');
$expectedResponse = new DataResponse('Share has no read permission');
$expectedResponse = new DataResponse('Share has no read permission', Http::STATUS_FORBIDDEN);
$this->assertEquals($expectedResponse, $response);
}

Expand Down Expand Up @@ -740,7 +743,7 @@ public function testDownloadShareWithoutDownloadPermission(): void {

// Test with a password protected share and no authentication
$response = $this->shareController->downloadShare('validtoken');
$expectedResponse = new DataResponse('Share has no download permission');
$expectedResponse = new DataResponse('Share has no download permission', Http::STATUS_FORBIDDEN);
$this->assertEquals($expectedResponse, $response);
}

Expand Down
Loading