406 lines
9.3 KiB
PHP
406 lines
9.3 KiB
PHP
<?php
|
|
/**
|
|
* Nextcloud - Gallery
|
|
*
|
|
* This file is licensed under the Affero General Public License version 3 or
|
|
* later. See the COPYING file.
|
|
*
|
|
* @author Olivier Paroz <galleryapps@oparoz.com>
|
|
* @author Authors of \OCA\Files_Sharing\Helper
|
|
*
|
|
* @copyright Olivier Paroz 2017
|
|
* @copyright Authors of \OCA\Files_Sharing\Helper 2014-2016
|
|
*/
|
|
|
|
namespace OCA\Gallery\Environment;
|
|
|
|
use OCP\IUserManager;
|
|
use OCP\Share;
|
|
use OCP\Share\IShare;
|
|
use OCP\ILogger;
|
|
use OCP\Files\IRootFolder;
|
|
use OCP\Files\Folder;
|
|
use OCP\Files\Node;
|
|
use OCP\Files\File;
|
|
use OCP\Files\NotFoundException;
|
|
|
|
/**
|
|
* Builds the environment so that the services have access to the files and folders' owner
|
|
*
|
|
* @package OCA\Gallery\Environment
|
|
*/
|
|
class Environment {
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
private $appName;
|
|
/**
|
|
* The userId of the logged-in user or the person sharing a folder publicly
|
|
*
|
|
* @var string
|
|
*/
|
|
private $userId;
|
|
/**
|
|
* The userFolder of the logged-in user or the ORIGINAL owner of the files which are shared
|
|
* publicly
|
|
*
|
|
* A share needs to be tracked back to its original owner in order to be able to access the
|
|
* resource
|
|
*
|
|
* @var Folder|null
|
|
*/
|
|
private $userFolder;
|
|
/**
|
|
* @var IUserManager
|
|
*/
|
|
private $userManager;
|
|
/**
|
|
* @var int
|
|
*/
|
|
private $sharedNodeId;
|
|
/**
|
|
* @var File|Folder
|
|
*/
|
|
private $sharedNode;
|
|
/**
|
|
* @var IRootFolder
|
|
*/
|
|
private $rootFolder;
|
|
/**
|
|
* @var ILogger
|
|
*/
|
|
private $logger;
|
|
/**
|
|
* The path to the userFolder for users with accounts: /userId/files
|
|
*
|
|
* For public folders, it's the path from the shared folder to the root folder in the original
|
|
* owner's filesystem: /userId/files/parent_folder/shared_folder
|
|
*
|
|
* @var string
|
|
*/
|
|
private $fromRootToFolder;
|
|
/**
|
|
* The name of the shared folder
|
|
*
|
|
* @var string
|
|
*/
|
|
private $folderName;
|
|
/**
|
|
* @var string|null
|
|
*/
|
|
private $sharePassword;
|
|
|
|
/***
|
|
* Constructor
|
|
*
|
|
* @param string $appName
|
|
* @param string|null $userId
|
|
* @param Folder|null $userFolder
|
|
* @param IUserManager $userManager
|
|
* @param IRootFolder $rootFolder
|
|
* @param ILogger $logger
|
|
*/
|
|
public function __construct(
|
|
$appName,
|
|
$userId,
|
|
$userFolder,
|
|
IUserManager $userManager,
|
|
IRootFolder $rootFolder,
|
|
ILogger $logger
|
|
) {
|
|
$this->appName = $appName;
|
|
$this->userId = $userId;
|
|
$this->userFolder = $userFolder;
|
|
$this->userManager = $userManager;
|
|
$this->rootFolder = $rootFolder;
|
|
$this->logger = $logger;
|
|
}
|
|
|
|
/**
|
|
* Creates the environment based on the share the token links to
|
|
*
|
|
* @param IShare $share
|
|
*/
|
|
public function setTokenBasedEnv($share) {
|
|
$origShareOwnerId = $share->getShareOwner();
|
|
$this->userFolder = $this->rootFolder->getUserFolder($origShareOwnerId);
|
|
|
|
$this->sharedNodeId = $share->getNodeId();
|
|
$this->sharedNode = $share->getNode();
|
|
$this->fromRootToFolder = $this->buildFromRootToFolder($this->sharedNodeId);
|
|
|
|
$this->folderName = $share->getTarget();
|
|
$this->userId = $origShareOwnerId;
|
|
$this->sharePassword = $share->getPassword();
|
|
}
|
|
|
|
/**
|
|
* Creates the environment for a logged-in user
|
|
*
|
|
* userId and userFolder are already known, we define fromRootToFolder
|
|
* so that the services can use one method to have access to resources
|
|
* without having to know whether they're private or public
|
|
*/
|
|
public function setStandardEnv() {
|
|
$this->fromRootToFolder = $this->userFolder->getPath() . '/';
|
|
}
|
|
|
|
/**
|
|
* Returns true if the environment has been setup using a token
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function isTokenBasedEnv() {
|
|
return !empty($this->sharedNodeId);
|
|
}
|
|
|
|
/**
|
|
* Returns the Node based on a path starting from the virtual root
|
|
*
|
|
* @param string $subPath
|
|
*
|
|
* @return File|Folder
|
|
*/
|
|
public function getNodeFromVirtualRoot($subPath) {
|
|
$relativePath = $this->getRelativePath($this->fromRootToFolder);
|
|
$path = $relativePath . '/' . $subPath;
|
|
$node = $this->getNodeFromUserFolder($path);
|
|
|
|
return $this->getResourceFromId($node->getId());
|
|
}
|
|
|
|
/**
|
|
* Returns the Node based on a path starting from the files' owner user folder
|
|
*
|
|
* When logged in, this is the current user's user folder
|
|
* When visiting a link, this is the sharer's user folder
|
|
*
|
|
* @param string $path
|
|
*
|
|
* @return File|Folder
|
|
*
|
|
* @throws NotFoundEnvException
|
|
*/
|
|
public function getNodeFromUserFolder($path) {
|
|
$folder = $this->userFolder;
|
|
if ($folder === null) {
|
|
throw new NotFoundEnvException("Could not access the user's folder");
|
|
} else {
|
|
try {
|
|
$node = $folder->get($path);
|
|
} catch (NotFoundException $exception) {
|
|
$message = 'Could not find anything at: ' . $exception->getMessage();
|
|
throw new NotFoundEnvException($message);
|
|
}
|
|
}
|
|
|
|
return $node;
|
|
}
|
|
|
|
/**
|
|
* Returns the resource identified by the given ID
|
|
*
|
|
* @param int $resourceId
|
|
*
|
|
* @return Node
|
|
*
|
|
* @throws NotFoundEnvException
|
|
*/
|
|
public function getResourceFromId($resourceId) {
|
|
if ($this->isTokenBasedEnv()) {
|
|
if ($this->sharedNode->getType() === 'dir') {
|
|
$resource = $this->getResourceFromFolderAndId($this->sharedNode, $resourceId);
|
|
} else {
|
|
$resource = $this->sharedNode;
|
|
}
|
|
} else {
|
|
$resource = $this->getResourceFromFolderAndId($this->userFolder, $resourceId);
|
|
}
|
|
|
|
return $resource;
|
|
}
|
|
|
|
/**
|
|
* Returns the shared node
|
|
*
|
|
* @return File|Folder
|
|
*/
|
|
public function getSharedNode() {
|
|
return $this->getResourceFromId($this->sharedNodeId);
|
|
}
|
|
|
|
/**
|
|
* Returns the virtual root where the user lands after logging in or when following a link
|
|
*
|
|
* @return Folder
|
|
* @throws NotFoundEnvException
|
|
*/
|
|
public function getVirtualRootFolder() {
|
|
$rootFolder = $this->userFolder;
|
|
if ($this->isTokenBasedEnv()) {
|
|
$node = $this->getSharedNode();
|
|
$nodeType = $node->getType();
|
|
if ($nodeType === 'dir') {
|
|
$rootFolder = $node;
|
|
} else {
|
|
throw new NotFoundEnvException($node->getPath() . ' is not a folder');
|
|
}
|
|
}
|
|
|
|
return $rootFolder;
|
|
}
|
|
|
|
/**
|
|
* Returns the userId of the currently logged-in user or the sharer
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getUserId() {
|
|
return $this->userId;
|
|
}
|
|
|
|
/**
|
|
* Returns the name of the user sharing files publicly
|
|
*
|
|
* @return string
|
|
* @throws NotFoundEnvException
|
|
*/
|
|
public function getDisplayName() {
|
|
$user = null;
|
|
$userId = $this->userId;
|
|
|
|
if (isset($userId)) {
|
|
$user = $this->userManager->get($userId);
|
|
}
|
|
if ($user === null) {
|
|
throw new NotFoundEnvException('Could not find user');
|
|
}
|
|
|
|
return $user->getDisplayName();
|
|
}
|
|
|
|
/**
|
|
* Returns the name of shared folder
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getSharedFolderName() {
|
|
return trim($this->folderName, '//');
|
|
}
|
|
|
|
/**
|
|
* Returns the password for the share, if there is one
|
|
*
|
|
* @return string|null
|
|
*/
|
|
public function getSharePassword() {
|
|
return $this->sharePassword;
|
|
}
|
|
|
|
/**
|
|
* Returns the path which goes from the file, up to the user folder, based on a node:
|
|
* parent_folder/current_folder/my_file
|
|
*
|
|
* This is used for the preview system, which needs a full path
|
|
*
|
|
* getPath() on the file produces a path like:
|
|
* '/userId/files/my_folder/my_sub_folder/my_file'
|
|
*
|
|
* So we substract the path to the folder, giving us a relative path
|
|
* 'my_folder/my_sub_folder/my_file'
|
|
*
|
|
* @param Node $file
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getPathFromUserFolder($file) {
|
|
$path = $file->getPath();
|
|
|
|
return $this->getRelativePath($path);
|
|
}
|
|
|
|
/**
|
|
* Returns the path which goes from the file, up to the root folder of the Gallery:
|
|
* current_folder/my_file
|
|
*
|
|
* That root folder changes when folders are shared publicly
|
|
*
|
|
* @param File|Folder|Node $node
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getPathFromVirtualRoot($node) {
|
|
$path = $node->getPath();
|
|
$nodeType = $node->getType();
|
|
|
|
// Needed because fromRootToFolder always ends with a slash
|
|
if ($nodeType === 'dir') {
|
|
$path .= '/';
|
|
}
|
|
|
|
$path = str_replace($this->fromRootToFolder, '', $path);
|
|
$path = rtrim($path, '/');
|
|
|
|
return $path;
|
|
}
|
|
|
|
/**
|
|
* Returns the resource found in a specific folder and identified by the given ID
|
|
*
|
|
* @param Folder $folder
|
|
* @param int $resourceId
|
|
*
|
|
* @return Node
|
|
* @throws NotFoundEnvException
|
|
*/
|
|
private function getResourceFromFolderAndId($folder, $resourceId) {
|
|
$resourcesArray = $folder->getById($resourceId);
|
|
|
|
if ($resourcesArray[0] === null) {
|
|
throw new NotFoundEnvException('Could not locate node linked to ID: ' . $resourceId);
|
|
}
|
|
|
|
return $resourcesArray[0];
|
|
}
|
|
|
|
/**
|
|
* Returns the path from the shared folder to the root folder in the original
|
|
* owner's filesystem: /userId/files/parent_folder/shared_folder
|
|
*
|
|
* This cannot be calculated with paths and IDs, the share's file source is required
|
|
*
|
|
* @param string $fileSource
|
|
*
|
|
* @return string
|
|
*/
|
|
private function buildFromRootToFolder($fileSource) {
|
|
$resource = $this->getResourceFromId($fileSource);
|
|
$fromRootToFolder = $resource->getPath() . '/';
|
|
|
|
return $fromRootToFolder;
|
|
}
|
|
|
|
/**
|
|
* Returns the path which goes from the file, up to the user folder, based on a path:
|
|
* parent_folder/current_folder/my_file
|
|
*
|
|
* getPath() on the file produces a path like:
|
|
* '/userId/files/my_folder/my_sub_folder/my_file'
|
|
*
|
|
* So we substract the path to the user folder, giving us a relative path
|
|
* 'my_folder/my_sub_folder'
|
|
*
|
|
* @param string $fullPath
|
|
*
|
|
* @return string
|
|
*/
|
|
private function getRelativePath($fullPath) {
|
|
$folderPath = $this->userFolder->getPath() . '/';
|
|
$origShareRelPath = str_replace($folderPath, '', $fullPath);
|
|
|
|
return $origShareRelPath;
|
|
}
|
|
|
|
}
|