diff options
Diffstat (limited to 'apps/dav/lib/Connector/Sabre/Node.php')
-rw-r--r-- | apps/dav/lib/Connector/Sabre/Node.php | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/apps/dav/lib/Connector/Sabre/Node.php b/apps/dav/lib/Connector/Sabre/Node.php new file mode 100644 index 00000000000..ccc035063cd --- /dev/null +++ b/apps/dav/lib/Connector/Sabre/Node.php @@ -0,0 +1,348 @@ +<?php +/** + * @author Arthur Schiwon <blizzz@owncloud.com> + * @author Bart Visscher <bartv@thisnet.nl> + * @author Jakob Sack <mail@jakobsack.de> + * @author Jörn Friedrich Dreyer <jfd@butonic.de> + * @author Klaas Freitag <freitag@owncloud.com> + * @author Markus Goetz <markus@woboq.com> + * @author Morris Jobke <hey@morrisjobke.de> + * @author Robin Appelman <icewind@owncloud.com> + * @author Thomas Müller <thomas.mueller@tmit.eu> + * @author Vincent Petry <pvince81@owncloud.com> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\Connector\Sabre; + +use OC\Files\Mount\MoveableMount; +use OCA\DAV\Connector\Sabre\Exception\InvalidPath; +use OCP\Share\Exceptions\ShareNotFound; +use OCP\Share\IManager; + + +abstract class Node implements \Sabre\DAV\INode { + + /** + * @var \OC\Files\View + */ + protected $fileView; + + /** + * The path to the current node + * + * @var string + */ + protected $path; + + /** + * node properties cache + * + * @var array + */ + protected $property_cache = null; + + /** + * @var \OCP\Files\FileInfo + */ + protected $info; + + /** + * @var IManager + */ + protected $shareManager; + + /** + * Sets up the node, expects a full path name + * + * @param \OC\Files\View $view + * @param \OCP\Files\FileInfo $info + * @param IManager $shareManager + */ + public function __construct($view, $info, IManager $shareManager = null) { + $this->fileView = $view; + $this->path = $this->fileView->getRelativePath($info->getPath()); + $this->info = $info; + if ($shareManager) { + $this->shareManager = $shareManager; + } else { + $this->shareManager = \OC::$server->getShareManager(); + } + } + + protected function refreshInfo() { + $this->info = $this->fileView->getFileInfo($this->path); + } + + /** + * Returns the name of the node + * + * @return string + */ + public function getName() { + return $this->info->getName(); + } + + /** + * Returns the full path + * + * @return string + */ + public function getPath() { + return $this->path; + } + + /** + * Renames the node + * + * @param string $name The new name + * @throws \Sabre\DAV\Exception\BadRequest + * @throws \Sabre\DAV\Exception\Forbidden + */ + public function setName($name) { + + // rename is only allowed if the update privilege is granted + if (!$this->info->isUpdateable()) { + throw new \Sabre\DAV\Exception\Forbidden(); + } + + list($parentPath,) = \Sabre\HTTP\URLUtil::splitPath($this->path); + list(, $newName) = \Sabre\HTTP\URLUtil::splitPath($name); + + // verify path of the target + $this->verifyPath(); + + $newPath = $parentPath . '/' . $newName; + + $this->fileView->rename($this->path, $newPath); + + $this->path = $newPath; + + $this->refreshInfo(); + } + + public function setPropertyCache($property_cache) { + $this->property_cache = $property_cache; + } + + /** + * Returns the last modification time, as a unix timestamp + * + * @return int timestamp as integer + */ + public function getLastModified() { + $timestamp = $this->info->getMtime(); + if (!empty($timestamp)) { + return (int)$timestamp; + } + return $timestamp; + } + + /** + * sets the last modification time of the file (mtime) to the value given + * in the second parameter or to now if the second param is empty. + * Even if the modification time is set to a custom value the access time is set to now. + */ + public function touch($mtime) { + $this->fileView->touch($this->path, $mtime); + $this->refreshInfo(); + } + + /** + * Returns the ETag for a file + * + * An ETag is a unique identifier representing the current version of the + * file. If the file changes, the ETag MUST change. The ETag is an + * arbitrary string, but MUST be surrounded by double-quotes. + * + * Return null if the ETag can not effectively be determined + * + * @return string + */ + public function getETag() { + return '"' . $this->info->getEtag() . '"'; + } + + /** + * Sets the ETag + * + * @param string $etag + * + * @return int file id of updated file or -1 on failure + */ + public function setETag($etag) { + return $this->fileView->putFileInfo($this->path, array('etag' => $etag)); + } + + /** + * Returns the size of the node, in bytes + * + * @return integer + */ + public function getSize() { + return $this->info->getSize(); + } + + /** + * Returns the cache's file id + * + * @return int + */ + public function getId() { + return $this->info->getId(); + } + + /** + * @return string|null + */ + public function getFileId() { + if ($this->info->getId()) { + $instanceId = \OC_Util::getInstanceId(); + $id = sprintf('%08d', $this->info->getId()); + return $id . $instanceId; + } + + return null; + } + + /** + * @return integer + */ + public function getInternalFileId() { + return $this->info->getId(); + } + + /** + * @param string $user + * @return int + */ + public function getSharePermissions($user) { + + // check of we access a federated share + if ($user !== null) { + try { + $share = $this->shareManager->getShareByToken($user); + return $share->getPermissions(); + } catch (ShareNotFound $e) { + // ignore + } + } + + $storage = $this->info->getStorage(); + + $path = $this->info->getInternalPath(); + + if ($storage->instanceOfStorage('\OC\Files\Storage\Shared')) { + /** @var \OC\Files\Storage\Shared $storage */ + $permissions = (int)$storage->getShare()->getPermissions(); + } else { + $permissions = $storage->getPermissions($path); + } + + /* + * We can always share non moveable mount points with DELETE and UPDATE + * Eventually we need to do this properly + */ + $mountpoint = $this->info->getMountPoint(); + if (!($mountpoint instanceof MoveableMount)) { + $mountpointpath = $mountpoint->getMountPoint(); + if (substr($mountpointpath, -1) === '/') { + $mountpointpath = substr($mountpointpath, 0, -1); + } + + if ($mountpointpath === $this->info->getPath()) { + $permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE; + } + } + + /* + * Files can't have create or delete permissions + */ + if ($this->info->getType() === \OCP\Files\FileInfo::TYPE_FILE) { + $permissions &= ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE); + } + + return $permissions; + } + + /** + * @return string + */ + public function getDavPermissions() { + $p = ''; + if ($this->info->isShared()) { + $p .= 'S'; + } + if ($this->info->isShareable()) { + $p .= 'R'; + } + if ($this->info->isMounted()) { + $p .= 'M'; + } + if ($this->info->isDeletable()) { + $p .= 'D'; + } + if ($this->info->isUpdateable()) { + $p .= 'NV'; // Renameable, Moveable + } + if ($this->info->getType() === \OCP\Files\FileInfo::TYPE_FILE) { + if ($this->info->isUpdateable()) { + $p .= 'W'; + } + } else { + if ($this->info->isCreatable()) { + $p .= 'CK'; + } + } + return $p; + } + + public function getOwner() { + return $this->info->getOwner(); + } + + protected function verifyPath() { + try { + $fileName = basename($this->info->getPath()); + $this->fileView->verifyPath($this->path, $fileName); + } catch (\OCP\Files\InvalidPathException $ex) { + throw new InvalidPath($ex->getMessage()); + } + } + + /** + * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE + */ + public function acquireLock($type) { + $this->fileView->lockFile($this->path, $type); + } + + /** + * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE + */ + public function releaseLock($type) { + $this->fileView->unlockFile($this->path, $type); + } + + /** + * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE + */ + public function changeLock($type) { + $this->fileView->changeLock($this->path, $type); + } +} |