diff options
Diffstat (limited to 'lib/private/files/node/folder.php')
-rw-r--r-- | lib/private/files/node/folder.php | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/lib/private/files/node/folder.php b/lib/private/files/node/folder.php new file mode 100644 index 00000000000..923f53821b2 --- /dev/null +++ b/lib/private/files/node/folder.php @@ -0,0 +1,382 @@ +<?php +/** + * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files\Node; + +use OC\Files\Cache\Cache; +use OC\Files\Cache\Scanner; +use OCP\Files\NotFoundException; +use OCP\Files\NotPermittedException; + +class Folder extends Node implements \OCP\Files\Folder { + /** + * @param string $path path relative to the folder + * @return string + * @throws \OCP\Files\NotPermittedException + */ + public function getFullPath($path) { + if (!$this->isValidPath($path)) { + throw new NotPermittedException(); + } + return $this->path . $this->normalizePath($path); + } + + /** + * @param string $path + * @throws \OCP\Files\NotFoundException + * @return string + */ + public function getRelativePath($path) { + if ($this->path === '' or $this->path === '/') { + return $this->normalizePath($path); + } + if (strpos($path, $this->path) !== 0) { + throw new NotFoundException(); + } else { + $path = substr($path, strlen($this->path)); + if (strlen($path) === 0) { + return '/'; + } else { + return $this->normalizePath($path); + } + } + } + + /** + * check if a node is a (grand-)child of the folder + * + * @param \OC\Files\Node\Node $node + * @return bool + */ + public function isSubNode($node) { + return strpos($node->getPath(), $this->path . '/') === 0; + } + + /** + * get the content of this directory + * + * @throws \OCP\Files\NotFoundException + * @return Node[] + */ + public function getDirectoryListing() { + $result = array(); + + /** + * @var \OC\Files\Storage\Storage $storage + */ + list($storage, $internalPath) = $this->view->resolvePath($this->path); + if ($storage) { + $cache = $storage->getCache($internalPath); + $permissionsCache = $storage->getPermissionsCache($internalPath); + + //trigger cache update check + $this->view->getFileInfo($this->path); + + $files = $cache->getFolderContents($internalPath); + $permissions = $permissionsCache->getDirectoryPermissions($this->getId(), $this->root->getUser()->getUID()); + } else { + $files = array(); + } + + //add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders + $mounts = $this->root->getMountsIn($this->path); + $dirLength = strlen($this->path); + foreach ($mounts as $mount) { + $subStorage = $mount->getStorage(); + if ($subStorage) { + $subCache = $subStorage->getCache(''); + + if ($subCache->getStatus('') === Cache::NOT_FOUND) { + $subScanner = $subStorage->getScanner(''); + $subScanner->scanFile(''); + } + + $rootEntry = $subCache->get(''); + if ($rootEntry) { + $relativePath = trim(substr($mount->getMountPoint(), $dirLength), '/'); + if ($pos = strpos($relativePath, '/')) { + //mountpoint inside subfolder add size to the correct folder + $entryName = substr($relativePath, 0, $pos); + foreach ($files as &$entry) { + if ($entry['name'] === $entryName) { + if ($rootEntry['size'] >= 0) { + $entry['size'] += $rootEntry['size']; + } else { + $entry['size'] = -1; + } + } + } + } else { //mountpoint in this folder, add an entry for it + $rootEntry['name'] = $relativePath; + $rootEntry['storageObject'] = $subStorage; + + //remove any existing entry with the same name + foreach ($files as $i => $file) { + if ($file['name'] === $rootEntry['name']) { + $files[$i] = null; + break; + } + } + $files[] = $rootEntry; + } + } + } + } + + foreach ($files as $file) { + if ($file) { + if (isset($permissions[$file['fileid']])) { + $file['permissions'] = $permissions[$file['fileid']]; + } + $node = $this->createNode($this->path . '/' . $file['name'], $file); + $result[] = $node; + } + } + + return $result; + } + + /** + * @param string $path + * @param array $info + * @return File|Folder + */ + protected function createNode($path, $info = array()) { + if (!isset($info['mimetype'])) { + $isDir = $this->view->is_dir($path); + } else { + $isDir = $info['mimetype'] === 'httpd/unix-directory'; + } + if ($isDir) { + return new Folder($this->root, $this->view, $path); + } else { + return new File($this->root, $this->view, $path); + } + } + + /** + * Get the node at $path + * + * @param string $path + * @return \OC\Files\Node\Node + * @throws \OCP\Files\NotFoundException + */ + public function get($path) { + return $this->root->get($this->getFullPath($path)); + } + + /** + * @param string $path + * @return bool + */ + public function nodeExists($path) { + try { + $this->get($path); + return true; + } catch (NotFoundException $e) { + return false; + } + } + + /** + * @param string $path + * @return \OC\Files\Node\Folder + * @throws \OCP\Files\NotPermittedException + */ + public function newFolder($path) { + if ($this->checkPermissions(\OCP\PERMISSION_CREATE)) { + $fullPath = $this->getFullPath($path); + $nonExisting = new NonExistingFolder($this->root, $this->view, $fullPath); + $this->root->emit('\OC\Files', 'preWrite', array($nonExisting)); + $this->root->emit('\OC\Files', 'preCreate', array($nonExisting)); + $this->view->mkdir($fullPath); + $node = new Folder($this->root, $this->view, $fullPath); + $this->root->emit('\OC\Files', 'postWrite', array($node)); + $this->root->emit('\OC\Files', 'postCreate', array($node)); + return $node; + } else { + throw new NotPermittedException(); + } + } + + /** + * @param string $path + * @return \OC\Files\Node\File + * @throws \OCP\Files\NotPermittedException + */ + public function newFile($path) { + if ($this->checkPermissions(\OCP\PERMISSION_CREATE)) { + $fullPath = $this->getFullPath($path); + $nonExisting = new NonExistingFile($this->root, $this->view, $fullPath); + $this->root->emit('\OC\Files', 'preWrite', array($nonExisting)); + $this->root->emit('\OC\Files', 'preCreate', array($nonExisting)); + $this->view->touch($fullPath); + $node = new File($this->root, $this->view, $fullPath); + $this->root->emit('\OC\Files', 'postWrite', array($node)); + $this->root->emit('\OC\Files', 'postCreate', array($node)); + return $node; + } else { + throw new NotPermittedException(); + } + } + + /** + * search for files with the name matching $query + * + * @param string $query + * @return \OC\Files\Node\Node[] + */ + public function search($query) { + return $this->searchCommon('%' . $query . '%', 'search'); + } + + /** + * search for files by mimetype + * + * @param string $mimetype + * @return Node[] + */ + public function searchByMime($mimetype) { + return $this->searchCommon($mimetype, 'searchByMime'); + } + + /** + * @param string $query + * @param string $method + * @return \OC\Files\Node\Node[] + */ + private function searchCommon($query, $method) { + $files = array(); + $rootLength = strlen($this->path); + /** + * @var \OC\Files\Storage\Storage $storage + */ + list($storage, $internalPath) = $this->view->resolvePath($this->path); + $internalRootLength = strlen($internalPath); + + $cache = $storage->getCache(''); + + $results = $cache->$method($query); + foreach ($results as $result) { + if ($internalRootLength === 0 or substr($result['path'], 0, $internalRootLength) === $internalPath) { + $result['internalPath'] = $result['path']; + $result['path'] = substr($result['path'], $internalRootLength); + $result['storage'] = $storage; + $files[] = $result; + } + } + + $mounts = $this->root->getMountsIn($this->path); + foreach ($mounts as $mount) { + $storage = $mount->getStorage(); + if ($storage) { + $cache = $storage->getCache(''); + + $relativeMountPoint = substr($mount->getMountPoint(), $rootLength); + $results = $cache->$method($query); + foreach ($results as $result) { + $result['internalPath'] = $result['path']; + $result['path'] = $relativeMountPoint . $result['path']; + $result['storage'] = $storage; + $files[] = $result; + } + } + } + + $result = array(); + foreach ($files as $file) { + $result[] = $this->createNode($this->normalizePath($this->path . '/' . $file['path']), $file); + } + + return $result; + } + + /** + * @param $id + * @return \OC\Files\Node\Node[] + */ + public function getById($id) { + $nodes = $this->root->getById($id); + $result = array(); + foreach ($nodes as $node) { + $pathPart = substr($node->getPath(), 0, strlen($this->getPath()) + 1); + if ($this->path === '/' or $pathPart === $this->getPath() . '/') { + $result[] = $node; + } + } + return $result; + } + + public function getFreeSpace() { + return $this->view->free_space($this->path); + } + + /** + * @return bool + */ + public function isCreatable() { + return $this->checkPermissions(\OCP\PERMISSION_CREATE); + } + + public function delete() { + if ($this->checkPermissions(\OCP\PERMISSION_DELETE)) { + $this->sendHooks(array('preDelete')); + $this->view->rmdir($this->path); + $nonExisting = new NonExistingFolder($this->root, $this->view, $this->path); + $this->root->emit('\OC\Files', 'postDelete', array($nonExisting)); + $this->exists = false; + } else { + throw new NotPermittedException(); + } + } + + /** + * @param string $targetPath + * @throws \OCP\Files\NotPermittedException + * @return \OC\Files\Node\Node + */ + public function copy($targetPath) { + $targetPath = $this->normalizePath($targetPath); + $parent = $this->root->get(dirname($targetPath)); + if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) { + $nonExisting = new NonExistingFolder($this->root, $this->view, $targetPath); + $this->root->emit('\OC\Files', 'preCopy', array($this, $nonExisting)); + $this->root->emit('\OC\Files', 'preWrite', array($nonExisting)); + $this->view->copy($this->path, $targetPath); + $targetNode = $this->root->get($targetPath); + $this->root->emit('\OC\Files', 'postCopy', array($this, $targetNode)); + $this->root->emit('\OC\Files', 'postWrite', array($targetNode)); + return $targetNode; + } else { + throw new NotPermittedException(); + } + } + + /** + * @param string $targetPath + * @throws \OCP\Files\NotPermittedException + * @return \OC\Files\Node\Node + */ + public function move($targetPath) { + $targetPath = $this->normalizePath($targetPath); + $parent = $this->root->get(dirname($targetPath)); + if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) { + $nonExisting = new NonExistingFolder($this->root, $this->view, $targetPath); + $this->root->emit('\OC\Files', 'preRename', array($this, $nonExisting)); + $this->root->emit('\OC\Files', 'preWrite', array($nonExisting)); + $this->view->rename($this->path, $targetPath); + $targetNode = $this->root->get($targetPath); + $this->root->emit('\OC\Files', 'postRename', array($this, $targetNode)); + $this->root->emit('\OC\Files', 'postWrite', array($targetNode)); + $this->path = $targetPath; + return $targetNode; + } else { + throw new NotPermittedException(); + } + } +} |