From c13e8dfcb2cb0efb57c9aec2c83c630a193fabac Mon Sep 17 00:00:00 2001 From: Jonathan Treffler Date: Tue, 23 Jan 2024 22:02:48 +0100 Subject: [PATCH] added relative_path functionality to getGroupFolderDirectory --- lib/Manager/PathManager.php | 109 +++++++++++++++++++++++------------- 1 file changed, 69 insertions(+), 40 deletions(-) diff --git a/lib/Manager/PathManager.php b/lib/Manager/PathManager.php index 662bbca..cbe9f91 100644 --- a/lib/Manager/PathManager.php +++ b/lib/Manager/PathManager.php @@ -5,50 +5,68 @@ namespace OCA\GroupfolderFilesystemSnapshots\Manager; use OCP\IConfig; use OCP\Files\IRootFolder; use OCA\GroupFolders\Folder\FolderManager; +use OCA\GroupFolders\Mount\MountProvider; class PathManager { - private IConfig $config; - private IRootFolder $rootFolder; - private FolderManager $groupfolderFolderManager; + private IConfig $config; + private IRootFolder $rootFolder; + private FolderManager $groupfolderFolderManager; + /** @var MountProvider */ + protected $mountProvider; - const FILESYSTEM_ROOT_PATH = "/srv/nextcloud/files/"; - const FILESYSTEM_SNAPSHOT_PATH = "/srv/nextcloud/files/.zfs/snapshot/"; + const FILESYSTEM_ROOT_PATH = "/srv/nextcloud/files/"; + const FILESYSTEM_SNAPSHOT_PATH = "/srv/nextcloud/files/.zfs/snapshot/"; - public function __construct(IConfig $config, IRootFolder $rootFolder, FolderManager $manager){ - $this->config = $config; - $this->groupfolderFolderManager = $manager; - $this->rootFolder = $rootFolder; - } + public function __construct( + IConfig $config, + IRootFolder $rootFolder, + FolderManager $manager, + MountProvider $mountProvider, + ){ + $this->config = $config; + $this->groupfolderFolderManager = $manager; + $this->rootFolder = $rootFolder; + $this->mountProvider = $mountProvider; + } - public function getFilesystemSnapshotPath() { - return self::FILESYSTEM_SNAPSHOT_PATH; - } + public function getFilesystemSnapshotPath() { + return self::FILESYSTEM_SNAPSHOT_PATH; + } - // Nextcloud general - public function getDataDirectory() { - return $this->config->getSystemValue("datadirectory"); - } + // Nextcloud general + public function getDataDirectory() { + return $this->config->getSystemValue("datadirectory"); + } - private function getRootFolderStorageId(): ?int { + private function getRootFolderStorageId(): ?int { return $this->rootFolder->getMountPoint()->getNumericStorageId(); } - // Snapshots - public function getSnapshotPath(string $snapshotId) { - return realpath(self::FILESYSTEM_SNAPSHOT_PATH . DIRECTORY_SEPARATOR . $snapshotId . DIRECTORY_SEPARATOR); - } + // Snapshots + public function getSnapshotPath(string $snapshotId) { + return realpath(self::FILESYSTEM_SNAPSHOT_PATH . DIRECTORY_SEPARATOR . $snapshotId . DIRECTORY_SEPARATOR); + } - public function convertToSnapshotPath(string $filesystemPath, string $snapshotId) { - $filesystemPath = realpath($filesystemPath); + public function convertToSnapshotPath(string $filesystemPath, string $snapshotId) { + $filesystemPath = realpath($filesystemPath); - if(!str_starts_with($filesystemPath, self::FILESYSTEM_ROOT_PATH)) { - return false; - } + if(!str_starts_with($filesystemPath, self::FILESYSTEM_ROOT_PATH)) { + return false; + } - return str_replace(self::FILESYSTEM_ROOT_PATH, $this->getSnapshotPath($snapshotId) . DIRECTORY_SEPARATOR, $filesystemPath); - } + return str_replace(self::FILESYSTEM_ROOT_PATH, $this->getSnapshotPath($snapshotId) . DIRECTORY_SEPARATOR, $filesystemPath); + } - // Groupfolders + // Groupfolders + public function getGroupfolderById(int $groupfolderId) { + $storageId = $this->getRootFolderStorageId(); + if (!is_null($storageId)) { + return $this->groupfolderFolderManager->getFolder($groupfolderId, $storageId); + } + } + public function getGroupfolderMountById(int $groupfolderId) { + return $this->mountProvider->getFolder($groupfolderId, False); + } private function checkIfGroupfolderExists(int $groupfolderId): bool { $storageId = $this->getRootFolderStorageId(); if ($storageId === null) { @@ -59,20 +77,31 @@ class PathManager { if ($folder === false) { return "Folder does not exist"; } - + return true; } - public function getGroupFolderDirectory(int $groupfolderId) { - $folderExistsCheck = $this->checkIfGroupfolderExists($groupfolderId); - if(!$folderExistsCheck) { - return $folderExistsCheck; - } + public function getGroupFolderDirectory(int $groupfolderId, string $relativePath) { + $groupFolder = $this->getGroupfolderMountById($groupfolderId); + $relativeToDataDirectoryPath = $groupFolder->get($relativePath)->getInternalPath(); + $minPath = realpath($this->getDataDirectory() . DIRECTORY_SEPARATOR . $groupFolder->getInternalPath() . DIRECTORY_SEPARATOR); + $realPath = realpath($this->getDataDirectory() . DIRECTORY_SEPARATOR . $relativeToDataDirectoryPath . DIRECTORY_SEPARATOR); - return realpath($this->getDataDirectory() . DIRECTORY_SEPARATOR . "__groupfolders" . DIRECTORY_SEPARATOR . $groupfolderId . DIRECTORY_SEPARATOR); + // Data directory and groupfolder directory have to actually exist + if(!file_exists($minPath) || !file_exists($realPath)) { + return false; + } + + // the group subfolder directory always has to start with the groupfolder directory + // prevents usage of ".." in relativePath to escape out of groupfolder or even data directory + if(!str_starts_with($realPath, $minPath)) { + return false; + } + + return $realPath; } - public function getGroupFolderSnapshotDirectory(int $groupfolderId, string $snapshotId) { - return $this->convertToSnapshotPath($this->getGroupFolderDirectory($groupfolderId), $snapshotId); - } + public function getGroupFolderSnapshotDirectory(int $groupfolderId, string $relativePath, string $snapshotId) { + return $this->convertToSnapshotPath($this->getGroupFolderDirectory($groupfolderId, $relativePath), $snapshotId); + } } \ No newline at end of file