parent
a2172786a8
commit
abb6e89c5d
@ -0,0 +1,255 @@ |
||||
<?php |
||||
/** |
||||
* Copyright (c) 2014 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\Cache\Wrapper; |
||||
|
||||
/** |
||||
* Jail to a subdirectory of the wrapped cache |
||||
*/ |
||||
class CacheJail extends CacheWrapper { |
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $root; |
||||
|
||||
/** |
||||
* @param \OC\Files\Cache\Cache $cache |
||||
* @param string $root |
||||
*/ |
||||
public function __construct($cache, $root) { |
||||
parent::__construct($cache); |
||||
$this->root = $root; |
||||
} |
||||
|
||||
protected function getSourcePath($path) { |
||||
if ($path === '') { |
||||
return $this->root; |
||||
} else { |
||||
return $this->root . '/' . $path; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @param string $path |
||||
* @return null|string the jailed path or null if the path is outside the jail |
||||
*/ |
||||
protected function getJailedPath($path) { |
||||
$rootLength = strlen($this->root) + 1; |
||||
if ($path === $this->root) { |
||||
return ''; |
||||
} else if (substr($path, 0, $rootLength) === $this->root . '/') { |
||||
return substr($path, $rootLength); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @param array $entry |
||||
* @return array |
||||
*/ |
||||
protected function formatCacheEntry($entry) { |
||||
if (isset($entry['path'])) { |
||||
$entry['path'] = $this->getJailedPath($entry['path']); |
||||
} |
||||
return $entry; |
||||
} |
||||
|
||||
protected function filterCacheEntry($entry) { |
||||
$rootLength = strlen($this->root) + 1; |
||||
return ($entry['path'] === $this->root) or (substr($entry['path'], 0, $rootLength) === $this->root . '/'); |
||||
} |
||||
|
||||
/** |
||||
* get the stored metadata of a file or folder |
||||
* |
||||
* @param string /int $file |
||||
* @return array|false |
||||
*/ |
||||
public function get($file) { |
||||
if (is_string($file) or $file == '') { |
||||
$file = $this->getSourcePath($file); |
||||
} |
||||
return parent::get($file); |
||||
} |
||||
|
||||
/** |
||||
* store meta data for a file or folder |
||||
* |
||||
* @param string $file |
||||
* @param array $data |
||||
* |
||||
* @return int file id |
||||
*/ |
||||
public function put($file, array $data) { |
||||
return $this->cache->put($this->getSourcePath($file), $data); |
||||
} |
||||
|
||||
/** |
||||
* update the metadata in the cache |
||||
* |
||||
* @param int $id |
||||
* @param array $data |
||||
*/ |
||||
public function update($id, array $data) { |
||||
$this->cache->update($this->getSourcePath($id), $data); |
||||
} |
||||
|
||||
/** |
||||
* get the file id for a file |
||||
* |
||||
* @param string $file |
||||
* @return int |
||||
*/ |
||||
public function getId($file) { |
||||
return $this->cache->getId($this->getSourcePath($file)); |
||||
} |
||||
|
||||
/** |
||||
* get the id of the parent folder of a file |
||||
* |
||||
* @param string $file |
||||
* @return int |
||||
*/ |
||||
public function getParentId($file) { |
||||
if ($file === '') { |
||||
return -1; |
||||
} else { |
||||
return $this->cache->getParentId($this->getSourcePath($file)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* check if a file is available in the cache |
||||
* |
||||
* @param string $file |
||||
* @return bool |
||||
*/ |
||||
public function inCache($file) { |
||||
return $this->cache->inCache($this->getSourcePath($file)); |
||||
} |
||||
|
||||
/** |
||||
* remove a file or folder from the cache |
||||
* |
||||
* @param string $file |
||||
*/ |
||||
public function remove($file) { |
||||
$this->cache->remove($this->getSourcePath($file)); |
||||
} |
||||
|
||||
/** |
||||
* Move a file or folder in the cache |
||||
* |
||||
* @param string $source |
||||
* @param string $target |
||||
*/ |
||||
public function move($source, $target) { |
||||
$this->cache->move($this->getSourcePath($source), $this->getSourcePath($target)); |
||||
} |
||||
|
||||
/** |
||||
* remove all entries for files that are stored on the storage from the cache |
||||
*/ |
||||
public function clear() { |
||||
$this->cache->remove($this->root); |
||||
} |
||||
|
||||
/** |
||||
* @param string $file |
||||
* |
||||
* @return int, Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE |
||||
*/ |
||||
public function getStatus($file) { |
||||
return $this->cache->getStatus($this->getSourcePath($file)); |
||||
} |
||||
|
||||
private function formatSearchResults($results) { |
||||
$results = array_filter($results, array($this, 'filterCacheEntry')); |
||||
$results = array_values($results); |
||||
return array_map(array($this, 'formatCacheEntry'), $results); |
||||
} |
||||
|
||||
/** |
||||
* search for files matching $pattern |
||||
* |
||||
* @param string $pattern |
||||
* @return array an array of file data |
||||
*/ |
||||
public function search($pattern) { |
||||
$results = $this->cache->search($pattern); |
||||
return $this->formatSearchResults($results); |
||||
} |
||||
|
||||
/** |
||||
* search for files by mimetype |
||||
* |
||||
* @param string $mimetype |
||||
* @return array |
||||
*/ |
||||
public function searchByMime($mimetype) { |
||||
$results = $this->cache->searchByMime($mimetype); |
||||
return $this->formatSearchResults($results); |
||||
} |
||||
|
||||
/** |
||||
* update the folder size and the size of all parent folders |
||||
* |
||||
* @param string|boolean $path |
||||
* @param array $data (optional) meta data of the folder |
||||
*/ |
||||
public function correctFolderSize($path, $data = null) { |
||||
$this->cache->correctFolderSize($this->getSourcePath($path), $data); |
||||
} |
||||
|
||||
/** |
||||
* get the size of a folder and set it in the cache |
||||
* |
||||
* @param string $path |
||||
* @param array $entry (optional) meta data of the folder |
||||
* @return int |
||||
*/ |
||||
public function calculateFolderSize($path, $entry = null) { |
||||
return $this->cache->calculateFolderSize($this->getSourcePath($path), $entry); |
||||
} |
||||
|
||||
/** |
||||
* get all file ids on the files on the storage |
||||
* |
||||
* @return int[] |
||||
*/ |
||||
public function getAll() { |
||||
// not supported |
||||
return array(); |
||||
} |
||||
|
||||
/** |
||||
* find a folder in the cache which has not been fully scanned |
||||
* |
||||
* If multiply incomplete folders are in the cache, the one with the highest id will be returned, |
||||
* use the one with the highest id gives the best result with the background scanner, since that is most |
||||
* likely the folder where we stopped scanning previously |
||||
* |
||||
* @return string|bool the path of the folder or false when no folder matched |
||||
*/ |
||||
public function getIncomplete() { |
||||
// not supported |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* get the path of a file on this storage by it's id |
||||
* |
||||
* @param int $id |
||||
* @return string|null |
||||
*/ |
||||
public function getPathById($id) { |
||||
$path = $this->cache->getPathById($id); |
||||
return $this->getJailedPath($path); |
||||
} |
||||
} |
||||
@ -0,0 +1,247 @@ |
||||
<?php |
||||
/** |
||||
* Copyright (c) 2014 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\Cache\Wrapper; |
||||
|
||||
use OC\Files\Cache\Cache; |
||||
|
||||
class CacheWrapper extends Cache { |
||||
/** |
||||
* @var \OC\Files\Cache\Cache |
||||
*/ |
||||
protected $cache; |
||||
|
||||
/** |
||||
* @param \OC\Files\Cache\Cache $cache |
||||
*/ |
||||
public function __construct($cache) { |
||||
$this->cache = $cache; |
||||
} |
||||
|
||||
/** |
||||
* Make it easy for wrappers to modify every returned cache entry |
||||
* |
||||
* @param array $entry |
||||
* @return array |
||||
*/ |
||||
protected function formatCacheEntry($entry) { |
||||
return $entry; |
||||
} |
||||
|
||||
/** |
||||
* get the stored metadata of a file or folder |
||||
* |
||||
* @param string /int $file |
||||
* @return array|false |
||||
*/ |
||||
public function get($file) { |
||||
$result = $this->cache->get($file); |
||||
if ($result) { |
||||
$result = $this->formatCacheEntry($result); |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
/** |
||||
* get the metadata of all files stored in $folder |
||||
* |
||||
* @param string $folder |
||||
* @return array |
||||
*/ |
||||
public function getFolderContents($folder) { |
||||
// cant do a simple $this->cache->.... call here since getFolderContentsById needs to be called on this |
||||
// and not the wrapped cache |
||||
$fileId = $this->getId($folder); |
||||
return $this->getFolderContentsById($fileId); |
||||
} |
||||
|
||||
/** |
||||
* get the metadata of all files stored in $folder |
||||
* |
||||
* @param int $fileId the file id of the folder |
||||
* @return array |
||||
*/ |
||||
public function getFolderContentsById($fileId) { |
||||
$results = $this->cache->getFolderContentsById($fileId); |
||||
return array_map(array($this, 'formatCacheEntry'), $results); |
||||
} |
||||
|
||||
/** |
||||
* store meta data for a file or folder |
||||
* |
||||
* @param string $file |
||||
* @param array $data |
||||
* |
||||
* @return int file id |
||||
*/ |
||||
public function put($file, array $data) { |
||||
return $this->cache->put($file, $data); |
||||
} |
||||
|
||||
/** |
||||
* update the metadata in the cache |
||||
* |
||||
* @param int $id |
||||
* @param array $data |
||||
*/ |
||||
public function update($id, array $data) { |
||||
$this->cache->update($id, $data); |
||||
} |
||||
|
||||
/** |
||||
* get the file id for a file |
||||
* |
||||
* @param string $file |
||||
* @return int |
||||
*/ |
||||
public function getId($file) { |
||||
return $this->cache->getId($file); |
||||
} |
||||
|
||||
/** |
||||
* get the id of the parent folder of a file |
||||
* |
||||
* @param string $file |
||||
* @return int |
||||
*/ |
||||
public function getParentId($file) { |
||||
return $this->cache->getParentId($file); |
||||
} |
||||
|
||||
/** |
||||
* check if a file is available in the cache |
||||
* |
||||
* @param string $file |
||||
* @return bool |
||||
*/ |
||||
public function inCache($file) { |
||||
return $this->cache->inCache($file); |
||||
} |
||||
|
||||
/** |
||||
* remove a file or folder from the cache |
||||
* |
||||
* @param string $file |
||||
*/ |
||||
public function remove($file) { |
||||
$this->cache->remove($file); |
||||
} |
||||
|
||||
/** |
||||
* Move a file or folder in the cache |
||||
* |
||||
* @param string $source |
||||
* @param string $target |
||||
*/ |
||||
public function move($source, $target) { |
||||
$this->cache->move($source, $target); |
||||
} |
||||
|
||||
/** |
||||
* remove all entries for files that are stored on the storage from the cache |
||||
*/ |
||||
public function clear() { |
||||
$this->cache->clear(); |
||||
} |
||||
|
||||
/** |
||||
* @param string $file |
||||
* |
||||
* @return int, Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE |
||||
*/ |
||||
public function getStatus($file) { |
||||
return $this->cache->getStatus($file); |
||||
} |
||||
|
||||
/** |
||||
* search for files matching $pattern |
||||
* |
||||
* @param string $pattern |
||||
* @return array an array of file data |
||||
*/ |
||||
public function search($pattern) { |
||||
$results = $this->cache->search($pattern); |
||||
return array_map(array($this, 'formatCacheEntry'), $results); |
||||
} |
||||
|
||||
/** |
||||
* search for files by mimetype |
||||
* |
||||
* @param string $mimetype |
||||
* @return array |
||||
*/ |
||||
public function searchByMime($mimetype) { |
||||
$results = $this->cache->searchByMime($mimetype); |
||||
return array_map(array($this, 'formatCacheEntry'), $results); |
||||
} |
||||
|
||||
/** |
||||
* update the folder size and the size of all parent folders |
||||
* |
||||
* @param string|boolean $path |
||||
* @param array $data (optional) meta data of the folder |
||||
*/ |
||||
public function correctFolderSize($path, $data = null) { |
||||
$this->cache->correctFolderSize($path, $data); |
||||
} |
||||
|
||||
/** |
||||
* get the size of a folder and set it in the cache |
||||
* |
||||
* @param string $path |
||||
* @param array $entry (optional) meta data of the folder |
||||
* @return int |
||||
*/ |
||||
public function calculateFolderSize($path, $entry = null) { |
||||
return $this->cache->calculateFolderSize($path, $entry); |
||||
} |
||||
|
||||
/** |
||||
* get all file ids on the files on the storage |
||||
* |
||||
* @return int[] |
||||
*/ |
||||
public function getAll() { |
||||
return $this->cache->getAll(); |
||||
} |
||||
|
||||
/** |
||||
* find a folder in the cache which has not been fully scanned |
||||
* |
||||
* If multiple incomplete folders are in the cache, the one with the highest id will be returned, |
||||
* use the one with the highest id gives the best result with the background scanner, since that is most |
||||
* likely the folder where we stopped scanning previously |
||||
* |
||||
* @return string|bool the path of the folder or false when no folder matched |
||||
*/ |
||||
public function getIncomplete() { |
||||
return $this->cache->getIncomplete(); |
||||
} |
||||
|
||||
/** |
||||
* get the path of a file on this storage by it's id |
||||
* |
||||
* @param int $id |
||||
* @return string|null |
||||
*/ |
||||
public function getPathById($id) { |
||||
return $this->cache->getPathById($id); |
||||
} |
||||
|
||||
/** |
||||
* get the storage id of the storage for a file and the internal path of the file |
||||
* unlike getPathById this does not limit the search to files on this storage and |
||||
* instead does a global search in the cache table |
||||
* |
||||
* @param int $id |
||||
* @return array, first element holding the storage id, second the path |
||||
*/ |
||||
static public function getById($id) { |
||||
return parent::getById($id); |
||||
} |
||||
} |
||||
@ -0,0 +1,413 @@ |
||||
<?php |
||||
/** |
||||
* Copyright (c) 2014 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\Storage\Wrapper; |
||||
|
||||
use OC\Files\Cache\Wrapper\CacheJail; |
||||
|
||||
/** |
||||
* Jail to a subdirectory of the wrapped storage |
||||
* |
||||
* This restricts access to a subfolder of the wrapped storage with the subfolder becoming the root folder new storage |
||||
*/ |
||||
class Jail extends Wrapper { |
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $rootPath; |
||||
|
||||
/** |
||||
* @param array $arguments ['storage' => $storage, 'mask' => $root] |
||||
* |
||||
* $storage: The storage that will be wrapper |
||||
* $root: The folder in the wrapped storage that will become the root folder of the wrapped storage |
||||
*/ |
||||
public function __construct($arguments) { |
||||
parent::__construct($arguments); |
||||
$this->rootPath = $arguments['root']; |
||||
} |
||||
|
||||
protected function getSourcePath($path) { |
||||
if ($path === '') { |
||||
return $this->rootPath; |
||||
} else { |
||||
return $this->rootPath . '/' . $path; |
||||
} |
||||
} |
||||
|
||||
public function getId() { |
||||
return 'link:' . parent::getId() . ':' . $this->rootPath; |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.mkdir.php |
||||
* |
||||
* @param string $path |
||||
* @return bool |
||||
*/ |
||||
public function mkdir($path) { |
||||
return $this->storage->mkdir($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.rmdir.php |
||||
* |
||||
* @param string $path |
||||
* @return bool |
||||
*/ |
||||
public function rmdir($path) { |
||||
return $this->storage->rmdir($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.opendir.php |
||||
* |
||||
* @param string $path |
||||
* @return resource |
||||
*/ |
||||
public function opendir($path) { |
||||
return $this->storage->opendir($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.is_dir.php |
||||
* |
||||
* @param string $path |
||||
* @return bool |
||||
*/ |
||||
public function is_dir($path) { |
||||
return $this->storage->is_dir($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.is_file.php |
||||
* |
||||
* @param string $path |
||||
* @return bool |
||||
*/ |
||||
public function is_file($path) { |
||||
return $this->storage->is_file($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.stat.php |
||||
* only the following keys are required in the result: size and mtime |
||||
* |
||||
* @param string $path |
||||
* @return array |
||||
*/ |
||||
public function stat($path) { |
||||
return $this->storage->stat($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.filetype.php |
||||
* |
||||
* @param string $path |
||||
* @return bool |
||||
*/ |
||||
public function filetype($path) { |
||||
return $this->storage->filetype($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.filesize.php |
||||
* The result for filesize when called on a folder is required to be 0 |
||||
* |
||||
* @param string $path |
||||
* @return int |
||||
*/ |
||||
public function filesize($path) { |
||||
return $this->storage->filesize($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* check if a file can be created in $path |
||||
* |
||||
* @param string $path |
||||
* @return bool |
||||
*/ |
||||
public function isCreatable($path) { |
||||
return $this->storage->isCreatable($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* check if a file can be read |
||||
* |
||||
* @param string $path |
||||
* @return bool |
||||
*/ |
||||
public function isReadable($path) { |
||||
return $this->storage->isReadable($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* check if a file can be written to |
||||
* |
||||
* @param string $path |
||||
* @return bool |
||||
*/ |
||||
public function isUpdatable($path) { |
||||
return $this->storage->isUpdatable($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* check if a file can be deleted |
||||
* |
||||
* @param string $path |
||||
* @return bool |
||||
*/ |
||||
public function isDeletable($path) { |
||||
return $this->storage->isDeletable($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* check if a file can be shared |
||||
* |
||||
* @param string $path |
||||
* @return bool |
||||
*/ |
||||
public function isSharable($path) { |
||||
return $this->storage->isSharable($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* get the full permissions of a path. |
||||
* Should return a combination of the PERMISSION_ constants defined in lib/public/constants.php |
||||
* |
||||
* @param string $path |
||||
* @return int |
||||
*/ |
||||
public function getPermissions($path) { |
||||
return $this->storage->getPermissions($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.file_exists.php |
||||
* |
||||
* @param string $path |
||||
* @return bool |
||||
*/ |
||||
public function file_exists($path) { |
||||
return $this->storage->file_exists($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.filemtime.php |
||||
* |
||||
* @param string $path |
||||
* @return int |
||||
*/ |
||||
public function filemtime($path) { |
||||
return $this->storage->filemtime($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.file_get_contents.php |
||||
* |
||||
* @param string $path |
||||
* @return string |
||||
*/ |
||||
public function file_get_contents($path) { |
||||
return $this->storage->file_get_contents($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.file_put_contents.php |
||||
* |
||||
* @param string $path |
||||
* @param string $data |
||||
* @return bool |
||||
*/ |
||||
public function file_put_contents($path, $data) { |
||||
return $this->storage->file_put_contents($this->getSourcePath($path), $data); |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.unlink.php |
||||
* |
||||
* @param string $path |
||||
* @return bool |
||||
*/ |
||||
public function unlink($path) { |
||||
return $this->storage->unlink($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.rename.php |
||||
* |
||||
* @param string $path1 |
||||
* @param string $path2 |
||||
* @return bool |
||||
*/ |
||||
public function rename($path1, $path2) { |
||||
return $this->storage->rename($this->getSourcePath($path1), $this->getSourcePath($path2)); |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.copy.php |
||||
* |
||||
* @param string $path1 |
||||
* @param string $path2 |
||||
* @return bool |
||||
*/ |
||||
public function copy($path1, $path2) { |
||||
return $this->storage->copy($this->getSourcePath($path1), $this->getSourcePath($path2)); |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.fopen.php |
||||
* |
||||
* @param string $path |
||||
* @param string $mode |
||||
* @return resource |
||||
*/ |
||||
public function fopen($path, $mode) { |
||||
return $this->storage->fopen($this->getSourcePath($path), $mode); |
||||
} |
||||
|
||||
/** |
||||
* get the mimetype for a file or folder |
||||
* The mimetype for a folder is required to be "httpd/unix-directory" |
||||
* |
||||
* @param string $path |
||||
* @return string |
||||
*/ |
||||
public function getMimeType($path) { |
||||
return $this->storage->getMimeType($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.hash.php |
||||
* |
||||
* @param string $type |
||||
* @param string $path |
||||
* @param bool $raw |
||||
* @return string |
||||
*/ |
||||
public function hash($type, $path, $raw = false) { |
||||
return $this->storage->hash($type, $this->getSourcePath($path), $raw); |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.free_space.php |
||||
* |
||||
* @param string $path |
||||
* @return int |
||||
*/ |
||||
public function free_space($path) { |
||||
return $this->storage->free_space($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* search for occurrences of $query in file names |
||||
* |
||||
* @param string $query |
||||
* @return array |
||||
*/ |
||||
public function search($query) { |
||||
return $this->storage->search($query); |
||||
} |
||||
|
||||
/** |
||||
* see http://php.net/manual/en/function.touch.php |
||||
* If the backend does not support the operation, false should be returned |
||||
* |
||||
* @param string $path |
||||
* @param int $mtime |
||||
* @return bool |
||||
*/ |
||||
public function touch($path, $mtime = null) { |
||||
return $this->storage->touch($this->getSourcePath($path), $mtime); |
||||
} |
||||
|
||||
/** |
||||
* get the path to a local version of the file. |
||||
* The local version of the file can be temporary and doesn't have to be persistent across requests |
||||
* |
||||
* @param string $path |
||||
* @return string |
||||
*/ |
||||
public function getLocalFile($path) { |
||||
return $this->storage->getLocalFile($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* get the path to a local version of the folder. |
||||
* The local version of the folder can be temporary and doesn't have to be persistent across requests |
||||
* |
||||
* @param string $path |
||||
* @return string |
||||
*/ |
||||
public function getLocalFolder($path) { |
||||
return $this->storage->getLocalFolder($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* check if a file or folder has been updated since $time |
||||
* |
||||
* @param string $path |
||||
* @param int $time |
||||
* @return bool |
||||
* |
||||
* hasUpdated for folders should return at least true if a file inside the folder is add, removed or renamed. |
||||
* returning true for other changes in the folder is optional |
||||
*/ |
||||
public function hasUpdated($path, $time) { |
||||
return $this->storage->hasUpdated($this->getSourcePath($path), $time); |
||||
} |
||||
|
||||
/** |
||||
* get a cache instance for the storage |
||||
* |
||||
* @param string $path |
||||
* @param \OC\Files\Storage\Storage (optional) the storage to pass to the cache |
||||
* @return \OC\Files\Cache\Cache |
||||
*/ |
||||
public function getCache($path = '', $storage = null) { |
||||
if (!$storage) { |
||||
$storage = $this; |
||||
} |
||||
$sourceCache = $this->storage->getCache($this->getSourcePath($path), $storage); |
||||
return new CacheJail($sourceCache, $this->rootPath); |
||||
} |
||||
|
||||
/** |
||||
* get the user id of the owner of a file or folder |
||||
* |
||||
* @param string $path |
||||
* @return string |
||||
*/ |
||||
public function getOwner($path) { |
||||
return $this->storage->getOwner($this->getSourcePath($path)); |
||||
} |
||||
|
||||
/** |
||||
* get a watcher instance for the cache |
||||
* |
||||
* @param string $path |
||||
* @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher |
||||
* @return \OC\Files\Cache\Watcher |
||||
*/ |
||||
public function getWatcher($path = '', $storage = null) { |
||||
if (!$storage) { |
||||
$storage = $this; |
||||
} |
||||
return $this->storage->getWatcher($this->getSourcePath($path), $storage); |
||||
} |
||||
|
||||
/** |
||||
* get the ETag for a file or folder |
||||
* |
||||
* @param string $path |
||||
* @return string |
||||
*/ |
||||
public function getETag($path) { |
||||
return $this->storage->getETag($this->getSourcePath($path)); |
||||
} |
||||
} |
||||
@ -0,0 +1,102 @@ |
||||
<?php |
||||
/** |
||||
* Copyright (c) 2014 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\Storage\Wrapper; |
||||
|
||||
use OC\Files\Cache\Wrapper\CachePermissionsMask; |
||||
|
||||
/** |
||||
* Mask the permissions of a storage |
||||
* |
||||
* Note that the read permissions cant be masked |
||||
*/ |
||||
class PermissionsMask extends Wrapper { |
||||
/** |
||||
* @var int |
||||
*/ |
||||
private $mask; |
||||
|
||||
public function __construct($arguments) { |
||||
parent::__construct($arguments); |
||||
$this->mask = $arguments['mask']; |
||||
} |
||||
|
||||
private function checkMask($permissions) { |
||||
return ($this->mask & $permissions) === $permissions; |
||||
} |
||||
|
||||
public function isUpdatable($path) { |
||||
return $this->checkMask(\OCP\PERMISSION_UPDATE) and parent::isUpdatable($path); |
||||
} |
||||
|
||||
public function isCreatable($path) { |
||||
return $this->checkMask(\OCP\PERMISSION_CREATE) and parent::isCreatable($path); |
||||
} |
||||
|
||||
public function isDeletable($path) { |
||||
return $this->checkMask(\OCP\PERMISSION_DELETE) and parent::isDeletable($path); |
||||
} |
||||
|
||||
public function getPermissions($path) { |
||||
return $this->storage->getPermissions($path) & $this->mask; |
||||
} |
||||
|
||||
public function rename($path1, $path2) { |
||||
return $this->checkMask(\OCP\PERMISSION_UPDATE) and parent::rename($path1, $path2); |
||||
} |
||||
|
||||
public function copy($path1, $path2) { |
||||
return $this->checkMask(\OCP\PERMISSION_CREATE) and parent::copy($path1, $path2); |
||||
} |
||||
|
||||
public function touch($path, $mtime = null) { |
||||
$permissions = $this->file_exists($path) ? \OCP\PERMISSION_UPDATE : \OCP\PERMISSION_CREATE; |
||||
return $this->checkMask($permissions) and parent::touch($path, $mtime); |
||||
} |
||||
|
||||
public function mkdir($path) { |
||||
return $this->checkMask(\OCP\PERMISSION_CREATE) and parent::mkdir($path); |
||||
} |
||||
|
||||
public function rmdir($path) { |
||||
return $this->checkMask(\OCP\PERMISSION_DELETE) and parent::rmdir($path); |
||||
} |
||||
|
||||
public function unlink($path) { |
||||
return $this->checkMask(\OCP\PERMISSION_DELETE) and parent::unlink($path); |
||||
} |
||||
|
||||
public function file_put_contents($path, $data) { |
||||
$permissions = $this->file_exists($path) ? \OCP\PERMISSION_UPDATE : \OCP\PERMISSION_CREATE; |
||||
return $this->checkMask($permissions) and parent::file_put_contents($path, $data); |
||||
} |
||||
|
||||
public function fopen($path, $mode) { |
||||
if ($mode === 'r' or $mode === 'rb') { |
||||
return parent::fopen($path, $mode); |
||||
} else { |
||||
$permissions = $this->file_exists($path) ? \OCP\PERMISSION_UPDATE : \OCP\PERMISSION_CREATE; |
||||
return $this->checkMask($permissions) ? parent::fopen($path, $mode) : false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* get a cache instance for the storage |
||||
* |
||||
* @param string $path |
||||
* @param \OC\Files\Storage\Storage (optional) the storage to pass to the cache |
||||
* @return \OC\Files\Cache\Cache |
||||
*/ |
||||
public function getCache($path = '', $storage = null) { |
||||
if (!$storage) { |
||||
$storage = $this; |
||||
} |
||||
$sourceCache = parent::getCache($path, $storage); |
||||
return new CachePermissionsMask($sourceCache, $this->mask); |
||||
} |
||||
} |
||||
@ -0,0 +1,67 @@ |
||||
<?php |
||||
/** |
||||
* Copyright (c) 2014 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 Test\Files\Cache\Wrapper; |
||||
|
||||
use Test\Files\Cache\Cache; |
||||
|
||||
class CacheJail extends Cache { |
||||
/** |
||||
* @var \OC\Files\Cache\Cache $sourceCache |
||||
*/ |
||||
protected $sourceCache; |
||||
|
||||
public function setUp() { |
||||
parent::setUp(); |
||||
$this->storage->mkdir('foo'); |
||||
$this->sourceCache = $this->cache; |
||||
$this->cache = new \OC\Files\Cache\Wrapper\CacheJail($this->sourceCache, 'foo'); |
||||
} |
||||
|
||||
function testSearchOutsideJail() { |
||||
$file1 = 'foo/foobar'; |
||||
$file2 = 'folder/foobar'; |
||||
$data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder'); |
||||
|
||||
$this->sourceCache->put($file1, $data1); |
||||
$this->sourceCache->put($file2, $data1); |
||||
|
||||
$this->assertCount(2, $this->sourceCache->search('%foobar')); |
||||
|
||||
$result = $this->cache->search('%foobar%'); |
||||
$this->assertCount(1, $result); |
||||
$this->assertEquals('foobar', $result[0]['path']); |
||||
} |
||||
|
||||
function testClearKeepEntriesOutsideJail() { |
||||
$file1 = 'foo/foobar'; |
||||
$file2 = 'foo/foobar/asd'; |
||||
$file3 = 'folder/foobar'; |
||||
$data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory'); |
||||
|
||||
$this->sourceCache->put('foo', $data1); |
||||
$this->sourceCache->put($file1, $data1); |
||||
$this->sourceCache->put($file2, $data1); |
||||
$this->sourceCache->put($file3, $data1); |
||||
|
||||
$this->cache->clear(); |
||||
|
||||
$this->assertFalse($this->cache->inCache('foobar')); |
||||
$this->assertTrue($this->sourceCache->inCache('folder/foobar')); |
||||
} |
||||
|
||||
function testGetById() { |
||||
//not supported |
||||
$this->assertTrue(true); |
||||
} |
||||
|
||||
function testGetIncomplete() { |
||||
//not supported |
||||
$this->assertTrue(true); |
||||
} |
||||
} |
||||
@ -0,0 +1,55 @@ |
||||
<?php |
||||
/** |
||||
* Copyright (c) 2014 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 Test\Files\Storage\Wrapper; |
||||
|
||||
class Jail extends \Test\Files\Storage\Storage { |
||||
/** |
||||
* @var string tmpDir |
||||
*/ |
||||
private $tmpDir; |
||||
|
||||
/** |
||||
* @var \OC\Files\Storage\Temporary |
||||
*/ |
||||
private $sourceStorage; |
||||
|
||||
public function setUp() { |
||||
parent::setUp(); |
||||
$this->sourceStorage = new \OC\Files\Storage\Temporary(array()); |
||||
$this->sourceStorage->mkdir('foo'); |
||||
$this->instance = new \OC\Files\Storage\Wrapper\Jail(array( |
||||
'storage' => $this->sourceStorage, |
||||
'root' => 'foo' |
||||
)); |
||||
} |
||||
|
||||
public function tearDown() { |
||||
// test that nothing outside our jail is touched |
||||
$contents = array(); |
||||
$dh = $this->sourceStorage->opendir(''); |
||||
while ($file = readdir($dh)) { |
||||
if ($file !== '.' and $file !== '..') { |
||||
$contents[] = $file; |
||||
} |
||||
} |
||||
$this->assertEquals(array('foo'), $contents); |
||||
$this->sourceStorage->cleanUp(); |
||||
parent::tearDown(); |
||||
} |
||||
|
||||
public function testMkDirRooted() { |
||||
$this->instance->mkdir('bar'); |
||||
$this->assertTrue($this->sourceStorage->is_dir('foo/bar')); |
||||
} |
||||
|
||||
public function testFilePutContentsRooted() { |
||||
$this->instance->file_put_contents('bar', 'asd'); |
||||
$this->assertEquals('asd', $this->sourceStorage->file_get_contents('foo/bar')); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue