diff options
author | Vincent Petry <pvince81@owncloud.com> | 2016-05-25 15:40:05 +0200 |
---|---|---|
committer | Vincent Petry <pvince81@owncloud.com> | 2016-05-25 15:40:05 +0200 |
commit | d22aeb749d22590c4caf630fd390dabca6e2c724 (patch) | |
tree | 34ee255a19177a99504b4b5f652b071dc268cf3b /apps/files_sharing/lib/SharedMount.php | |
parent | 7f20203006d1a8ac1ba4d367044b9a0613a3fb59 (diff) | |
parent | 3f0b2d148d875a2a4961a5b27309d379b9de1329 (diff) | |
download | nextcloud-server-d22aeb749d22590c4caf630fd390dabca6e2c724.tar.gz nextcloud-server-d22aeb749d22590c4caf630fd390dabca6e2c724.zip |
Merge pull request #24661 from owncloud/files_sharing-psr4
Move Files_Sharing to PSR-4
Diffstat (limited to 'apps/files_sharing/lib/SharedMount.php')
-rw-r--r-- | apps/files_sharing/lib/SharedMount.php | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/apps/files_sharing/lib/SharedMount.php b/apps/files_sharing/lib/SharedMount.php new file mode 100644 index 00000000000..4aed80b12b2 --- /dev/null +++ b/apps/files_sharing/lib/SharedMount.php @@ -0,0 +1,226 @@ +<?php +/** + * @author Björn Schießle <schiessle@owncloud.com> + * @author Joas Schilling <nickvergessen@owncloud.com> + * @author Morris Jobke <hey@morrisjobke.de> + * @author Robin Appelman <icewind@owncloud.com> + * @author Roeland Jago Douma <rullzer@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\Files_Sharing; + +use OC\Files\Filesystem; +use OC\Files\Mount\MountPoint; +use OC\Files\Mount\MoveableMount; +use OC\Files\View; + +/** + * Shared mount points can be moved by the user + */ +class SharedMount extends MountPoint implements MoveableMount { + /** + * @var \OC\Files\Storage\Shared $storage + */ + protected $storage = null; + + /** + * @var \OC\Files\View + */ + private $recipientView; + + /** + * @var string + */ + private $user; + + /** @var \OCP\Share\IShare */ + private $share; + + /** + * @param string $storage + * @param SharedMount[] $mountpoints + * @param array|null $arguments + * @param \OCP\Files\Storage\IStorageFactory $loader + */ + public function __construct($storage, array $mountpoints, $arguments = null, $loader = null) { + $this->user = $arguments['user']; + $this->recipientView = new View('/' . $this->user . '/files'); + $this->share = $arguments['newShare']; + $newMountPoint = $this->verifyMountPoint($this->share, $mountpoints); + $absMountPoint = '/' . $this->user . '/files' . $newMountPoint; + $arguments['ownerView'] = new View('/' . $this->share->getShareOwner() . '/files'); + parent::__construct($storage, $absMountPoint, $arguments, $loader); + } + + /** + * check if the parent folder exists otherwise move the mount point up + * + * @param \OCP\Share\IShare $share + * @param SharedMount[] $mountpoints + * @return string + */ + private function verifyMountPoint(\OCP\Share\IShare $share, array $mountpoints) { + + $mountPoint = basename($share->getTarget()); + $parent = dirname($share->getTarget()); + + if (!$this->recipientView->is_dir($parent)) { + $parent = Helper::getShareFolder(); + } + + $newMountPoint = $this->generateUniqueTarget( + \OC\Files\Filesystem::normalizePath($parent . '/' . $mountPoint), + $this->recipientView, + $mountpoints + ); + + if ($newMountPoint !== $share->getTarget()) { + $this->updateFileTarget($newMountPoint, $share); + } + + return $newMountPoint; + } + + /** + * update fileTarget in the database if the mount point changed + * + * @param string $newPath + * @param \OCP\Share\IShare $share + * @return bool + */ + private function updateFileTarget($newPath, &$share) { + $share->setTarget($newPath); + \OC::$server->getShareManager()->moveShare($share, $this->user); + } + + + /** + * @param string $path + * @param View $view + * @param SharedMount[] $mountpoints + * @return mixed + */ + private function generateUniqueTarget($path, $view, array $mountpoints) { + $pathinfo = pathinfo($path); + $ext = (isset($pathinfo['extension'])) ? '.'.$pathinfo['extension'] : ''; + $name = $pathinfo['filename']; + $dir = $pathinfo['dirname']; + + // Helper function to find existing mount points + $mountpointExists = function($path) use ($mountpoints) { + foreach ($mountpoints as $mountpoint) { + if ($mountpoint->getShare()->getTarget() === $path) { + return true; + } + } + return false; + }; + + $i = 2; + while ($view->file_exists($path) || $mountpointExists($path)) { + $path = Filesystem::normalizePath($dir . '/' . $name . ' ('.$i.')' . $ext); + $i++; + } + + return $path; + } + + /** + * Format a path to be relative to the /user/files/ directory + * + * @param string $path the absolute path + * @return string e.g. turns '/admin/files/test.txt' into '/test.txt' + * @throws \OCA\Files_Sharing\Exceptions\BrokenPath + */ + protected function stripUserFilesPath($path) { + $trimmed = ltrim($path, '/'); + $split = explode('/', $trimmed); + + // it is not a file relative to data/user/files + if (count($split) < 3 || $split[1] !== 'files') { + \OCP\Util::writeLog('file sharing', + 'Can not strip userid and "files/" from path: ' . $path, + \OCP\Util::ERROR); + throw new \OCA\Files_Sharing\Exceptions\BrokenPath('Path does not start with /user/files', 10); + } + + // skip 'user' and 'files' + $sliced = array_slice($split, 2); + $relPath = implode('/', $sliced); + + return '/' . $relPath; + } + + /** + * Move the mount point to $target + * + * @param string $target the target mount point + * @return bool + */ + public function moveMount($target) { + + $relTargetPath = $this->stripUserFilesPath($target); + $share = $this->storage->getShare(); + + $result = true; + + try { + $this->updateFileTarget($relTargetPath, $share); + $this->setMountPoint($target); + $this->storage->setMountPoint($relTargetPath); + } catch (\Exception $e) { + \OCP\Util::writeLog('file sharing', + 'Could not rename mount point for shared folder "' . $this->getMountPoint() . '" to "' . $target . '"', + \OCP\Util::ERROR); + } + + return $result; + } + + /** + * Remove the mount points + * + * @return bool + */ + public function removeMount() { + $mountManager = \OC\Files\Filesystem::getMountManager(); + /** @var $storage \OC\Files\Storage\Shared */ + $storage = $this->getStorage(); + $result = $storage->unshareStorage(); + $mountManager->removeMount($this->mountPoint); + + return $result; + } + + /** + * @return \OCP\Share\IShare + */ + public function getShare() { + return $this->share; + } + + /** + * Get the file id of the root of the storage + * + * @return int + */ + public function getStorageRootId() { + return $this->share->getNodeId(); + } +} |