config = $config; $this->groupfolderFolderManager = $manager; $this->rootFolder = $rootFolder; $this->mountProvider = $mountProvider; } public function getFilesystemSnapshotPath() { return self::FILESYSTEM_SNAPSHOT_PATH; } // Nextcloud general public function getDataDirectory() { return $this->config->getSystemValue("datadirectory"); } 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); } public function convertToSnapshotPath(string $filesystemPath, string $snapshotId) { $filesystemPath = realpath($filesystemPath); if(!str_starts_with($filesystemPath, self::FILESYSTEM_ROOT_PATH)) { return false; } return str_replace(self::FILESYSTEM_ROOT_PATH, $this->getSnapshotPath($snapshotId) . DIRECTORY_SEPARATOR, $filesystemPath); } // 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) { return "storage Id null"; } $folder = $this->groupfolderFolderManager->getFolder($groupfolderId, $storageId); if ($folder === false) { return "Folder does not exist"; } return true; } 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); // 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 $relativePath, string $snapshotId) { return $this->convertToSnapshotPath($this->getGroupFolderDirectory($groupfolderId, $relativePath), $snapshotId); } }