From fe8571c6c53561649a2111e7a4b8b9453e3a37f6 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Thu, 7 Nov 2024 12:21:35 +0530 Subject: [PATCH 01/23] Hide folder from search result --- lib/Filesystem/CacheWrapper.php | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index da6e3253..374c63da 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -13,6 +13,8 @@ use OCP\Files\Search\ISearchQuery; class CacheWrapper extends Wrapper { + private string $excludedFolder = 'restricted-folder'; + public function __construct( ICache $cache ) { @@ -47,11 +49,23 @@ class CacheWrapper extends Wrapper { throw new \Exception('User data cache removal is disabled.'); } + // Exclude specific folder and its files from search results public function searchQuery(ISearchQuery $searchQuery) { - return []; + $results = parent::searchQuery($searchQuery); + return array_filter($results, function($entry) { + return !$this->isExcludedPath($entry['path']); + }); } public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry { - return null; + if ($this->isExcludedPath($rawEntry->getPath())) { + return null; + } + return parent::getCacheEntryFromSearchResult($rawEntry); + } + + // Check if a path is within the excluded folder + private function isExcludedPath(string $path): bool { + return strpos($path, $this->excludedFolder) === 0; } } -- GitLab From cb64dd7b46328c6d90ca8e015925be5b85de0ef1 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Thu, 7 Nov 2024 12:50:20 +0530 Subject: [PATCH 02/23] fix lint --- lib/Filesystem/CacheWrapper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index 374c63da..b16bd82c 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -52,7 +52,7 @@ class CacheWrapper extends Wrapper { // Exclude specific folder and its files from search results public function searchQuery(ISearchQuery $searchQuery) { $results = parent::searchQuery($searchQuery); - return array_filter($results, function($entry) { + return array_filter($results, function ($entry) { return !$this->isExcludedPath($entry['path']); }); } -- GitLab From 1bbb8d9e0d8b4a3f8fc8b186a06cdbc75d9bfd74 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Thu, 7 Nov 2024 14:32:16 +0530 Subject: [PATCH 03/23] bloced restricted folder and its content from search --- lib/Filesystem/CacheWrapper.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index b16bd82c..9ca12351 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -13,7 +13,7 @@ use OCP\Files\Search\ISearchQuery; class CacheWrapper extends Wrapper { - private string $excludedFolder = 'restricted-folder'; + private string $excludedFolder = 'files/restricted-folder'; public function __construct( ICache $cache @@ -53,7 +53,7 @@ class CacheWrapper extends Wrapper { public function searchQuery(ISearchQuery $searchQuery) { $results = parent::searchQuery($searchQuery); return array_filter($results, function ($entry) { - return !$this->isExcludedPath($entry['path']); + return isset($entry['path']) && !$this->isExcludedPath($entry['path']); }); } -- GitLab From 9f3eaccf0b0b65b014575bd4bad80de3970f37a1 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Wed, 27 Nov 2024 11:25:51 +0530 Subject: [PATCH 04/23] added check for storage wrapper recovery folder --- lib/Filesystem/CacheWrapper.php | 2 +- lib/Filesystem/StorageWrapper.php | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index 9ca12351..df145740 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -13,7 +13,7 @@ use OCP\Files\Search\ISearchQuery; class CacheWrapper extends Wrapper { - private string $excludedFolder = 'files/restricted-folder'; + private string $excludedFolder = 'files/Recovery'; public function __construct( ICache $cache diff --git a/lib/Filesystem/StorageWrapper.php b/lib/Filesystem/StorageWrapper.php index f35a5510..2dc3262d 100644 --- a/lib/Filesystem/StorageWrapper.php +++ b/lib/Filesystem/StorageWrapper.php @@ -12,6 +12,7 @@ use OCP\Files\Storage\IStorage; use OCP\Files\Storage\IWriteStreamStorage; class StorageWrapper extends Wrapper implements IWriteStreamStorage { + private const RECOVERY_FOLDER = 'files/Recovery'; /** * @param array $parameters */ @@ -23,7 +24,20 @@ class StorageWrapper extends Wrapper implements IWriteStreamStorage { * @throws ForbiddenException */ protected function checkFileAccess(string $path, bool $isDir = false): void { - throw new ForbiddenException('Access denied', false); + if ($this->isRecoveryFolder($path)) { + throw new ForbiddenException('Access denied to the Recovery folder', false); + } + } + + /** + * Check if the path refers to the "Recovery" folder. + * + * @param string $path + * @return bool + */ + private function isRecoveryFolder(string $path): bool { + + return strpos($path, '/' . self::RECOVERY_FOLDER) !== false; } /* -- GitLab From 3695622239a3bbae9f069dc8798c445f420e7a50 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Wed, 27 Nov 2024 15:35:47 +0530 Subject: [PATCH 05/23] add check for recovery --- lib/Filesystem/StorageWrapper.php | 40 ++++++++++++------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/lib/Filesystem/StorageWrapper.php b/lib/Filesystem/StorageWrapper.php index 2dc3262d..73a7f87c 100644 --- a/lib/Filesystem/StorageWrapper.php +++ b/lib/Filesystem/StorageWrapper.php @@ -73,11 +73,9 @@ class StorageWrapper extends Wrapper implements IWriteStreamStorage { * @return bool */ public function isCreatable($path) { - try { - $this->checkFileAccess($path); - } catch (ForbiddenException $e) { - return false; - } + + $this->checkFileAccess($path); + } /** @@ -87,11 +85,9 @@ class StorageWrapper extends Wrapper implements IWriteStreamStorage { * @return bool */ public function isReadable($path) { - try { - $this->checkFileAccess($path); - } catch (ForbiddenException $e) { - return false; - } + + $this->checkFileAccess($path); + } /** @@ -101,11 +97,9 @@ class StorageWrapper extends Wrapper implements IWriteStreamStorage { * @return bool */ public function isUpdatable($path) { - try { - $this->checkFileAccess($path); - } catch (ForbiddenException $e) { - return false; - } + + $this->checkFileAccess($path); + } /** @@ -115,19 +109,15 @@ class StorageWrapper extends Wrapper implements IWriteStreamStorage { * @return bool */ public function isDeletable($path) { - try { - $this->checkFileAccess($path); - } catch (ForbiddenException $e) { - return false; - } + + $this->checkFileAccess($path); + } public function getPermissions($path) { - try { - $this->checkFileAccess($path); - } catch (ForbiddenException $e) { - return $this->mask; - } + + $this->checkFileAccess($path); + } /** -- GitLab From db6e02762156234be1f832fc5530814047c68884 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Wed, 27 Nov 2024 16:19:44 +0530 Subject: [PATCH 06/23] add check for recovery --- lib/Filesystem/StorageWrapper.php | 428 ++++++++++++------------------ 1 file changed, 176 insertions(+), 252 deletions(-) diff --git a/lib/Filesystem/StorageWrapper.php b/lib/Filesystem/StorageWrapper.php index 73a7f87c..db25b23a 100644 --- a/lib/Filesystem/StorageWrapper.php +++ b/lib/Filesystem/StorageWrapper.php @@ -1,264 +1,188 @@ -isRecoveryFolder($path)) { - throw new ForbiddenException('Access denied to the Recovery folder', false); - } - } - - /** - * Check if the path refers to the "Recovery" folder. - * - * @param string $path - * @return bool - */ - private function isRecoveryFolder(string $path): bool { - - return strpos($path, '/' . self::RECOVERY_FOLDER) !== false; - } - - /* - * Storage wrapper methods - */ - - /** - * see http://php.net/manual/en/function.mkdir.php - * - * @param string $path - * @return bool - * @throws ForbiddenException - */ - public function mkdir($path) { - $this->checkFileAccess($path, true); - } - - /** - * see http://php.net/manual/en/function.rmdir.php - * - * @param string $path - * @return bool - * @throws ForbiddenException - */ - public function rmdir($path) { - $this->checkFileAccess($path, true); - } - - /** - * check if a file can be created in $path - * - * @param string $path - * @return bool - */ - public function isCreatable($path) { - - $this->checkFileAccess($path); - - } - - /** - * check if a file can be read - * - * @param string $path - * @return bool - */ - public function isReadable($path) { - - $this->checkFileAccess($path); - - } - - /** - * check if a file can be written to - * - * @param string $path - * @return bool - */ - public function isUpdatable($path) { - - $this->checkFileAccess($path); - - } - - /** - * check if a file can be deleted - * - * @param string $path - * @return bool - */ - public function isDeletable($path) { - - $this->checkFileAccess($path); - - } - - public function getPermissions($path) { - - $this->checkFileAccess($path); - - } - - /** - * see http://php.net/manual/en/function.file_get_contents.php - * - * @param string $path - * @return string - * @throws ForbiddenException - */ - public function file_get_contents($path) { - $this->checkFileAccess($path); - } - - /** - * see http://php.net/manual/en/function.file_put_contents.php - * - * @param string $path - * @param string $data - * @return bool - * @throws ForbiddenException - */ - public function file_put_contents($path, $data) { - $this->checkFileAccess($path); - } - - /** - * see http://php.net/manual/en/function.unlink.php - * - * @param string $path - * @return bool - * @throws ForbiddenException - */ - public function unlink($path) { - $this->checkFileAccess($path); - } - - /** - * see http://php.net/manual/en/function.rename.php - * - * @param string $path1 - * @param string $path2 - * @return bool - * @throws ForbiddenException - */ - public function rename($path1, $path2) { - $this->checkFileAccess($path1); - $this->checkFileAccess($path2); - } - - /** - * see http://php.net/manual/en/function.copy.php - * - * @param string $path1 - * @param string $path2 - * @return bool - * @throws ForbiddenException - */ - public function copy($path1, $path2) { - $this->checkFileAccess($path1); - $this->checkFileAccess($path2); - } - - /** - * see http://php.net/manual/en/function.fopen.php - * - * @param string $path - * @param string $mode - * @return resource - * @throws ForbiddenException - */ - public function fopen($path, $mode) { - $this->checkFileAccess($path); - } - - /** - * see http://php.net/manual/en/function.touch.php - * If the backend does not support the operation, false should be returned - * - * @param string $path - * @param int $mtime - * @return bool - * @throws ForbiddenException - */ - public function touch($path, $mtime = null) { - $this->checkFileAccess($path); - } - - /** - * get a cache instance for the storage - * - * @param string $path - * @param Storage (optional) the storage to pass to the cache - * @return Cache - */ - public function getCache($path = '', $storage = null) { - if (!$storage) { - $storage = $this; - } - $cache = $this->storage->getCache($path, $storage); - return new CacheWrapper($cache, $storage); - } - - /** - * A custom storage implementation can return an url for direct download of a give file. - * - * For now the returned array can hold the parameter url - in future more attributes might follow. - * - * @param string $path - * @return array - * @throws ForbiddenException - */ - public function getDirectDownload($path) { - $this->checkFileAccess($path); - } - - /** - * @param IStorage $sourceStorage - * @param string $sourceInternalPath - * @param string $targetInternalPath - * @return bool - * @throws ForbiddenException - */ - public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) { - $this->checkFileAccess($targetInternalPath); - } - - /** - * @param IStorage $sourceStorage - * @param string $sourceInternalPath - * @param string $targetInternalPath - * @return bool - * @throws ForbiddenException - */ - public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) { - $this->checkFileAccess($targetInternalPath); - } - - /** - * @throws ForbiddenException - */ - public function writeStream(string $path, $stream, ?int $size = null): int { - $this->checkFileAccess($path); - } + private const RECOVERY_FOLDER = 'files/Recovery'; + protected readonly int $mask; + + /** + * Constructor + * + * @param array $parameters + */ + public function __construct($parameters) { + parent::__construct($parameters); + + // Set up the permission mask to block specific permissions + $this->mask = Constants::PERMISSION_ALL + & ~Constants::PERMISSION_READ + & ~Constants::PERMISSION_CREATE + & ~Constants::PERMISSION_UPDATE + & ~Constants::PERMISSION_DELETE; + } + + /** + * @throws ForbiddenException + */ + protected function checkFileAccess(string $path, ?bool $isDir = null): void { + if ($this->isRecoveryFolder($path)) { + // Block access to the "Recovery" folder + throw new ForbiddenException('Access denied to the Recovery folder', false); + } + + // If you need additional access checks for other folders, you can add here. + } + + /** + * Check if the path refers to the "Recovery" folder. + * + * @param string $path + * @return bool + */ + private function isRecoveryFolder(string $path): bool { + // Ensure the path matches exactly or starts with "files/Recovery" + return strpos($path, '/' . self::RECOVERY_FOLDER) === 0; + } + + /* + * Storage wrapper methods + */ + + public function mkdir($path): bool { + $this->checkFileAccess($path, true); + return $this->storage->mkdir($path); + } + + public function rmdir($path): bool { + $this->checkFileAccess($path, true); + return $this->storage->rmdir($path); + } + + public function isCreatable($path): bool { + try { + $this->checkFileAccess($path); + } catch (ForbiddenException $e) { + return false; + } + return $this->storage->isCreatable($path); + } + + public function isReadable($path): bool { + try { + $this->checkFileAccess($path); + } catch (ForbiddenException $e) { + return false; + } + return $this->storage->isReadable($path); + } + + public function isUpdatable($path): bool { + try { + $this->checkFileAccess($path); + } catch (ForbiddenException $e) { + return false; + } + return $this->storage->isUpdatable($path); + } + + public function isDeletable($path): bool { + try { + $this->checkFileAccess($path); + } catch (ForbiddenException $e) { + return false; + } + return $this->storage->isDeletable($path); + } + + public function getPermissions($path): int { + try { + $this->checkFileAccess($path); + } catch (ForbiddenException $e) { + return $this->mask; + } + return $this->storage->getPermissions($path); + } + + public function file_get_contents($path): string|false { + $this->checkFileAccess($path, false); + return $this->storage->file_get_contents($path); + } + + public function file_put_contents($path, $data): int|float|false { + $this->checkFileAccess($path, false); + return $this->storage->file_put_contents($path, $data); + } + + public function unlink($path): bool { + $this->checkFileAccess($path, false); + return $this->storage->unlink($path); + } + + public function rename($source, $target): bool { + $isDir = $this->is_dir($source); + $this->checkFileAccess($source, $isDir); + $this->checkFileAccess($target, $isDir); + return $this->storage->rename($source, $target); + } + + public function copy($source, $target): bool { + $isDir = $this->is_dir($source); + $this->checkFileAccess($source, $isDir); + $this->checkFileAccess($target, $isDir); + return $this->storage->copy($source, $target); + } + + public function fopen($path, $mode) { + $this->checkFileAccess($path, false); + return $this->storage->fopen($path, $mode); + } + + public function touch($path, $mtime = null): bool { + $this->checkFileAccess($path, false); + return $this->storage->touch($path, $mtime); + } + + /** + * Get a cache instance for the storage + * + * @param string $path + * @param Storage (optional) the storage to pass to the cache + * @return Cache + */ + public function getCache($path = '', $storage = null): ICache { + if (!$storage) { + $storage = $this; + } + $cache = $this->storage->getCache($path, $storage); + return new CacheWrapper($cache, $storage); + } + + public function getDirectDownload($path): array|false { + $this->checkFileAccess($path, false); + return $this->storage->getDirectDownload($path); + } + + public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath): bool { + $this->checkFileAccess($targetInternalPath); + return $this->storage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); + } + + public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath): bool { + $this->checkFileAccess($targetInternalPath); + return $this->storage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); + } + + public function writeStream(string $path, $stream, ?int $size = null): int { + $this->checkFileAccess($path, false); + return $this->storage->writeStream($path, $stream, $size); + } } -- GitLab From f90c56e000f7a56752b8237e59616c173290ea9a Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Wed, 27 Nov 2024 16:38:36 +0530 Subject: [PATCH 07/23] add check for recovery --- lib/Filesystem/StorageWrapper.php | 353 +++++++++++++++--------------- 1 file changed, 178 insertions(+), 175 deletions(-) diff --git a/lib/Filesystem/StorageWrapper.php b/lib/Filesystem/StorageWrapper.php index db25b23a..aaa3bf95 100644 --- a/lib/Filesystem/StorageWrapper.php +++ b/lib/Filesystem/StorageWrapper.php @@ -1,3 +1,6 @@ +mask = Constants::PERMISSION_ALL - & ~Constants::PERMISSION_READ - & ~Constants::PERMISSION_CREATE - & ~Constants::PERMISSION_UPDATE - & ~Constants::PERMISSION_DELETE; - } - - /** - * @throws ForbiddenException - */ - protected function checkFileAccess(string $path, ?bool $isDir = null): void { - if ($this->isRecoveryFolder($path)) { - // Block access to the "Recovery" folder - throw new ForbiddenException('Access denied to the Recovery folder', false); - } - - // If you need additional access checks for other folders, you can add here. - } - - /** - * Check if the path refers to the "Recovery" folder. - * - * @param string $path - * @return bool - */ - private function isRecoveryFolder(string $path): bool { - // Ensure the path matches exactly or starts with "files/Recovery" - return strpos($path, '/' . self::RECOVERY_FOLDER) === 0; - } - - /* - * Storage wrapper methods - */ - - public function mkdir($path): bool { - $this->checkFileAccess($path, true); - return $this->storage->mkdir($path); - } - - public function rmdir($path): bool { - $this->checkFileAccess($path, true); - return $this->storage->rmdir($path); - } - - public function isCreatable($path): bool { - try { - $this->checkFileAccess($path); - } catch (ForbiddenException $e) { - return false; - } - return $this->storage->isCreatable($path); - } - - public function isReadable($path): bool { - try { - $this->checkFileAccess($path); - } catch (ForbiddenException $e) { - return false; - } - return $this->storage->isReadable($path); - } - - public function isUpdatable($path): bool { - try { - $this->checkFileAccess($path); - } catch (ForbiddenException $e) { - return false; - } - return $this->storage->isUpdatable($path); - } - - public function isDeletable($path): bool { - try { - $this->checkFileAccess($path); - } catch (ForbiddenException $e) { - return false; - } - return $this->storage->isDeletable($path); - } - - public function getPermissions($path): int { - try { - $this->checkFileAccess($path); - } catch (ForbiddenException $e) { - return $this->mask; - } - return $this->storage->getPermissions($path); - } - - public function file_get_contents($path): string|false { - $this->checkFileAccess($path, false); - return $this->storage->file_get_contents($path); - } - - public function file_put_contents($path, $data): int|float|false { - $this->checkFileAccess($path, false); - return $this->storage->file_put_contents($path, $data); - } - - public function unlink($path): bool { - $this->checkFileAccess($path, false); - return $this->storage->unlink($path); - } - - public function rename($source, $target): bool { - $isDir = $this->is_dir($source); - $this->checkFileAccess($source, $isDir); - $this->checkFileAccess($target, $isDir); - return $this->storage->rename($source, $target); - } - - public function copy($source, $target): bool { - $isDir = $this->is_dir($source); - $this->checkFileAccess($source, $isDir); - $this->checkFileAccess($target, $isDir); - return $this->storage->copy($source, $target); - } - - public function fopen($path, $mode) { - $this->checkFileAccess($path, false); - return $this->storage->fopen($path, $mode); - } - - public function touch($path, $mtime = null): bool { - $this->checkFileAccess($path, false); - return $this->storage->touch($path, $mtime); - } - - /** - * Get a cache instance for the storage - * - * @param string $path - * @param Storage (optional) the storage to pass to the cache - * @return Cache - */ - public function getCache($path = '', $storage = null): ICache { - if (!$storage) { - $storage = $this; - } - $cache = $this->storage->getCache($path, $storage); - return new CacheWrapper($cache, $storage); - } - - public function getDirectDownload($path): array|false { - $this->checkFileAccess($path, false); - return $this->storage->getDirectDownload($path); - } - - public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath): bool { - $this->checkFileAccess($targetInternalPath); - return $this->storage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); - } - - public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath): bool { - $this->checkFileAccess($targetInternalPath); - return $this->storage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); - } - - public function writeStream(string $path, $stream, ?int $size = null): int { - $this->checkFileAccess($path, false); - return $this->storage->writeStream($path, $stream, $size); - } + private const RECOVERY_FOLDER = 'files/Recovery'; + protected readonly int $mask; + + /** + * Constructor + * + * @param array $parameters + */ + public function __construct($parameters) { + parent::__construct($parameters); + + // Set up the permission mask to block specific permissions + $this->mask = Constants::PERMISSION_ALL + & ~Constants::PERMISSION_READ + & ~Constants::PERMISSION_CREATE + & ~Constants::PERMISSION_UPDATE + & ~Constants::PERMISSION_DELETE; + } + + /** + * @throws ForbiddenException + */ + protected function checkFileAccess(string $path, ?bool $isDir = null): void { + if ($this->isRecoveryFolder($path)) { + // Block access to the "Recovery" folder + throw new ForbiddenException('Access denied to the Recovery folder', false); + } + + // If you need additional access checks for other folders, you can add here. + } + + /** + * Check if the path refers to the "Recovery" folder. + * + * @param string $path + * @return bool + */ + private function isRecoveryFolder(string $path): bool { + // Ensure the path matches exactly or starts with "files/Recovery" + return strpos($path, '/' . self::RECOVERY_FOLDER) === 0; + } + + /* + * Storage wrapper methods + */ + + public function mkdir($path): bool { + $this->checkFileAccess($path, true); + return $this->storage->mkdir($path); + } + + public function rmdir($path): bool { + $this->checkFileAccess($path, true); + return $this->storage->rmdir($path); + } + + public function isCreatable($path): bool { + try { + $this->checkFileAccess($path); + } catch (ForbiddenException $e) { + return false; + } + return $this->storage->isCreatable($path); + } + + public function isReadable($path): bool { + try { + $this->checkFileAccess($path); + } catch (ForbiddenException $e) { + return false; + } + return $this->storage->isReadable($path); + } + + public function isUpdatable($path): bool { + try { + $this->checkFileAccess($path); + } catch (ForbiddenException $e) { + return false; + } + return $this->storage->isUpdatable($path); + } + + public function isDeletable($path): bool { + try { + $this->checkFileAccess($path); + } catch (ForbiddenException $e) { + return false; + } + return $this->storage->isDeletable($path); + } + + public function getPermissions($path): int { + try { + $this->checkFileAccess($path); + } catch (ForbiddenException $e) { + return $this->mask; + } + return $this->storage->getPermissions($path); + } + + public function file_get_contents($path): string|false { + $this->checkFileAccess($path, false); + return $this->storage->file_get_contents($path); + } + + public function file_put_contents($path, $data): int|float|false { + $this->checkFileAccess($path, false); + return $this->storage->file_put_contents($path, $data); + } + + public function unlink($path): bool { + $this->checkFileAccess($path, false); + return $this->storage->unlink($path); + } + + public function rename($source, $target): bool { + $isDir = $this->is_dir($source); + $this->checkFileAccess($source, $isDir); + $this->checkFileAccess($target, $isDir); + return $this->storage->rename($source, $target); + } + + public function copy($source, $target): bool { + $isDir = $this->is_dir($source); + $this->checkFileAccess($source, $isDir); + $this->checkFileAccess($target, $isDir); + return $this->storage->copy($source, $target); + } + + public function fopen($path, $mode) { + $this->checkFileAccess($path, false); + return $this->storage->fopen($path, $mode); + } + + public function touch($path, $mtime = null): bool { + $this->checkFileAccess($path, false); + return $this->storage->touch($path, $mtime); + } + + /** + * Get a cache instance for the storage + * + * @param string $path + * @param Storage (optional) the storage to pass to the cache + * @return Cache + */ + public function getCache($path = '', $storage = null): ICache { + if (!$storage) { + $storage = $this; + } + $cache = $this->storage->getCache($path, $storage); + return new CacheWrapper($cache, $storage); + } + + public function getDirectDownload($path): array|false { + $this->checkFileAccess($path, false); + return $this->storage->getDirectDownload($path); + } + + public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath): bool { + $this->checkFileAccess($targetInternalPath); + return $this->storage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); + } + + public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath): bool { + $this->checkFileAccess($targetInternalPath); + return $this->storage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); + } + + public function writeStream(string $path, $stream, ?int $size = null): int { + $this->checkFileAccess($path, false); + return $this->storage->writeStream($path, $stream, $size); + } } -- GitLab From 3557d8c57b0ef0a9e63ce16d78bf4a6f143068f0 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Wed, 27 Nov 2024 17:01:53 +0530 Subject: [PATCH 08/23] add check for recover in cache wrapper --- lib/Filesystem/CacheWrapper.php | 45 ++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index df145740..2d6d8fb3 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -8,7 +8,6 @@ use OC\Files\Cache\Wrapper\CacheWrapper as Wrapper; use OCP\Constants; use OCP\Files\Cache\ICache; use OCP\Files\Cache\ICacheEntry; -use OCP\Files\ForbiddenException; use OCP\Files\Search\ISearchQuery; class CacheWrapper extends Wrapper { @@ -26,30 +25,53 @@ class CacheWrapper extends Wrapper { & ~Constants::PERMISSION_DELETE; } + /** + * Format the cache entry to check access and adjust permissions. + */ protected function formatCacheEntry($entry) { if (isset($entry['path']) && isset($entry['permissions'])) { - try { - throw new ForbiddenException('Access denied', false); - } catch (ForbiddenException) { + // Only restrict permissions for files in the "Recovery" folder + if ($this->isExcludedPath($entry['path'])) { $entry['permissions'] &= $this->mask; } } return $entry; } + /** + * Prevent inserting into the cache for "Recovery" folder. + */ public function insert($file, $data) { - throw new \Exception('User data cache insert is disabled.'); + if ($this->isExcludedPath($file)) { + throw new \Exception('Cache insert is disabled for the Recovery folder.'); + } + return parent::insert($file, $data); // Normal insert for other paths } + /** + * Prevent updating cache for files in the "Recovery" folder. + */ public function update($id, $data) { - throw new \Exception('User data cache update is disabled.'); + if ($this->isExcludedPath($data['path'])) { + throw new \Exception('Cache update is disabled for the Recovery folder.'); + } + return parent::update($id, $data); // Normal update for other paths } + /** + * Prevent removal from cache for files in the "Recovery" folder. + */ public function remove($fileId) { - throw new \Exception('User data cache removal is disabled.'); + $filePath = $this->storage->getPath($fileId); + if ($this->isExcludedPath($filePath)) { + throw new \Exception('Cache removal is disabled for the Recovery folder.'); + } + return parent::remove($fileId); // Normal removal for other paths } - // Exclude specific folder and its files from search results + /** + * Exclude specific folder and its files from search results. + */ public function searchQuery(ISearchQuery $searchQuery) { $results = parent::searchQuery($searchQuery); return array_filter($results, function ($entry) { @@ -57,6 +79,9 @@ class CacheWrapper extends Wrapper { }); } + /** + * Filter out "Recovery" folder from cache search results. + */ public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry { if ($this->isExcludedPath($rawEntry->getPath())) { return null; @@ -64,7 +89,9 @@ class CacheWrapper extends Wrapper { return parent::getCacheEntryFromSearchResult($rawEntry); } - // Check if a path is within the excluded folder + /** + * Check if a path is within the excluded folder (e.g., "Recovery"). + */ private function isExcludedPath(string $path): bool { return strpos($path, $this->excludedFolder) === 0; } -- GitLab From 6646c45f5493d2226cc77e37cde4f879840a1c12 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Wed, 27 Nov 2024 17:31:53 +0530 Subject: [PATCH 09/23] add check for recover in cache wrapper --- lib/Filesystem/CacheWrapper.php | 157 +++++++++++++++++--------------- 1 file changed, 82 insertions(+), 75 deletions(-) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index 2d6d8fb3..e12d49c4 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -8,91 +8,98 @@ use OC\Files\Cache\Wrapper\CacheWrapper as Wrapper; use OCP\Constants; use OCP\Files\Cache\ICache; use OCP\Files\Cache\ICacheEntry; +use OCP\Files\ForbiddenException; use OCP\Files\Search\ISearchQuery; class CacheWrapper extends Wrapper { - private string $excludedFolder = 'files/Recovery'; + private string $excludedFolder = 'files/Recovery'; - public function __construct( - ICache $cache - ) { - parent::__construct($cache); - $this->mask = Constants::PERMISSION_ALL - & ~Constants::PERMISSION_READ - & ~Constants::PERMISSION_CREATE - & ~Constants::PERMISSION_UPDATE - & ~Constants::PERMISSION_DELETE; - } + public function __construct( + ICache $cache + ) { + parent::__construct($cache); + $this->mask = Constants::PERMISSION_ALL + & ~Constants::PERMISSION_READ + & ~Constants::PERMISSION_CREATE + & ~Constants::PERMISSION_UPDATE + & ~Constants::PERMISSION_DELETE; + } - /** - * Format the cache entry to check access and adjust permissions. - */ - protected function formatCacheEntry($entry) { - if (isset($entry['path']) && isset($entry['permissions'])) { - // Only restrict permissions for files in the "Recovery" folder - if ($this->isExcludedPath($entry['path'])) { - $entry['permissions'] &= $this->mask; - } - } - return $entry; - } + /** + * Format the cache entry to check access and adjust permissions. + */ + protected function formatCacheEntry($entry) { + if (isset($entry['path']) && isset($entry['permissions'])) { + // Only restrict permissions for files in the "Recovery" folder + if ($this->isExcludedPath($entry['path'])) { + $entry['permissions'] &= $this->mask; + } + } + return $entry; + } - /** - * Prevent inserting into the cache for "Recovery" folder. - */ - public function insert($file, $data) { - if ($this->isExcludedPath($file)) { - throw new \Exception('Cache insert is disabled for the Recovery folder.'); - } - return parent::insert($file, $data); // Normal insert for other paths - } + /** + * Prevent inserting into the cache for "Recovery" folder. + */ + public function insert($file, $data) { + // Ensure path is set before checking + if (isset($file) && $this->isExcludedPath($file)) { + throw new \Exception('Cache insert is disabled for the Recovery folder.'); + } + return parent::insert($file, $data); // Normal insert for other paths + } - /** - * Prevent updating cache for files in the "Recovery" folder. - */ - public function update($id, $data) { - if ($this->isExcludedPath($data['path'])) { - throw new \Exception('Cache update is disabled for the Recovery folder.'); - } - return parent::update($id, $data); // Normal update for other paths - } + /** + * Prevent updating cache for files in the "Recovery" folder. + */ + public function update($id, $data) { + // Ensure path is set before checking + if (isset($data['path']) && $this->isExcludedPath($data['path'])) { + throw new \Exception('Cache update is disabled for the Recovery folder.'); + } + return parent::update($id, $data); // Normal update for other paths + } - /** - * Prevent removal from cache for files in the "Recovery" folder. - */ - public function remove($fileId) { - $filePath = $this->storage->getPath($fileId); - if ($this->isExcludedPath($filePath)) { - throw new \Exception('Cache removal is disabled for the Recovery folder.'); - } - return parent::remove($fileId); // Normal removal for other paths - } + /** + * Prevent removal from cache for files in the "Recovery" folder. + */ + public function remove($fileId) { + $filePath = $this->storage->getPath($fileId); + if ($this->isExcludedPath($filePath)) { + throw new \Exception('Cache removal is disabled for the Recovery folder.'); + } + return parent::remove($fileId); // Normal removal for other paths + } - /** - * Exclude specific folder and its files from search results. - */ - public function searchQuery(ISearchQuery $searchQuery) { - $results = parent::searchQuery($searchQuery); - return array_filter($results, function ($entry) { - return isset($entry['path']) && !$this->isExcludedPath($entry['path']); - }); - } + /** + * Exclude specific folder and its files from search results. + */ + public function searchQuery(ISearchQuery $searchQuery) { + $results = parent::searchQuery($searchQuery); + return array_filter($results, function ($entry) { + return isset($entry['path']) && !$this->isExcludedPath($entry['path']); + }); + } - /** - * Filter out "Recovery" folder from cache search results. - */ - public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry { - if ($this->isExcludedPath($rawEntry->getPath())) { - return null; - } - return parent::getCacheEntryFromSearchResult($rawEntry); - } + /** + * Filter out "Recovery" folder from cache search results. + */ + public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry { + if ($this->isExcludedPath($rawEntry->getPath())) { + return null; + } + return parent::getCacheEntryFromSearchResult($rawEntry); + } - /** - * Check if a path is within the excluded folder (e.g., "Recovery"). - */ - private function isExcludedPath(string $path): bool { - return strpos($path, $this->excludedFolder) === 0; - } + /** + * Check if a path is within the excluded folder (e.g., "Recovery"). + */ + private function isExcludedPath(?string $path): bool { + // If path is null or not set, return false + if ($path === null) { + return false; + } + return strpos($path, $this->excludedFolder) === 0; + } } -- GitLab From 26c4367e26e2e322a09ac11a9d8a7960191db2e7 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Wed, 27 Nov 2024 17:32:04 +0530 Subject: [PATCH 10/23] add check for recover in cache wrapper --- lib/Filesystem/CacheWrapper.php | 163 ++++++++++++++++---------------- 1 file changed, 81 insertions(+), 82 deletions(-) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index e12d49c4..5140d658 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -8,98 +8,97 @@ use OC\Files\Cache\Wrapper\CacheWrapper as Wrapper; use OCP\Constants; use OCP\Files\Cache\ICache; use OCP\Files\Cache\ICacheEntry; -use OCP\Files\ForbiddenException; use OCP\Files\Search\ISearchQuery; class CacheWrapper extends Wrapper { - private string $excludedFolder = 'files/Recovery'; + private string $excludedFolder = 'files/Recovery'; - public function __construct( - ICache $cache - ) { - parent::__construct($cache); - $this->mask = Constants::PERMISSION_ALL - & ~Constants::PERMISSION_READ - & ~Constants::PERMISSION_CREATE - & ~Constants::PERMISSION_UPDATE - & ~Constants::PERMISSION_DELETE; - } + public function __construct( + ICache $cache + ) { + parent::__construct($cache); + $this->mask = Constants::PERMISSION_ALL + & ~Constants::PERMISSION_READ + & ~Constants::PERMISSION_CREATE + & ~Constants::PERMISSION_UPDATE + & ~Constants::PERMISSION_DELETE; + } - /** - * Format the cache entry to check access and adjust permissions. - */ - protected function formatCacheEntry($entry) { - if (isset($entry['path']) && isset($entry['permissions'])) { - // Only restrict permissions for files in the "Recovery" folder - if ($this->isExcludedPath($entry['path'])) { - $entry['permissions'] &= $this->mask; - } - } - return $entry; - } + /** + * Format the cache entry to check access and adjust permissions. + */ + protected function formatCacheEntry($entry) { + if (isset($entry['path']) && isset($entry['permissions'])) { + // Only restrict permissions for files in the "Recovery" folder + if ($this->isExcludedPath($entry['path'])) { + $entry['permissions'] &= $this->mask; + } + } + return $entry; + } - /** - * Prevent inserting into the cache for "Recovery" folder. - */ - public function insert($file, $data) { - // Ensure path is set before checking - if (isset($file) && $this->isExcludedPath($file)) { - throw new \Exception('Cache insert is disabled for the Recovery folder.'); - } - return parent::insert($file, $data); // Normal insert for other paths - } + /** + * Prevent inserting into the cache for "Recovery" folder. + */ + public function insert($file, $data) { + // Ensure path is set before checking + if (isset($file) && $this->isExcludedPath($file)) { + throw new \Exception('Cache insert is disabled for the Recovery folder.'); + } + return parent::insert($file, $data); // Normal insert for other paths + } - /** - * Prevent updating cache for files in the "Recovery" folder. - */ - public function update($id, $data) { - // Ensure path is set before checking - if (isset($data['path']) && $this->isExcludedPath($data['path'])) { - throw new \Exception('Cache update is disabled for the Recovery folder.'); - } - return parent::update($id, $data); // Normal update for other paths - } + /** + * Prevent updating cache for files in the "Recovery" folder. + */ + public function update($id, $data) { + // Ensure path is set before checking + if (isset($data['path']) && $this->isExcludedPath($data['path'])) { + throw new \Exception('Cache update is disabled for the Recovery folder.'); + } + return parent::update($id, $data); // Normal update for other paths + } - /** - * Prevent removal from cache for files in the "Recovery" folder. - */ - public function remove($fileId) { - $filePath = $this->storage->getPath($fileId); - if ($this->isExcludedPath($filePath)) { - throw new \Exception('Cache removal is disabled for the Recovery folder.'); - } - return parent::remove($fileId); // Normal removal for other paths - } + /** + * Prevent removal from cache for files in the "Recovery" folder. + */ + public function remove($fileId) { + $filePath = $this->storage->getPath($fileId); + if ($this->isExcludedPath($filePath)) { + throw new \Exception('Cache removal is disabled for the Recovery folder.'); + } + return parent::remove($fileId); // Normal removal for other paths + } - /** - * Exclude specific folder and its files from search results. - */ - public function searchQuery(ISearchQuery $searchQuery) { - $results = parent::searchQuery($searchQuery); - return array_filter($results, function ($entry) { - return isset($entry['path']) && !$this->isExcludedPath($entry['path']); - }); - } + /** + * Exclude specific folder and its files from search results. + */ + public function searchQuery(ISearchQuery $searchQuery) { + $results = parent::searchQuery($searchQuery); + return array_filter($results, function ($entry) { + return isset($entry['path']) && !$this->isExcludedPath($entry['path']); + }); + } - /** - * Filter out "Recovery" folder from cache search results. - */ - public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry { - if ($this->isExcludedPath($rawEntry->getPath())) { - return null; - } - return parent::getCacheEntryFromSearchResult($rawEntry); - } + /** + * Filter out "Recovery" folder from cache search results. + */ + public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry { + if ($this->isExcludedPath($rawEntry->getPath())) { + return null; + } + return parent::getCacheEntryFromSearchResult($rawEntry); + } - /** - * Check if a path is within the excluded folder (e.g., "Recovery"). - */ - private function isExcludedPath(?string $path): bool { - // If path is null or not set, return false - if ($path === null) { - return false; - } - return strpos($path, $this->excludedFolder) === 0; - } + /** + * Check if a path is within the excluded folder (e.g., "Recovery"). + */ + private function isExcludedPath(?string $path): bool { + // If path is null or not set, return false + if ($path === null) { + return false; + } + return strpos($path, $this->excludedFolder) === 0; + } } -- GitLab From f61a7b0db2e899eb92ec870a21965049c4e70556 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Wed, 27 Nov 2024 17:57:07 +0530 Subject: [PATCH 11/23] add check for recover folder in cache wrapper --- lib/Filesystem/StorageWrapper.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/Filesystem/StorageWrapper.php b/lib/Filesystem/StorageWrapper.php index aaa3bf95..c5f20ca7 100644 --- a/lib/Filesystem/StorageWrapper.php +++ b/lib/Filesystem/StorageWrapper.php @@ -170,16 +170,23 @@ class StorageWrapper extends Wrapper implements IWriteStreamStorage { } public function getDirectDownload($path): array|false { + $this->checkFileAccess($path, false); return $this->storage->getDirectDownload($path); } public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath): bool { + if ($sourceStorage === $this) { + return $this->copy($sourceInternalPath, $targetInternalPath); + } $this->checkFileAccess($targetInternalPath); return $this->storage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); } public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath): bool { + if ($sourceStorage === $this) { + return $this->rename($sourceInternalPath, $targetInternalPath); + } $this->checkFileAccess($targetInternalPath); return $this->storage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); } -- GitLab From 9c6d8d7e99ddef8d80f31e0c397b0f5d13ee3983 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Wed, 27 Nov 2024 19:26:19 +0530 Subject: [PATCH 12/23] add check for recover folder in cache wrapper --- lib/Filesystem/CacheWrapper.php | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index 5140d658..890b0245 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -5,9 +5,9 @@ declare(strict_types=1); namespace OCA\EcloudAccounts\Filesystem; use OC\Files\Cache\Wrapper\CacheWrapper as Wrapper; -use OCP\Constants; use OCP\Files\Cache\ICache; use OCP\Files\Cache\ICacheEntry; +use OCP\Files\ForbiddenException; use OCP\Files\Search\ISearchQuery; class CacheWrapper extends Wrapper { @@ -18,11 +18,6 @@ class CacheWrapper extends Wrapper { ICache $cache ) { parent::__construct($cache); - $this->mask = Constants::PERMISSION_ALL - & ~Constants::PERMISSION_READ - & ~Constants::PERMISSION_CREATE - & ~Constants::PERMISSION_UPDATE - & ~Constants::PERMISSION_DELETE; } /** @@ -30,9 +25,9 @@ class CacheWrapper extends Wrapper { */ protected function formatCacheEntry($entry) { if (isset($entry['path']) && isset($entry['permissions'])) { - // Only restrict permissions for files in the "Recovery" folder + // Check if the file is in the "Recovery" folder if ($this->isExcludedPath($entry['path'])) { - $entry['permissions'] &= $this->mask; + throw new ForbiddenException('Access denied to the Recovery folder.', 503); } } return $entry; -- GitLab From c6410f848ac8f91455990126bb050883d35dd610 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Wed, 27 Nov 2024 21:01:08 +0530 Subject: [PATCH 13/23] add check for recover folder in cache wrapper --- lib/Filesystem/CacheWrapper.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index 890b0245..dfeff0e3 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace OCA\EcloudAccounts\Filesystem; use OC\Files\Cache\Wrapper\CacheWrapper as Wrapper; +use OCP\Constants; use OCP\Files\Cache\ICache; use OCP\Files\Cache\ICacheEntry; use OCP\Files\ForbiddenException; @@ -18,6 +19,11 @@ class CacheWrapper extends Wrapper { ICache $cache ) { parent::__construct($cache); + $this->mask = Constants::PERMISSION_ALL + & ~Constants::PERMISSION_READ + & ~Constants::PERMISSION_CREATE + & ~Constants::PERMISSION_UPDATE + & ~Constants::PERMISSION_DELETE; } /** @@ -29,6 +35,9 @@ class CacheWrapper extends Wrapper { if ($this->isExcludedPath($entry['path'])) { throw new ForbiddenException('Access denied to the Recovery folder.', 503); } + + // Mask permissions for files outside of the "Recovery" folder + $entry['permissions'] &= $this->mask; } return $entry; } -- GitLab From d070b8882e7bc086926233262730ce395f3dde3a Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Wed, 27 Nov 2024 21:27:24 +0530 Subject: [PATCH 14/23] add check for recover folder in cache wrapper --- lib/Filesystem/CacheWrapper.php | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index dfeff0e3..d773c21f 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -31,13 +31,15 @@ class CacheWrapper extends Wrapper { */ protected function formatCacheEntry($entry) { if (isset($entry['path']) && isset($entry['permissions'])) { - // Check if the file is in the "Recovery" folder + // Only restrict permissions for files in the "Recovery" folder if ($this->isExcludedPath($entry['path'])) { - throw new ForbiddenException('Access denied to the Recovery folder.', 503); - } + try { + throw new ForbiddenException('Access denied', false); + } catch (ForbiddenException) { + $entry['permissions'] &= $this->mask; + } - // Mask permissions for files outside of the "Recovery" folder - $entry['permissions'] &= $this->mask; + } } return $entry; } @@ -46,8 +48,7 @@ class CacheWrapper extends Wrapper { * Prevent inserting into the cache for "Recovery" folder. */ public function insert($file, $data) { - // Ensure path is set before checking - if (isset($file) && $this->isExcludedPath($file)) { + if ($this->isExcludedPath($file)) { throw new \Exception('Cache insert is disabled for the Recovery folder.'); } return parent::insert($file, $data); // Normal insert for other paths @@ -57,8 +58,7 @@ class CacheWrapper extends Wrapper { * Prevent updating cache for files in the "Recovery" folder. */ public function update($id, $data) { - // Ensure path is set before checking - if (isset($data['path']) && $this->isExcludedPath($data['path'])) { + if ($this->isExcludedPath($data['path'])) { throw new \Exception('Cache update is disabled for the Recovery folder.'); } return parent::update($id, $data); // Normal update for other paths @@ -98,11 +98,7 @@ class CacheWrapper extends Wrapper { /** * Check if a path is within the excluded folder (e.g., "Recovery"). */ - private function isExcludedPath(?string $path): bool { - // If path is null or not set, return false - if ($path === null) { - return false; - } + private function isExcludedPath(string $path): bool { return strpos($path, $this->excludedFolder) === 0; } } -- GitLab From 2c6f9c1d1db638bddcdf0c213c4627776d8c85f6 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Wed, 27 Nov 2024 22:22:04 +0530 Subject: [PATCH 15/23] empty path check --- lib/Filesystem/CacheWrapper.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index d773c21f..a6f4349e 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -99,6 +99,9 @@ class CacheWrapper extends Wrapper { * Check if a path is within the excluded folder (e.g., "Recovery"). */ private function isExcludedPath(string $path): bool { + if (empty($path)) { + return false; + } return strpos($path, $this->excludedFolder) === 0; } } -- GitLab From 7ab6721ce1c46a9f0a3392b53968e240c86429ec Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Wed, 27 Nov 2024 23:03:29 +0530 Subject: [PATCH 16/23] empty path check --- lib/Filesystem/CacheWrapper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index a6f4349e..33e35fad 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -58,7 +58,7 @@ class CacheWrapper extends Wrapper { * Prevent updating cache for files in the "Recovery" folder. */ public function update($id, $data) { - if ($this->isExcludedPath($data['path'])) { + if (isset($data['path']) && $data['path'] !== null && $this->isExcludedPath($data['path'])) { throw new \Exception('Cache update is disabled for the Recovery folder.'); } return parent::update($id, $data); // Normal update for other paths -- GitLab From d7ed554ce03c23648143117a9d388975558ffde2 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Thu, 28 Nov 2024 14:18:37 +0530 Subject: [PATCH 17/23] applied suggestions --- lib/Filesystem/CacheWrapper.php | 2 +- lib/Filesystem/StorageWrapper.php | 33 ++++++------------------------- 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index 33e35fad..34f3e21f 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -49,7 +49,7 @@ class CacheWrapper extends Wrapper { */ public function insert($file, $data) { if ($this->isExcludedPath($file)) { - throw new \Exception('Cache insert is disabled for the Recovery folder.'); + throw new \OC\ServiceUnavailableException('Service unavailable'); } return parent::insert($file, $data); // Normal insert for other paths } diff --git a/lib/Filesystem/StorageWrapper.php b/lib/Filesystem/StorageWrapper.php index c5f20ca7..673ae903 100644 --- a/lib/Filesystem/StorageWrapper.php +++ b/lib/Filesystem/StorageWrapper.php @@ -9,7 +9,6 @@ use OC\Files\Cache\Cache; use OC\Files\Storage\Wrapper\Wrapper; use OCP\Constants; use OCP\Files\Cache\ICache; -use OCP\Files\ForbiddenException; use OCP\Files\Storage\IStorage; use OCP\Files\Storage\IWriteStreamStorage; @@ -39,7 +38,7 @@ class StorageWrapper extends Wrapper implements IWriteStreamStorage { protected function checkFileAccess(string $path, ?bool $isDir = null): void { if ($this->isRecoveryFolder($path)) { // Block access to the "Recovery" folder - throw new ForbiddenException('Access denied to the Recovery folder', false); + throw new StorageNotAvailableException('Service unavailable'); } // If you need additional access checks for other folders, you can add here. @@ -71,47 +70,27 @@ class StorageWrapper extends Wrapper implements IWriteStreamStorage { } public function isCreatable($path): bool { - try { - $this->checkFileAccess($path); - } catch (ForbiddenException $e) { - return false; - } + $this->checkFileAccess($path); return $this->storage->isCreatable($path); } public function isReadable($path): bool { - try { - $this->checkFileAccess($path); - } catch (ForbiddenException $e) { - return false; - } + $this->checkFileAccess($path); return $this->storage->isReadable($path); } public function isUpdatable($path): bool { - try { - $this->checkFileAccess($path); - } catch (ForbiddenException $e) { - return false; - } + $this->checkFileAccess($path); return $this->storage->isUpdatable($path); } public function isDeletable($path): bool { - try { - $this->checkFileAccess($path); - } catch (ForbiddenException $e) { - return false; - } + $this->checkFileAccess($path); return $this->storage->isDeletable($path); } public function getPermissions($path): int { - try { - $this->checkFileAccess($path); - } catch (ForbiddenException $e) { - return $this->mask; - } + $this->checkFileAccess($path); return $this->storage->getPermissions($path); } -- GitLab From afcb82383d96530d8ae51b83a5b9cd495394b836 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Fri, 29 Nov 2024 15:42:33 +0530 Subject: [PATCH 18/23] added exception --- lib/Filesystem/CacheWrapper.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index 34f3e21f..c980e7db 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -59,7 +59,7 @@ class CacheWrapper extends Wrapper { */ public function update($id, $data) { if (isset($data['path']) && $data['path'] !== null && $this->isExcludedPath($data['path'])) { - throw new \Exception('Cache update is disabled for the Recovery folder.'); + throw new \OC\ServiceUnavailableException('Service unavailable'); } return parent::update($id, $data); // Normal update for other paths } @@ -70,7 +70,7 @@ class CacheWrapper extends Wrapper { public function remove($fileId) { $filePath = $this->storage->getPath($fileId); if ($this->isExcludedPath($filePath)) { - throw new \Exception('Cache removal is disabled for the Recovery folder.'); + throw new \OC\ServiceUnavailableException('Service unavailable'); } return parent::remove($fileId); // Normal removal for other paths } -- GitLab From f62c73772b1ce654261f62a9f34c077bb251625a Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Fri, 29 Nov 2024 17:17:56 +0530 Subject: [PATCH 19/23] added exception --- lib/Filesystem/CacheWrapper.php | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index c980e7db..b3850514 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -19,11 +19,6 @@ class CacheWrapper extends Wrapper { ICache $cache ) { parent::__construct($cache); - $this->mask = Constants::PERMISSION_ALL - & ~Constants::PERMISSION_READ - & ~Constants::PERMISSION_CREATE - & ~Constants::PERMISSION_UPDATE - & ~Constants::PERMISSION_DELETE; } /** @@ -33,12 +28,7 @@ class CacheWrapper extends Wrapper { if (isset($entry['path']) && isset($entry['permissions'])) { // Only restrict permissions for files in the "Recovery" folder if ($this->isExcludedPath($entry['path'])) { - try { - throw new ForbiddenException('Access denied', false); - } catch (ForbiddenException) { - $entry['permissions'] &= $this->mask; - } - + throw new \OC\ServiceUnavailableException('Service unavailable'); } } return $entry; -- GitLab From 61252b1dd00909d68a4276d8c53b71c272015a41 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Fri, 29 Nov 2024 17:25:43 +0530 Subject: [PATCH 20/23] Fix lint --- lib/Filesystem/CacheWrapper.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index b3850514..68699b43 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -5,10 +5,8 @@ declare(strict_types=1); namespace OCA\EcloudAccounts\Filesystem; use OC\Files\Cache\Wrapper\CacheWrapper as Wrapper; -use OCP\Constants; use OCP\Files\Cache\ICache; use OCP\Files\Cache\ICacheEntry; -use OCP\Files\ForbiddenException; use OCP\Files\Search\ISearchQuery; class CacheWrapper extends Wrapper { -- GitLab From 92179f7d0b89c43393ec74e69d4a72b411b7e605 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Fri, 29 Nov 2024 18:43:06 +0530 Subject: [PATCH 21/23] Fix catch --- lib/Filesystem/CacheWrapper.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index 68699b43..67c218c9 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace OCA\EcloudAccounts\Filesystem; use OC\Files\Cache\Wrapper\CacheWrapper as Wrapper; +use OCP\Constants; use OCP\Files\Cache\ICache; use OCP\Files\Cache\ICacheEntry; use OCP\Files\Search\ISearchQuery; @@ -17,6 +18,11 @@ class CacheWrapper extends Wrapper { ICache $cache ) { parent::__construct($cache); + $this->mask = Constants::PERMISSION_ALL + & ~Constants::PERMISSION_READ + & ~Constants::PERMISSION_CREATE + & ~Constants::PERMISSION_UPDATE + & ~Constants::PERMISSION_DELETE; } /** @@ -26,7 +32,11 @@ class CacheWrapper extends Wrapper { if (isset($entry['path']) && isset($entry['permissions'])) { // Only restrict permissions for files in the "Recovery" folder if ($this->isExcludedPath($entry['path'])) { - throw new \OC\ServiceUnavailableException('Service unavailable'); + try { + throw new \OC\ServiceUnavailableException('Service unavailable'); + } catch (\OC\ServiceUnavailableException $e) { + $entry['permissions'] &= $this->mask; + } } } return $entry; -- GitLab From 2a7f246836c86925d3448bcfc668f717e7cedbcf Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Mon, 2 Dec 2024 12:52:12 +0530 Subject: [PATCH 22/23] removed catch --- lib/Filesystem/CacheWrapper.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index 67c218c9..b97b9dfa 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -32,11 +32,7 @@ class CacheWrapper extends Wrapper { if (isset($entry['path']) && isset($entry['permissions'])) { // Only restrict permissions for files in the "Recovery" folder if ($this->isExcludedPath($entry['path'])) { - try { - throw new \OC\ServiceUnavailableException('Service unavailable'); - } catch (\OC\ServiceUnavailableException $e) { - $entry['permissions'] &= $this->mask; - } + throw new \OC\ServiceUnavailableException('Service unavailable'); } } return $entry; -- GitLab From cd9e456c217efd4ba56f8dfb354fda61ad442fb5 Mon Sep 17 00:00:00 2001 From: Avinash Gusain Date: Mon, 2 Dec 2024 13:26:54 +0530 Subject: [PATCH 23/23] revert the change as it stopping any folder loading --- lib/Filesystem/CacheWrapper.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/Filesystem/CacheWrapper.php b/lib/Filesystem/CacheWrapper.php index b97b9dfa..67c218c9 100644 --- a/lib/Filesystem/CacheWrapper.php +++ b/lib/Filesystem/CacheWrapper.php @@ -32,7 +32,11 @@ class CacheWrapper extends Wrapper { if (isset($entry['path']) && isset($entry['permissions'])) { // Only restrict permissions for files in the "Recovery" folder if ($this->isExcludedPath($entry['path'])) { - throw new \OC\ServiceUnavailableException('Service unavailable'); + try { + throw new \OC\ServiceUnavailableException('Service unavailable'); + } catch (\OC\ServiceUnavailableException $e) { + $entry['permissions'] &= $this->mask; + } } } return $entry; -- GitLab