public function testFindByStorageId() { /** @var \OCA\Files_External\Service\UserStoragesService $storageService */ $storageService = $this->getMockBuilder('\\OCA\\Files_External\\Service\\UserStoragesService')->disableOriginalConstructor()->getMock(); $storage = $this->getMockBuilder('\\OC\\Files\\Storage\\Storage')->disableOriginalConstructor()->getMock(); $storage->expects($this->any())->method('getId')->will($this->returnValue('dummy')); $mount = new PersonalMount($storageService, 10, $storage, '/foo'); $mountManager = new Manager(); $mountManager->addMount($mount); $this->assertEquals([$mount], $mountManager->findByStorageId('dummy')); }
public function testLong() { $storage = new LongId(array()); $mount = new \OC\Files\Mount\MountPoint($storage, '/foo'); $this->manager->addMount($mount); $id = $mount->getStorageId(); $storageId = $storage->getId(); $this->assertEquals(array($mount), $this->manager->findByStorageId($id)); $this->assertEquals(array($mount), $this->manager->findByStorageId($storageId)); $this->assertEquals(array($mount), $this->manager->findByStorageId(md5($storageId))); }
/** * mount an \OC\Files\Storage\Storage in our virtual filesystem * * @param \OC\Files\Storage\Storage|string $class * @param array $arguments * @param string $mountpoint */ static public function mount($class, $arguments, $mountpoint) { if (!self::$mounts) { \OC_Util::setupFS(); } $mount = new Mount\Mount($class, $mountpoint, $arguments, self::getLoader()); self::$mounts->addMount($mount); }
public function removeShare($mountPoint) { $mountPointObj = $this->mountManager->find($mountPoint); $id = $mountPointObj->getStorage()->getCache()->getId(''); $mountPoint = $this->stripPath($mountPoint); $hash = md5($mountPoint); $getShare = $this->connection->prepare(' SELECT `remote`, `share_token`, `remote_id` FROM `*PREFIX*share_external` WHERE `mountpoint_hash` = ? AND `user` = ?'); $result = $getShare->execute(array($hash, $this->uid)); if ($result) { $share = $getShare->fetch(); $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline'); } $getShare->closeCursor(); $query = $this->connection->prepare(' DELETE FROM `*PREFIX*share_external` WHERE `mountpoint_hash` = ? AND `user` = ? '); $result = (bool) $query->execute(array($hash, $this->uid)); if ($result) { $this->removeReShares($id); } return $result; }
/** * @param array $data * @return Mount */ protected function mountShare($data) { $data['manager'] = $this; $mountPoint = '/' . $this->userSession->getUser()->getUID() . '/files' . $data['mountpoint']; $data['mountpoint'] = $mountPoint; $mount = new Mount(self::STORAGE, $mountPoint, $data, $this, $this->storageLoader); $this->mountManager->addMount($mount); return $mount; }
/** * copy file between two storages * * @param Storage $sourceStorage * @param string $sourceInternalPath * @param string $targetInternalPath * @param bool $preserveMtime * @param bool $isRename * @return bool */ private function copyBetweenStorage(Storage $sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime, $isRename) { // first copy the keys that we reuse the existing file key on the target location // and don't create a new one which would break versions for example. $mount = $this->mountManager->findByStorageId($sourceStorage->getId()); if (count($mount) === 1) { $mountPoint = $mount[0]->getMountPoint(); $source = $mountPoint . '/' . $sourceInternalPath; $target = $this->getFullPath($targetInternalPath); $this->copyKeys($source, $target); } else { $this->logger->error('Could not find mount point, can\'t keep encryption keys'); } if ($sourceStorage->is_dir($sourceInternalPath)) { $dh = $sourceStorage->opendir($sourceInternalPath); $result = $this->mkdir($targetInternalPath); if (is_resource($dh)) { while ($result and ($file = readdir($dh)) !== false) { if (!Filesystem::isIgnoredDir($file)) { $result &= $this->copyFromStorage($sourceStorage, $sourceInternalPath . '/' . $file, $targetInternalPath . '/' . $file); } } } } else { try { $source = $sourceStorage->fopen($sourceInternalPath, 'r'); $target = $this->fopen($targetInternalPath, 'w'); list(, $result) = \OC_Helper::streamCopy($source, $target); fclose($source); fclose($target); } catch (\Exception $e) { fclose($source); fclose($target); throw $e; } if ($result) { if ($preserveMtime) { $this->touch($targetInternalPath, $sourceStorage->filemtime($sourceInternalPath)); } $isEncrypted = $this->encryptionManager->isEnabled() && $this->mount->getOption('encrypt', true) ? 1 : 0; // in case of a rename we need to manipulate the source cache because // this information will be kept for the new target if ($isRename) { $sourceStorage->getCache()->put($sourceInternalPath, ['encrypted' => $isEncrypted]); } else { $this->getCache()->put($targetInternalPath, ['encrypted' => $isEncrypted]); } } else { // delete partially written target file $this->unlink($targetInternalPath); // delete cache entry that was created by fopen $this->getCache()->remove($targetInternalPath); } } return (bool) $result; }
/** * Moves a file from one location to another * * @param string $sourcePath The path to the file which should be moved * @param string $destinationPath The full destination path, so not just the destination parent node * @throws \Sabre\DAV\Exception\BadRequest * @throws \Sabre\DAV\Exception\ServiceUnavailable * @throws \Sabre\DAV\Exception\Forbidden * @return int */ public function move($sourcePath, $destinationPath) { if (!$this->fileView) { throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup'); } $targetNodeExists = $this->nodeExists($destinationPath); $sourceNode = $this->getNodeForPath($sourcePath); if ($sourceNode instanceof \Sabre\DAV\ICollection && $targetNodeExists) { throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode . ', target exists'); } list($sourceDir, ) = \Sabre\HTTP\URLUtil::splitPath($sourcePath); list($destinationDir, ) = \Sabre\HTTP\URLUtil::splitPath($destinationPath); $isMovableMount = false; $sourceMount = $this->mountManager->find($this->fileView->getAbsolutePath($sourcePath)); $internalPath = $sourceMount->getInternalPath($this->fileView->getAbsolutePath($sourcePath)); if ($sourceMount instanceof MoveableMount && $internalPath === '') { $isMovableMount = true; } try { $sameFolder = $sourceDir === $destinationDir; // if we're overwriting or same folder if ($targetNodeExists || $sameFolder) { // note that renaming a share mount point is always allowed if (!$this->fileView->isUpdatable($destinationDir) && !$isMovableMount) { throw new \Sabre\DAV\Exception\Forbidden(); } } else { if (!$this->fileView->isCreatable($destinationDir)) { throw new \Sabre\DAV\Exception\Forbidden(); } } if (!$sameFolder) { // moving to a different folder, source will be gone, like a deletion // note that moving a share mount point is always allowed if (!$this->fileView->isDeletable($sourcePath) && !$isMovableMount) { throw new \Sabre\DAV\Exception\Forbidden(); } } $fileName = basename($destinationPath); try { $this->fileView->verifyPath($destinationDir, $fileName); } catch (\OCP\Files\InvalidPathException $ex) { throw new InvalidPath($ex->getMessage()); } $renameOkay = $this->fileView->rename($sourcePath, $destinationPath); if (!$renameOkay) { throw new \Sabre\DAV\Exception\Forbidden(''); } } catch (StorageNotAvailableException $e) { throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage()); } catch (LockedException $e) { throw new FileLocked($e->getMessage(), $e->getCode(), $e); } $this->markDirty($sourceDir); $this->markDirty($destinationDir); }
/** * @param array $data * @return Mount */ protected function mountShare($data) { $data['manager'] = $this; $mountPoint = '/' . $this->uid . '/files' . $data['mountpoint']; $data['mountpoint'] = $mountPoint; $data['certificateManager'] = \OC::$server->getCertificateManager($this->uid); $mount = new Mount(self::STORAGE, $mountPoint, $data, $this, $this->storageLoader); $this->mountManager->addMount($mount); return $mount; }
/** * Moves a file from one location to another * * @param string $sourcePath The path to the file which should be moved * @param string $destinationPath The full destination path, so not just the destination parent node * @throws \Sabre\DAV\Exception\BadRequest * @throws \Sabre\DAV\Exception\ServiceUnavailable * @throws \Sabre\DAV\Exception\Forbidden * @return int */ public function move($sourcePath, $destinationPath) { if (!$this->fileView) { throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup'); } $targetNodeExists = $this->nodeExists($destinationPath); $sourceNode = $this->getNodeForPath($sourcePath); if ($sourceNode instanceof \Sabre\DAV\ICollection && $targetNodeExists) { throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode . ', target exists'); } list($sourceDir, ) = \Sabre\DAV\URLUtil::splitPath($sourcePath); list($destinationDir, ) = \Sabre\DAV\URLUtil::splitPath($destinationPath); $isMovableMount = false; $sourceMount = $this->mountManager->find($this->fileView->getAbsolutePath($sourcePath)); $internalPath = $sourceMount->getInternalPath($this->fileView->getAbsolutePath($sourcePath)); if ($sourceMount instanceof MoveableMount && $internalPath === '') { $isMovableMount = true; } try { $sameFolder = $sourceDir === $destinationDir; // if we're overwriting or same folder if ($targetNodeExists || $sameFolder) { // note that renaming a share mount point is always allowed if (!$this->fileView->isUpdatable($destinationDir) && !$isMovableMount) { throw new \Sabre\DAV\Exception\Forbidden(); } } else { if (!$this->fileView->isCreatable($destinationDir)) { throw new \Sabre\DAV\Exception\Forbidden(); } } if (!$sameFolder) { // moving to a different folder, source will be gone, like a deletion // note that moving a share mount point is always allowed if (!$this->fileView->isDeletable($sourcePath) && !$isMovableMount) { throw new \Sabre\DAV\Exception\Forbidden(); } } $fileName = basename($destinationPath); if (!\OCP\Util::isValidFileName($fileName)) { throw new \Sabre\DAV\Exception\BadRequest(); } $renameOkay = $this->fileView->rename($sourcePath, $destinationPath); if (!$renameOkay) { throw new \Sabre\DAV\Exception\Forbidden(''); } } catch (\OCP\Files\StorageNotAvailableException $e) { throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage()); } // update properties $query = \OC_DB::prepare('UPDATE `*PREFIX*properties` SET `propertypath` = ?' . ' WHERE `userid` = ? AND `propertypath` = ?'); $query->execute(array(\OC\Files\Filesystem::normalizePath($destinationPath), \OC_User::getUser(), \OC\Files\Filesystem::normalizePath($sourcePath))); $this->markDirty($sourceDir); $this->markDirty($destinationDir); }
private function assertNotMount($mountPoint) { $mountPoint = rtrim($mountPoint, '/'); $mount = $this->mountManager->find($this->getFullPath($mountPoint)); if ($mount) { $this->assertInstanceOf('\\OCP\\Files\\Mount\\IMountPoint', $mount); $this->assertNotEquals($this->getFullPath($mountPoint), rtrim($mount->getMountPoint(), '/')); } else { $this->assertNull($mount); } }
/** * search file by id * * An array is returned because in the case where a single storage is mounted in different places the same file * can exist in different places * * @param int $id * @throws \OCP\Files\NotFoundException * @return Node[] */ public function getById($id) { $result = Cache::getById($id); if (is_null($result)) { throw new NotFoundException(); } else { list($storageId, $internalPath) = $result; $nodes = array(); $mounts = $this->mountManager->findByStorageId($storageId); foreach ($mounts as $mount) { $nodes[] = $this->get($mount->getMountPoint() . $internalPath); } return $nodes; } }
/** * Moves a file from one location to another * * @param string $sourcePath The path to the file which should be moved * @param string $destinationPath The full destination path, so not just the destination parent node * @throws \Sabre\DAV\Exception\BadRequest * @throws \Sabre\DAV\Exception\ServiceUnavailable * @throws \Sabre\DAV\Exception\Forbidden * @return int */ public function move($sourcePath, $destinationPath) { if (!$this->fileView) { throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup'); } $sourceNode = $this->getNodeForPath($sourcePath); if ($sourceNode instanceof \Sabre\DAV\ICollection and $this->nodeExists($destinationPath)) { throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode . ', target exists'); } list($sourceDir, ) = \Sabre\DAV\URLUtil::splitPath($sourcePath); list($destinationDir, ) = \Sabre\DAV\URLUtil::splitPath($destinationPath); $isMovableMount = false; $sourceMount = $this->mountManager->find($this->fileView->getAbsolutePath($sourcePath)); $internalPath = $sourceMount->getInternalPath($this->fileView->getAbsolutePath($sourcePath)); if ($sourceMount instanceof MoveableMount && $internalPath === '') { $isMovableMount = true; } try { // check update privileges if (!$this->fileView->isUpdatable($sourcePath) && !$isMovableMount) { throw new \Sabre\DAV\Exception\Forbidden(); } if ($sourceDir !== $destinationDir) { if (!$this->fileView->isCreatable($destinationDir)) { throw new \Sabre\DAV\Exception\Forbidden(); } if (!$this->fileView->isDeletable($sourcePath) && !$isMovableMount) { throw new \Sabre\DAV\Exception\Forbidden(); } } $fileName = basename($destinationPath); if (!\OCP\Util::isValidFileName($fileName)) { throw new \Sabre\DAV\Exception\BadRequest(); } $renameOkay = $this->fileView->rename($sourcePath, $destinationPath); if (!$renameOkay) { throw new \Sabre\DAV\Exception\Forbidden(''); } } catch (\OCP\Files\StorageNotAvailableException $e) { throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage()); } // update properties $query = \OC_DB::prepare('UPDATE `*PREFIX*properties` SET `propertypath` = ?' . ' WHERE `userid` = ? AND `propertypath` = ?'); $query->execute(array(\OC\Files\Filesystem::normalizePath($destinationPath), \OC_User::getUser(), \OC\Files\Filesystem::normalizePath($sourcePath))); $this->markDirty($sourceDir); $this->markDirty($destinationDir); }
/** * update keyfiles and share keys recursively * * @param int $fileSource file source id */ private function update($fileSource) { $path = \OC\Files\Filesystem::getPath($fileSource); $info = \OC\Files\Filesystem::getFileInfo($path); $owner = \OC\Files\Filesystem::getOwner($path); $view = new \OC\Files\View('/' . $owner . '/files'); $ownerPath = $view->getPath($info->getId()); $absPath = '/' . $owner . '/files' . $ownerPath; $mount = $this->mountManager->find($path); $mountPoint = $mount->getMountPoint(); // if a folder was shared, get a list of all (sub-)folders if ($this->view->is_dir($absPath)) { $allFiles = $this->util->getAllFiles($absPath, $mountPoint); } else { $allFiles = array($absPath); } $encryptionModule = $this->encryptionManager->getDefaultEncryptionModule(); foreach ($allFiles as $path) { $usersSharing = $this->file->getAccessList($path); $encryptionModule->update($path, $this->uid, $usersSharing); } }
/** * @param \OC\Files\Mount\MountPoint $mount */ public function unMount($mount) { $this->mountManager->remove($mount); }
/** * @param array $data * @return Mount */ protected function mountShare($data) { $mount = $this->getMount($data); $this->mountManager->addMount($mount); return $mount; }
/** * copy file between two storages * * @param Storage $sourceStorage * @param string $sourceInternalPath * @param string $targetInternalPath * @param bool $preserveMtime * @param bool $isRename * @return bool * @throws \Exception */ private function copyBetweenStorage(Storage $sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime, $isRename) { // for versions we have nothing to do, because versions should always use the // key from the original file. Just create a 1:1 copy and done if ($this->isVersion($targetInternalPath) || $this->isVersion($sourceInternalPath)) { // remember that we try to create a version so that we can detect it during // fopen($sourceInternalPath) and by-pass the encryption in order to // create a 1:1 copy of the file $this->arrayCache->set('encryption_copy_version_' . $sourceInternalPath, true); $result = $this->storage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); $this->arrayCache->remove('encryption_copy_version_' . $sourceInternalPath); if ($result) { $info = $this->getCache('', $sourceStorage)->get($sourceInternalPath); // make sure that we update the unencrypted size for the version if (isset($info['encrypted']) && $info['encrypted'] === true) { $this->updateUnencryptedSize($this->getFullPath($targetInternalPath), $info['size']); } $this->updateEncryptedVersion($sourceStorage, $sourceInternalPath, $targetInternalPath, $isRename); } return $result; } // first copy the keys that we reuse the existing file key on the target location // and don't create a new one which would break versions for example. $mount = $this->mountManager->findByStorageId($sourceStorage->getId()); if (count($mount) === 1) { $mountPoint = $mount[0]->getMountPoint(); $source = $mountPoint . '/' . $sourceInternalPath; $target = $this->getFullPath($targetInternalPath); $this->copyKeys($source, $target); } else { $this->logger->error('Could not find mount point, can\'t keep encryption keys'); } if ($sourceStorage->is_dir($sourceInternalPath)) { $dh = $sourceStorage->opendir($sourceInternalPath); $result = $this->mkdir($targetInternalPath); if (is_resource($dh)) { while ($result and ($file = readdir($dh)) !== false) { if (!Filesystem::isIgnoredDir($file)) { $result &= $this->copyFromStorage($sourceStorage, $sourceInternalPath . '/' . $file, $targetInternalPath . '/' . $file, false, $isRename); } } } } else { try { $source = $sourceStorage->fopen($sourceInternalPath, 'r'); $target = $this->fopen($targetInternalPath, 'w'); list(, $result) = \OC_Helper::streamCopy($source, $target); fclose($source); fclose($target); } catch (\Exception $e) { fclose($source); fclose($target); throw $e; } if ($result) { if ($preserveMtime) { $this->touch($targetInternalPath, $sourceStorage->filemtime($sourceInternalPath)); } $this->updateEncryptedVersion($sourceStorage, $sourceInternalPath, $targetInternalPath, $isRename); } else { // delete partially written target file $this->unlink($targetInternalPath); // delete cache entry that was created by fopen $this->getCache()->remove($targetInternalPath); } } return (bool) $result; }