mirror of
https://github.com/nextcloud/server.git
synced 2025-02-12 03:59:16 +00:00
![Ferdinand Thiessen](/assets/img/avatar_default.png)
Previously there was a different behavior for public shares (link-shares) and internal shares, if the user disabled the view permission. The legacy UI for public shares simply "disabled" the context menu and hided all download actions. With Nextcloud 31 all share types use the consistent permissions attributes, which simplifies code, but caused a regression: Images can no longer been viewed. Because on 30 and before the attribute was not set, previews for view-only files were still allowed. Now with 31 we need a new way to allow "viewing" shares. So this is allowing previews for those files, but only for internal usage. This is done by settin a special header, which only works with custom requests, and not by opening the URL directly. Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
98 lines
2.3 KiB
PHP
98 lines
2.3 KiB
PHP
<?php
|
|
/**
|
|
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
|
|
* SPDX-FileCopyrightText: 2019 ownCloud GmbH
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
*/
|
|
|
|
namespace OCA\Files_Sharing;
|
|
|
|
use OCP\Files\File;
|
|
use OCP\Files\Folder;
|
|
use OCP\Files\Node;
|
|
use OCP\Files\NotFoundException;
|
|
|
|
/**
|
|
* Handles restricting for download of files
|
|
*/
|
|
class ViewOnly {
|
|
|
|
public function __construct(
|
|
private Folder $userFolder,
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* @param string[] $pathsToCheck
|
|
* @return bool
|
|
*/
|
|
public function check(array $pathsToCheck): bool {
|
|
// If any of elements cannot be downloaded, prevent whole download
|
|
foreach ($pathsToCheck as $file) {
|
|
try {
|
|
$info = $this->userFolder->get($file);
|
|
if ($info instanceof File) {
|
|
// access to filecache is expensive in the loop
|
|
if (!$this->checkFileInfo($info)) {
|
|
return false;
|
|
}
|
|
} elseif ($info instanceof Folder) {
|
|
// get directory content is rather cheap query
|
|
if (!$this->dirRecursiveCheck($info)) {
|
|
return false;
|
|
}
|
|
}
|
|
} catch (NotFoundException $e) {
|
|
continue;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @param Folder $dirInfo
|
|
* @return bool
|
|
* @throws NotFoundException
|
|
*/
|
|
private function dirRecursiveCheck(Folder $dirInfo): bool {
|
|
if (!$this->checkFileInfo($dirInfo)) {
|
|
return false;
|
|
}
|
|
// If any of elements cannot be downloaded, prevent whole download
|
|
$files = $dirInfo->getDirectoryListing();
|
|
foreach ($files as $file) {
|
|
if ($file instanceof File) {
|
|
if (!$this->checkFileInfo($file)) {
|
|
return false;
|
|
}
|
|
} elseif ($file instanceof Folder) {
|
|
return $this->dirRecursiveCheck($file);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @param Node $fileInfo
|
|
* @return bool
|
|
* @throws NotFoundException
|
|
*/
|
|
private function checkFileInfo(Node $fileInfo): bool {
|
|
// Restrict view-only to nodes which are shared
|
|
$storage = $fileInfo->getStorage();
|
|
if (!$storage->instanceOfStorage(SharedStorage::class)) {
|
|
return true;
|
|
}
|
|
|
|
// Extract extra permissions
|
|
/** @var SharedStorage $storage */
|
|
$share = $storage->getShare();
|
|
|
|
// Check whether download-permission was denied (granted if not set)
|
|
$attributes = $share->getAttributes();
|
|
$canDownload = $attributes?->getAttribute('permissions', 'download');
|
|
|
|
return $canDownload !== false;
|
|
}
|
|
}
|