diff options
author | Henrik Kjölhede <hkjolhede@gmail.com> | 2013-02-09 14:05:33 +0100 |
---|---|---|
committer | Henrik Kjölhede <hkjolhede@gmail.com> | 2013-02-09 14:05:33 +0100 |
commit | 41fa65e7befb249e260f2dd91e33971261cfd302 (patch) | |
tree | 4ebb4cb10f7869ba3288308ca3a35ce53970ed40 /lib/files/storage | |
parent | b1b2eafa50db54b2613cf2bc52bfab2015d67b2f (diff) | |
parent | ec829bd345045df985f623fa2fe6587d0ce68eb2 (diff) | |
download | nextcloud-server-41fa65e7befb249e260f2dd91e33971261cfd302.tar.gz nextcloud-server-41fa65e7befb249e260f2dd91e33971261cfd302.zip |
Merge branch 'master' of https://github.com/owncloud/core
Conflicts:
apps/files_external/appinfo/app.php
Diffstat (limited to 'lib/files/storage')
-rw-r--r-- | lib/files/storage/common.php | 304 | ||||
-rw-r--r-- | lib/files/storage/commontest.php | 80 | ||||
-rw-r--r-- | lib/files/storage/local.php | 252 | ||||
-rw-r--r-- | lib/files/storage/mappedlocal.php | 335 | ||||
-rw-r--r-- | lib/files/storage/storage.php | 88 | ||||
-rw-r--r-- | lib/files/storage/temporary.php | 27 |
6 files changed, 1086 insertions, 0 deletions
diff --git a/lib/files/storage/common.php b/lib/files/storage/common.php new file mode 100644 index 00000000000..668cb08d7b1 --- /dev/null +++ b/lib/files/storage/common.php @@ -0,0 +1,304 @@ +<?php +/** + * Copyright (c) 2012 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; + +/** + * Storage backend class for providing common filesystem operation methods + * which are not storage-backend specific. + * + * \OC\Files\Storage\Common is never used directly; it is extended by all other + * storage backends, where its methods may be overridden, and additional + * (backend-specific) methods are defined. + * + * Some \OC\Files\Storage\Common methods call functions which are first defined + * in classes which extend it, e.g. $this->stat() . + */ + +abstract class Common implements \OC\Files\Storage\Storage { + + public function __construct($parameters) {} + public function is_dir($path) { + return $this->filetype($path)=='dir'; + } + public function is_file($path) { + return $this->filetype($path)=='file'; + } + public function filesize($path) { + if($this->is_dir($path)) { + return 0;//by definition + }else{ + $stat = $this->stat($path); + return $stat['size']; + } + } + public function isCreatable($path) { + if ($this->is_dir($path) && $this->isUpdatable($path)) { + return true; + } + return false; + } + public function isDeletable($path) { + return $this->isUpdatable($path); + } + public function isSharable($path) { + return $this->isReadable($path); + } + public function getPermissions($path){ + $permissions = 0; + if($this->isCreatable($path)){ + $permissions |= \OCP\PERMISSION_CREATE; + } + if($this->isReadable($path)){ + $permissions |= \OCP\PERMISSION_READ; + } + if($this->isUpdatable($path)){ + $permissions |= \OCP\PERMISSION_UPDATE; + } + if($this->isDeletable($path)){ + $permissions |= \OCP\PERMISSION_DELETE; + } + if($this->isSharable($path)){ + $permissions |= \OCP\PERMISSION_SHARE; + } + return $permissions; + } + public function filemtime($path) { + $stat = $this->stat($path); + return $stat['mtime']; + } + public function file_get_contents($path) { + $handle = $this->fopen($path, "r"); + if(!$handle) { + return false; + } + $size=$this->filesize($path); + if($size==0) { + return ''; + } + return fread($handle, $size); + } + public function file_put_contents($path,$data) { + $handle = $this->fopen($path, "w"); + return fwrite($handle, $data); + } + public function rename($path1,$path2) { + if($this->copy($path1,$path2)) { + return $this->unlink($path1); + }else{ + return false; + } + } + public function copy($path1,$path2) { + $source=$this->fopen($path1,'r'); + $target=$this->fopen($path2,'w'); + $count=\OC_Helper::streamCopy($source,$target); + return $count>0; + } + + /** + * @brief Deletes all files and folders recursively within a directory + * @param string $directory The directory whose contents will be deleted + * @param bool $empty Flag indicating whether directory will be emptied + * @returns bool + * + * @note By default the directory specified by $directory will be + * deleted together with its contents. To avoid this set $empty to true + */ + public function deleteAll( $directory, $empty = false ) { + $directory = trim($directory,'/'); + + if ( !$this->file_exists( \OCP\USER::getUser() . '/' . $directory ) || !$this->is_dir( \OCP\USER::getUser() . '/' . $directory ) ) { + return false; + } elseif( !$this->isReadable( \OCP\USER::getUser() . '/' . $directory ) ) { + return false; + } else { + $directoryHandle = $this->opendir( \OCP\USER::getUser() . '/' . $directory ); + while ( $contents = readdir( $directoryHandle ) ) { + if ( $contents != '.' && $contents != '..') { + $path = $directory . "/" . $contents; + if ( $this->is_dir( $path ) ) { + $this->deleteAll( $path ); + } else { + $this->unlink( \OCP\USER::getUser() .'/' . $path ); // TODO: make unlink use same system path as is_dir + } + } + } + //$this->closedir( $directoryHandle ); // TODO: implement closedir in OC_FSV + if ( $empty == false ) { + if ( !$this->rmdir( $directory ) ) { + return false; + } + } + return true; + } + + } + public function getMimeType($path) { + if(!$this->file_exists($path)) { + return false; + } + if($this->is_dir($path)) { + return 'httpd/unix-directory'; + } + $source=$this->fopen($path,'r'); + if(!$source) { + return false; + } + $head=fread($source,8192);//8kb should suffice to determine a mimetype + if($pos=strrpos($path,'.')) { + $extension=substr($path,$pos); + }else{ + $extension=''; + } + $tmpFile=\OC_Helper::tmpFile($extension); + file_put_contents($tmpFile,$head); + $mime=\OC_Helper::getMimeType($tmpFile); + unlink($tmpFile); + return $mime; + } + public function hash($type,$path,$raw = false) { + $tmpFile=$this->getLocalFile($path); + $hash=hash($type,$tmpFile,$raw); + unlink($tmpFile); + return $hash; + } + public function search($query) { + return $this->searchInDir($query); + } + public function getLocalFile($path) { + return $this->toTmpFile($path); + } + private function toTmpFile($path) {//no longer in the storage api, still useful here + $source=$this->fopen($path,'r'); + if(!$source) { + return false; + } + if($pos=strrpos($path,'.')) { + $extension=substr($path,$pos); + }else{ + $extension=''; + } + $tmpFile=\OC_Helper::tmpFile($extension); + $target=fopen($tmpFile,'w'); + \OC_Helper::streamCopy($source,$target); + return $tmpFile; + } + public function getLocalFolder($path) { + $baseDir=\OC_Helper::tmpFolder(); + $this->addLocalFolder($path,$baseDir); + return $baseDir; + } + private function addLocalFolder($path,$target) { + if($dh=$this->opendir($path)) { + while($file=readdir($dh)) { + if($file!=='.' and $file!=='..') { + if($this->is_dir($path.'/'.$file)) { + mkdir($target.'/'.$file); + $this->addLocalFolder($path.'/'.$file,$target.'/'.$file); + }else{ + $tmp=$this->toTmpFile($path.'/'.$file); + rename($tmp,$target.'/'.$file); + } + } + } + } + } + + protected function searchInDir($query,$dir='') { + $files=array(); + $dh=$this->opendir($dir); + if($dh) { + while($item=readdir($dh)) { + if ($item == '.' || $item == '..') continue; + if(strstr(strtolower($item), strtolower($query))!==false) { + $files[]=$dir.'/'.$item; + } + if($this->is_dir($dir.'/'.$item)) { + $files=array_merge($files,$this->searchInDir($query,$dir.'/'.$item)); + } + } + } + return $files; + } + + /** + * check if a file or folder has been updated since $time + * @param string $path + * @param int $time + * @return bool + */ + public function hasUpdated($path,$time) { + return $this->filemtime($path)>$time; + } + + public function getCache($path=''){ + return new \OC\Files\Cache\Cache($this); + } + + public function getScanner($path=''){ + return new \OC\Files\Cache\Scanner($this); + } + + public function getPermissionsCache($path=''){ + return new \OC\Files\Cache\Permissions($this); + } + + public function getWatcher($path=''){ + return new \OC\Files\Cache\Watcher($this); + } + + /** + * get the owner of a path + * @param string $path The path to get the owner + * @return string uid or false + */ + public function getOwner($path) { + return \OC_User::getUser(); + } + + /** + * get the ETag for a file or folder + * + * @param string $path + * @return string + */ + public function getETag($path){ + $ETagFunction = \OC_Connector_Sabre_Node::$ETagFunction; + if($ETagFunction) { + $hash = call_user_func($ETagFunction, $path); + return $hash; + }else{ + return uniqid(); + } + } + + /** + * clean a path, i.e. remove all redundant '.' and '..' + * making sure that it can't point to higher than '/' + * @param $path The path to clean + * @return string cleaned path + */ + public function cleanPath($path) { + if (strlen($path) == 0 or $path[0] != '/') { + $path = '/' . $path; + } + + $chunks = explode('/', $path); + $output = array(); + foreach ($chunks as $chunk) { + if ($chunk == '..') { + array_pop($output); + } else if ($chunk == '.') { + } else { + $output[] = $chunk; + } + } + return implode('/', $output); + } +} diff --git a/lib/files/storage/commontest.php b/lib/files/storage/commontest.php new file mode 100644 index 00000000000..fbdb7fbf110 --- /dev/null +++ b/lib/files/storage/commontest.php @@ -0,0 +1,80 @@ +<?php + +/** +* ownCloud +* +* @author Robin Appelman +* @copyright 2012 Robin Appelman icewind@owncloud.com +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE +* License as published by the Free Software Foundation; either +* version 3 of the License, or any later version. +* +* This library 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 along with this library. If not, see <http://www.gnu.org/licenses/>. +* +*/ + +/** + * test implementation for \OC\Files\Storage\Common with \OC\Files\Storage\Local + */ + +namespace OC\Files\Storage; + +class CommonTest extends \OC\Files\Storage\Common{ + /** + * underlying local storage used for missing functions + * @var \OC\Files\Storage\Local + */ + private $storage; + + public function __construct($params) { + $this->storage=new \OC\Files\Storage\Local($params); + } + + public function getId(){ + return 'test::'.$this->storage->getId(); + } + public function mkdir($path) { + return $this->storage->mkdir($path); + } + public function rmdir($path) { + return $this->storage->rmdir($path); + } + public function opendir($path) { + return $this->storage->opendir($path); + } + public function stat($path) { + return $this->storage->stat($path); + } + public function filetype($path) { + return $this->storage->filetype($path); + } + public function isReadable($path) { + return $this->storage->isReadable($path); + } + public function isUpdatable($path) { + return $this->storage->isUpdatable($path); + } + public function file_exists($path) { + return $this->storage->file_exists($path); + } + public function unlink($path) { + return $this->storage->unlink($path); + } + public function fopen($path, $mode) { + return $this->storage->fopen($path, $mode); + } + public function free_space($path) { + return $this->storage->free_space($path); + } + public function touch($path, $mtime=null) { + return $this->storage->touch($path, $mtime); + } +}
\ No newline at end of file diff --git a/lib/files/storage/local.php b/lib/files/storage/local.php new file mode 100644 index 00000000000..d387a898320 --- /dev/null +++ b/lib/files/storage/local.php @@ -0,0 +1,252 @@ +<?php +/** + * Copyright (c) 2012 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; + +if (\OC_Util::runningOnWindows()) { + require_once 'mappedlocal.php'; +} else { + +/** + * for local filestore, we only have to map the paths + */ +class Local extends \OC\Files\Storage\Common{ + protected $datadir; + public function __construct($arguments) { + $this->datadir=$arguments['datadir']; + if(substr($this->datadir, -1)!=='/') { + $this->datadir.='/'; + } + } + public function getId(){ + return 'local::'.$this->datadir; + } + public function mkdir($path) { + return @mkdir($this->datadir.$path); + } + public function rmdir($path) { + return @rmdir($this->datadir.$path); + } + public function opendir($path) { + return opendir($this->datadir.$path); + } + public function is_dir($path) { + if(substr($path,-1)=='/') { + $path=substr($path, 0, -1); + } + return is_dir($this->datadir.$path); + } + public function is_file($path) { + return is_file($this->datadir.$path); + } + public function stat($path) { + $fullPath = $this->datadir . $path; + $statResult = stat($fullPath); + + if ($statResult['size'] < 0) { + $size = self::getFileSizeFromOS($fullPath); + $statResult['size'] = $size; + $statResult[7] = $size; + } + return $statResult; + } + public function filetype($path) { + $filetype=filetype($this->datadir.$path); + if($filetype=='link') { + $filetype=filetype(realpath($this->datadir.$path)); + } + return $filetype; + } + public function filesize($path) { + if($this->is_dir($path)) { + return 0; + }else{ + $fullPath = $this->datadir . $path; + $fileSize = filesize($fullPath); + if ($fileSize < 0) { + return self::getFileSizeFromOS($fullPath); + } + + return $fileSize; + } + } + public function isReadable($path) { + return is_readable($this->datadir.$path); + } + public function isUpdatable($path) { + return is_writable($this->datadir.$path); + } + public function file_exists($path) { + return file_exists($this->datadir.$path); + } + public function filemtime($path) { + return filemtime($this->datadir.$path); + } + public function touch($path, $mtime=null) { + // sets the modification time of the file to the given value. + // If mtime is nil the current time is set. + // note that the access time of the file always changes to the current time. + if(!is_null($mtime)) { + $result=touch( $this->datadir.$path, $mtime ); + }else{ + $result=touch( $this->datadir.$path); + } + if( $result ) { + clearstatcache( true, $this->datadir.$path ); + } + + return $result; + } + public function file_get_contents($path) { + return file_get_contents($this->datadir.$path); + } + public function file_put_contents($path, $data) {//trigger_error("$path = ".var_export($path, 1)); + return file_put_contents($this->datadir.$path, $data); + } + public function unlink($path) { + return $this->delTree($path); + } + public function rename($path1, $path2) { + if (!$this->isUpdatable($path1)) { + \OC_Log::write('core','unable to rename, file is not writable : '.$path1,\OC_Log::ERROR); + return false; + } + if(! $this->file_exists($path1)) { + \OC_Log::write('core','unable to rename, file does not exists : '.$path1,\OC_Log::ERROR); + return false; + } + + if($return=rename($this->datadir.$path1, $this->datadir.$path2)) { + } + return $return; + } + public function copy($path1, $path2) { + if($this->is_dir($path2)) { + if(!$this->file_exists($path2)) { + $this->mkdir($path2); + } + $source=substr($path1, strrpos($path1, '/')+1); + $path2.=$source; + } + return copy($this->datadir.$path1, $this->datadir.$path2); + } + public function fopen($path, $mode) { + if($return=fopen($this->datadir.$path, $mode)) { + switch($mode) { + case 'r': + break; + case 'r+': + case 'w+': + case 'x+': + case 'a+': + break; + case 'w': + case 'x': + case 'a': + break; + } + } + return $return; + } + + public function getMimeType($path) { + if($this->isReadable($path)) { + return \OC_Helper::getMimeType($this->datadir . $path); + }else{ + return false; + } + } + + private function delTree($dir) { + $dirRelative=$dir; + $dir=$this->datadir.$dir; + if (!file_exists($dir)) return true; + if (!is_dir($dir) || is_link($dir)) return unlink($dir); + foreach (scandir($dir) as $item) { + if ($item == '.' || $item == '..') continue; + if(is_file($dir.'/'.$item)) { + if(unlink($dir.'/'.$item)) { + } + }elseif(is_dir($dir.'/'.$item)) { + if (!$this->delTree($dirRelative. "/" . $item)) { + return false; + }; + } + } + if($return=rmdir($dir)) { + } + return $return; + } + + private static function getFileSizeFromOS($fullPath) { + $name = strtolower(php_uname('s')); + // Windows OS: we use COM to access the filesystem + if (strpos($name, 'win') !== false) { + if (class_exists('COM')) { + $fsobj = new \COM("Scripting.FileSystemObject"); + $f = $fsobj->GetFile($fullPath); + return $f->Size; + } + } else if (strpos($name, 'bsd') !== false) { + if (\OC_Helper::is_function_enabled('exec')) { + return (float)exec('stat -f %z ' . escapeshellarg($fullPath)); + } + } else if (strpos($name, 'linux') !== false) { + if (\OC_Helper::is_function_enabled('exec')) { + return (float)exec('stat -c %s ' . escapeshellarg($fullPath)); + } + } else { + \OC_Log::write('core', 'Unable to determine file size of "'.$fullPath.'". Unknown OS: '.$name, \OC_Log::ERROR); + } + + return 0; + } + + public function hash($path, $type, $raw=false) { + return hash_file($type, $this->datadir.$path, $raw); + } + + public function free_space($path) { + return @disk_free_space($this->datadir.$path); + } + + public function search($query) { + return $this->searchInDir($query); + } + public function getLocalFile($path) { + return $this->datadir.$path; + } + public function getLocalFolder($path) { + return $this->datadir.$path; + } + + protected function searchInDir($query, $dir='') { + $files=array(); + foreach (scandir($this->datadir.$dir) as $item) { + if ($item == '.' || $item == '..') continue; + if(strstr(strtolower($item), strtolower($query))!==false) { + $files[]=$dir.'/'.$item; + } + if(is_dir($this->datadir.$dir.'/'.$item)) { + $files=array_merge($files, $this->searchInDir($query, $dir.'/'.$item)); + } + } + return $files; + } + + /** + * check if a file or folder has been updated since $time + * @param string $path + * @param int $time + * @return bool + */ + public function hasUpdated($path, $time) { + return $this->filemtime($path)>$time; + } +} +} diff --git a/lib/files/storage/mappedlocal.php b/lib/files/storage/mappedlocal.php new file mode 100644 index 00000000000..80dd79bc41f --- /dev/null +++ b/lib/files/storage/mappedlocal.php @@ -0,0 +1,335 @@ +<?php +/** + * Copyright (c) 2012 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; + +/** + * for local filestore, we only have to map the paths + */ +class Local extends \OC\Files\Storage\Common{ + protected $datadir; + private $mapper; + + public function __construct($arguments) { + $this->datadir=$arguments['datadir']; + if(substr($this->datadir, -1)!=='/') { + $this->datadir.='/'; + } + + $this->mapper= new \OC\Files\Mapper(); + } + public function __destruct() { + if (defined('PHPUNIT_RUN')) { + $this->mapper->removePath($this->datadir, true, true); + } + } + public function getId(){ + return 'local::'.$this->datadir; + } + public function mkdir($path) { + return @mkdir($this->buildPath($path)); + } + public function rmdir($path) { + if ($result = @rmdir($this->buildPath($path))) { + $this->cleanMapper($path); + } + return $result; + } + public function opendir($path) { + $files = array('.', '..'); + $physicalPath= $this->buildPath($path); + + $logicalPath = $this->mapper->physicalToLogic($physicalPath); + $dh = opendir($physicalPath); + while ($file = readdir($dh)) { + if ($file === '.' or $file === '..') { + continue; + } + + $logicalFilePath = $this->mapper->physicalToLogic($physicalPath.DIRECTORY_SEPARATOR.$file); + + $file= $this->mapper->stripRootFolder($logicalFilePath, $logicalPath); + $file = $this->stripLeading($file); + $files[]= $file; + } + + \OC\Files\Stream\Dir::register('local-win32'.$path, $files); + return opendir('fakedir://local-win32'.$path); + } + public function is_dir($path) { + if(substr($path,-1)=='/') { + $path=substr($path, 0, -1); + } + return is_dir($this->buildPath($path)); + } + public function is_file($path) { + return is_file($this->buildPath($path)); + } + public function stat($path) { + $fullPath = $this->buildPath($path); + $statResult = stat($fullPath); + + if ($statResult['size'] < 0) { + $size = self::getFileSizeFromOS($fullPath); + $statResult['size'] = $size; + $statResult[7] = $size; + } + return $statResult; + } + public function filetype($path) { + $filetype=filetype($this->buildPath($path)); + if($filetype=='link') { + $filetype=filetype(realpath($this->buildPath($path))); + } + return $filetype; + } + public function filesize($path) { + if($this->is_dir($path)) { + return 0; + }else{ + $fullPath = $this->buildPath($path); + $fileSize = filesize($fullPath); + if ($fileSize < 0) { + return self::getFileSizeFromOS($fullPath); + } + + return $fileSize; + } + } + public function isReadable($path) { + return is_readable($this->buildPath($path)); + } + public function isUpdatable($path) { + return is_writable($this->buildPath($path)); + } + public function file_exists($path) { + return file_exists($this->buildPath($path)); + } + public function filemtime($path) { + return filemtime($this->buildPath($path)); + } + public function touch($path, $mtime=null) { + // sets the modification time of the file to the given value. + // If mtime is nil the current time is set. + // note that the access time of the file always changes to the current time. + if(!is_null($mtime)) { + $result=touch( $this->buildPath($path), $mtime ); + }else{ + $result=touch( $this->buildPath($path)); + } + if( $result ) { + clearstatcache( true, $this->buildPath($path) ); + } + + return $result; + } + public function file_get_contents($path) { + return file_get_contents($this->buildPath($path)); + } + public function file_put_contents($path, $data) {//trigger_error("$path = ".var_export($path, 1)); + return file_put_contents($this->buildPath($path), $data); + } + public function unlink($path) { + return $this->delTree($path); + } + public function rename($path1, $path2) { + if (!$this->isUpdatable($path1)) { + \OC_Log::write('core','unable to rename, file is not writable : '.$path1,\OC_Log::ERROR); + return false; + } + if(! $this->file_exists($path1)) { + \OC_Log::write('core','unable to rename, file does not exists : '.$path1,\OC_Log::ERROR); + return false; + } + + $physicPath1 = $this->buildPath($path1); + $physicPath2 = $this->buildPath($path2); + if($return=rename($physicPath1, $physicPath2)) { + // mapper needs to create copies or all children + $this->copyMapping($path1, $path2); + $this->cleanMapper($physicPath1, false, true); + } + return $return; + } + public function copy($path1, $path2) { + if($this->is_dir($path2)) { + if(!$this->file_exists($path2)) { + $this->mkdir($path2); + } + $source=substr($path1, strrpos($path1, '/')+1); + $path2.=$source; + } + if($return=copy($this->buildPath($path1), $this->buildPath($path2))) { + // mapper needs to create copies or all children + $this->copyMapping($path1, $path2); + } + return $return; + } + public function fopen($path, $mode) { + if($return=fopen($this->buildPath($path), $mode)) { + switch($mode) { + case 'r': + break; + case 'r+': + case 'w+': + case 'x+': + case 'a+': + break; + case 'w': + case 'x': + case 'a': + break; + } + } + return $return; + } + + public function getMimeType($path) { + if($this->isReadable($path)) { + return \OC_Helper::getMimeType($this->buildPath($path)); + }else{ + return false; + } + } + + private function delTree($dir, $isLogicPath=true) { + $dirRelative=$dir; + if ($isLogicPath) { + $dir=$this->buildPath($dir); + } + if (!file_exists($dir)) { + return true; + } + if (!is_dir($dir) || is_link($dir)) { + if($return=unlink($dir)) { + $this->cleanMapper($dir, false); + return $return; + } + } + foreach (scandir($dir) as $item) { + if ($item == '.' || $item == '..') { + continue; + } + if(is_file($dir.'/'.$item)) { + if(unlink($dir.'/'.$item)) { + $this->cleanMapper($dir.'/'.$item, false); + } + }elseif(is_dir($dir.'/'.$item)) { + if (!$this->delTree($dir. "/" . $item, false)) { + return false; + }; + } + } + if($return=rmdir($dir)) { + $this->cleanMapper($dir, false); + } + return $return; + } + + private static function getFileSizeFromOS($fullPath) { + $name = strtolower(php_uname('s')); + // Windows OS: we use COM to access the filesystem + if (strpos($name, 'win') !== false) { + if (class_exists('COM')) { + $fsobj = new \COM("Scripting.FileSystemObject"); + $f = $fsobj->GetFile($fullPath); + return $f->Size; + } + } else if (strpos($name, 'bsd') !== false) { + if (\OC_Helper::is_function_enabled('exec')) { + return (float)exec('stat -f %z ' . escapeshellarg($fullPath)); + } + } else if (strpos($name, 'linux') !== false) { + if (\OC_Helper::is_function_enabled('exec')) { + return (float)exec('stat -c %s ' . escapeshellarg($fullPath)); + } + } else { + \OC_Log::write('core', 'Unable to determine file size of "'.$fullPath.'". Unknown OS: '.$name, \OC_Log::ERROR); + } + + return 0; + } + + public function hash($path, $type, $raw=false) { + return hash_file($type, $this->buildPath($path), $raw); + } + + public function free_space($path) { + return @disk_free_space($this->buildPath($path)); + } + + public function search($query) { + return $this->searchInDir($query); + } + public function getLocalFile($path) { + return $this->buildPath($path); + } + public function getLocalFolder($path) { + return $this->buildPath($path); + } + + protected function searchInDir($query, $dir='', $isLogicPath=true) { + $files=array(); + $physicalDir = $this->buildPath($dir); + foreach (scandir($physicalDir) as $item) { + if ($item == '.' || $item == '..') + continue; + $physicalItem = $this->mapper->physicalToLogic($physicalDir.DIRECTORY_SEPARATOR.$item); + $item = substr($physicalItem, strlen($physicalDir)+1); + + if(strstr(strtolower($item), strtolower($query)) !== false) { + $files[]=$dir.'/'.$item; + } + if(is_dir($physicalItem)) { + $files=array_merge($files, $this->searchInDir($query, $physicalItem, false)); + } + } + return $files; + } + + /** + * check if a file or folder has been updated since $time + * @param string $path + * @param int $time + * @return bool + */ + public function hasUpdated($path, $time) { + return $this->filemtime($path)>$time; + } + + private function buildPath($path, $create=true) { + $path = $this->stripLeading($path); + $fullPath = $this->datadir.$path; + return $this->mapper->logicToPhysical($fullPath, $create); + } + + private function cleanMapper($path, $isLogicPath=true, $recursive=true) { + $fullPath = $path; + if ($isLogicPath) { + $fullPath = $this->datadir.$path; + } + $this->mapper->removePath($fullPath, $isLogicPath, $recursive); + } + + private function copyMapping($path1, $path2) { + $path1 = $this->stripLeading($path1); + $path2 = $this->stripLeading($path2); + + $fullPath1 = $this->datadir.$path1; + $fullPath2 = $this->datadir.$path2; + + $this->mapper->copy($fullPath1, $fullPath2); + } + + private function stripLeading($path) { + if(strpos($path, '/') === 0) { + $path = substr($path, 1); + } + + return $path; + } +} diff --git a/lib/files/storage/storage.php b/lib/files/storage/storage.php new file mode 100644 index 00000000000..2cc835236ba --- /dev/null +++ b/lib/files/storage/storage.php @@ -0,0 +1,88 @@ +<?php +/** + * Copyright (c) 2012 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; + +/** + * Provide a common interface to all different storage options + */ +interface Storage{ + public function __construct($parameters); + public function getId(); + public function mkdir($path); + public function rmdir($path); + public function opendir($path); + public function is_dir($path); + public function is_file($path); + public function stat($path); + public function filetype($path); + public function filesize($path); + public function isCreatable($path); + public function isReadable($path); + public function isUpdatable($path); + public function isDeletable($path); + public function isSharable($path); + public function getPermissions($path); + public function file_exists($path); + public function filemtime($path); + public function file_get_contents($path); + public function file_put_contents($path,$data); + public function unlink($path); + public function rename($path1,$path2); + public function copy($path1,$path2); + public function fopen($path,$mode); + public function getMimeType($path); + public function hash($type,$path,$raw = false); + public function free_space($path); + public function search($query); + public function touch($path, $mtime=null); + public function getLocalFile($path);// get a path to a local version of the file, whether the original file is local or remote + public function getLocalFolder($path);// get a path to a local version of the folder, whether the original file is local or remote + /** + * check if a file or folder has been updated since $time + * @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); + + /** + * @param string $path + * @return \OC\Files\Cache\Cache + */ + public function getCache($path=''); + /** + * @param string $path + * @return \OC\Files\Cache\Scanner + */ + public function getScanner($path=''); + + public function getOwner($path); + + /** + * @param string $path + * @return \OC\Files\Cache\Permissions + */ + public function getPermissionsCache($path=''); + + /** + * @param string $path + * @return \OC\Files\Cache\Watcher + */ + public function getWatcher($path=''); + + /** + * get the ETag for a file or folder + * + * @param string $path + * @return string + */ + public function getETag($path); +} diff --git a/lib/files/storage/temporary.php b/lib/files/storage/temporary.php new file mode 100644 index 00000000000..d84dbda2e39 --- /dev/null +++ b/lib/files/storage/temporary.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright (c) 2012 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; + +/** + * local storage backend in temporary folder for testing purpose + */ +class Temporary extends Local{ + public function __construct($arguments) { + parent::__construct(array('datadir' => \OC_Helper::tmpFolder())); + } + + public function cleanUp() { + \OC_Helper::rmdirr($this->datadir); + } + + public function __destruct() { + parent::__destruct(); + $this->cleanUp(); + } +} |