diff options
author | Robin Appelman <icewind1991@gmail.com> | 2011-08-15 20:37:50 +0200 |
---|---|---|
committer | Robin Appelman <icewind1991@gmail.com> | 2011-08-15 21:09:13 +0200 |
commit | 6173c0fbc262f0d02c45d9cf4e81b020ad839145 (patch) | |
tree | 7c453e5dce300051efbcc3721eec4d7306c6000d /lib | |
parent | 2f1a06b2ee8b2022e71d8903fd5ce0ccf2f8c22f (diff) | |
download | nextcloud-server-6173c0fbc262f0d02c45d9cf4e81b020ad839145.tar.gz nextcloud-server-6173c0fbc262f0d02c45d9cf4e81b020ad839145.zip |
a bit of refactoring for oc_filesystem and implement user quota
Diffstat (limited to 'lib')
-rw-r--r-- | lib/fileproxy.php | 111 | ||||
-rw-r--r-- | lib/fileproxy/quota.php | 61 | ||||
-rw-r--r-- | lib/filesystem.php | 278 | ||||
-rw-r--r-- | lib/util.php | 2 |
4 files changed, 258 insertions, 194 deletions
diff --git a/lib/fileproxy.php b/lib/fileproxy.php new file mode 100644 index 00000000000..549b7015a6a --- /dev/null +++ b/lib/fileproxy.php @@ -0,0 +1,111 @@ +<?php + +/** +* ownCloud +* +* @author Robin Appelman +* @copyright 2011 Robin Appelman icewind1991@gmail.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/>. +* +*/ + +/** + * Class for manipulating filesystem requests + * + * Manipulation happens by using 2 kind of proxy operations, pre and post proxies + * that manipulate the filesystem call and the result of the call respectively + * + * A pre-proxy recieves the filepath as arugments (or 2 filespaths in case of operations like copy or move) and return a boolean + * If a pre-proxy returnes false the file operation will be canceled + * All filesystem operations have a pre-proxy + * + * A post-proxy recieves 2 arguments, the filepath and the result of the operation. + * The return calue of the post-proxy will be used as the new result of the operation + * The operations that have a post-proxy are + * file_get_contents, is_file, is_dir, file_exists, stat, is_readable, is_writable, fileatime, filemtime, filectime, file_get_contents, getMimeType, hash, free_space and search + */ + +class OC_FileProxy{ + private static $proxies=array(); + + /** + * check if this proxy implments a specific proxy operation + * @param string #proxy name of the proxy operation + * @return bool + */ + public function provides($operation){ + return method_exists($this,$operation); + } + + /** + * fallback function when a proxy operation is not implement + * @param string $function the name of the proxy operation + * @param mixed + * + * this implements a dummy proxy for all operations + */ + public function __call($function,$arguments){ + if(substr($function,0,3)=='pre'){ + return true; + }else{ + return $arguments[1]; + } + } + + /** + * register a proxy to be used + * @param OC_FileProxy $proxy + */ + public static function register($proxy){ + self::$proxies[]=$proxy; + } + + public static function getProxies($operation,$post){ + $operation=(($post)?'post':'pre').$operation; + $proxies=array(); + foreach(self::$proxies as $proxy){ + if($proxy->provides($operation)){ + $proxies[]=$proxy; + } + } + return $proxies; + } + + public static function runPreProxies($operation,$filepath,$filepath2=null){ + $proxies=self::getProxies($operation,false); + $operation='pre'.$operation; + foreach($proxies as $proxy){ + if($filepath2){ + if(!$proxy->$operation($filepath,$filepath2)){ + return false; + } + }else{ + if(!$proxy->$operation($filepath)){ + return false; + } + } + } + return true; + } + + public static function runPostProxies($operation,$path,$result){ + $proxies=self::getProxies($operation,true); + $operation='post'.$operation; + foreach($proxies as $proxy){ + $result=$proxy->$operation($path,$result); + } + return $result; + } +}
\ No newline at end of file diff --git a/lib/fileproxy/quota.php b/lib/fileproxy/quota.php new file mode 100644 index 00000000000..af8ddee1473 --- /dev/null +++ b/lib/fileproxy/quota.php @@ -0,0 +1,61 @@ +<?php + +/** +* ownCloud +* +* @author Robin Appelman +* @copyright 2011 Robin Appelman icewind1991@gmail.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/>. +* +*/ + +/** + * user quota managment + */ + +class OC_FileProxy_Quota extends OC_FileProxy{ + private function getFreeSpace(){ + $usedSpace=OC_Filesystem::filesize(''); + $totalSpace=OC_Preferences::getValue(OC_User::getUser(),'files','quota',0); + if($totalSpace==0){ + return 0; + } + return $totalSpace-$usedSpace; + } + + public function postFree_space($path,$space){ + $free=$this->getFreeSpace(); + if($free==0){ + return $space; + } + return min($free,$space); + } + + public function preFile_put_contents($path,$data){ + return (strlen($data)<$this->getFreeSpace() or $this->getFreeSpace()==0); + } + + public function preCopy($path1,$path2){ + return (OC_Filesystem::filesize($path1)<$this->getFreeSpace() or $this->getFreeSpace()==0); + } + + public function preFromTmpFile($tmpfile,$path){ + return (filesize($tmpfile)<$this->getFreeSpace() or $this->getFreeSpace()==0); + } + + public function preFromUploadedFile($tmpfile,$path){ + return (filesize($tmpfile)<$this->getFreeSpace() or $this->getFreeSpace()==0); + } +}
\ No newline at end of file diff --git a/lib/filesystem.php b/lib/filesystem.php index a688c9c2b06..911a85e4a33 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -228,150 +228,71 @@ class OC_Filesystem{ } static public function mkdir($path){ - $parent=substr($path,0,strrpos($path,'/')); - if(self::canWrite($parent) and $storage=self::getStorage($path)){ - $run=true; - OC_Hook::emit( 'OC_Filesystem', 'create', array( 'path' => $path, 'run' => &$run)); - if($run){ - OC_Hook::emit( 'OC_Filesystem', 'write', array( 'path' => $path, 'run' => &$run)); - } - if($run){ - $result=$storage->mkdir(self::getInternalPath($path)); - OC_Hook::emit( 'OC_Filesystem', 'post_create', array( 'path' => $path)); - OC_Hook::emit( 'OC_Filesystem', 'post_write', array( 'path' => $path)); - return $result; - } - } + return self::basicOperation('mkdir',$path,array('create','write')); } static public function rmdir($path){ - if(self::canWrite($path) and $storage=self::getStorage($path)){ - $run=true; - OC_Hook::emit( 'OC_Filesystem', 'delete', array( 'path' => $path, 'run' => &$run)); - if($run){ - $result=$storage->rmdir(self::getInternalPath($path)); - OC_Hook::emit( 'OC_Filesystem', 'post_delete', array( 'path' => $path)); - return $result; - } - } + return self::basicOperation('rmdir',$path,array('delete')); } static public function opendir($path){ - if(self::canRead($path) and $storage=self::getStorage($path)){ - OC_Hook::emit( 'OC_Filesystem', 'read', array( 'path' => $path)); - return $storage->opendir(self::getInternalPath($path)); - } + return self::basicOperation('opendir',$path,array('read')); } static public function is_dir($path){ if($path=='/'){ return true; } - if(self::canRead($path) and $storage=self::getStorage($path)){ - return $storage->is_dir(self::getInternalPath($path)); - } + return self::basicOperation('is_dir',$path); } static public function is_file($path){ if($path=='/'){ return false; } - if(self::canRead($path) and $storage=self::getStorage($path)){ - return $storage->is_file(self::getInternalPath($path)); - } + return self::basicOperation('is_file',$path); } static public function stat($path){ - if(self::canRead($path) and $storage=self::getStorage($path)){ - return $storage->stat(self::getInternalPath($path)); - } + return self::basicOperation('stat',$path); } static public function filetype($path){ - if(self::canRead($path) and $storage=self::getStorage($path)){ - return $storage->filetype(self::getInternalPath($path)); - } + return self::basicOperation('filetype',$path); } static public function filesize($path){ - if(self::canRead($path) and $storage=self::getStorage($path)){ - return $storage->filesize(self::getInternalPath($path)); - } + return self::basicOperation('filesize',$path); } static public function readfile($path){ - if(self::canRead($path) and $storage=self::getStorage($path)){ - OC_Hook::emit( 'OC_Filesystem', 'read', array( 'path' => $path)); - return $storage->readfile(self::getInternalPath($path)); - } + return self::basicOperation('readfile',$path,array('read')); } static public function is_readable($path){ - if(self::canRead($path) and $storage=self::getStorage($path)){ - return $storage->is_readable(self::getInternalPath($path)); - } - return false; + return self::basicOperation('is_readable',$path); } static public function is_writeable($path){ - if(self::canWrite($path) and $storage=self::getStorage($path)){ - return $storage->is_writeable(self::getInternalPath($path)); - } - return false; + return self::basicOperation('is_writeable',$path); } static public function file_exists($path){ if($path=='/'){ return true; } - if(self::canWrite($path) and $storage=self::getStorage($path)){ - return $storage->file_exists(self::getInternalPath($path)); - } - return false; + return self::basicOperation('file_exists',$path); } static public function filectime($path){ - if($storage=self::getStorage($path)){ - return $storage->filectime(self::getInternalPath($path)); - } + return self::basicOperation('filectime',$path); } static public function filemtime($path){ - if($storage=self::getStorage($path)){ - return $storage->filemtime(self::getInternalPath($path)); - } + return self::basicOperation('filemtime',$path); } static public function fileatime($path){ - if($storage=self::getStorage($path)){ - return $storage->fileatime(self::getInternalPath($path)); - } + return self::basicOperation('fileatime',$path); } static public function file_get_contents($path){ - if(self::canRead($path) and $storage=self::getStorage($path)){ - OC_Hook::emit( 'OC_Filesystem', 'read', array( 'path' => $path)); - return $storage->file_get_contents(self::getInternalPath($path)); - } + return self::basicOperation('file_get_contents',$path,array('read')); } static public function file_put_contents($path,$data){ - if(self::canWrite($path) and $storage=self::getStorage($path)){ - $run=true; - $exists=self::file_exists($path); - if(!$exists){ - OC_Hook::emit( 'OC_Filesystem', 'create', array( 'path' => $path, 'run' => &$run)); - } - if($run){ - OC_Hook::emit( 'OC_Filesystem', 'write', array( 'path' => $path, 'run' => &$run)); - } - if($run){ - $result=$storage->file_put_contents(self::getInternalPath($path),$data); - if(!$exists){ - OC_Hook::emit( 'OC_Filesystem', 'post_create', array( 'path' => $path)); - } - OC_Hook::emit( 'OC_Filesystem', 'post_write', array( 'path' => $path)); - return $result; - } - } + error_log($data); + return self::basicOperation('file_put_contents',$path,array('create','write'),$data); } static public function unlink($path){ - if(self::canWrite($path) and $storage=self::getStorage($path)){ - $run=true; - OC_Hook::emit( 'OC_Filesystem', 'delete', array( 'path' => $path, 'run' => &$run)); - if($run){ - $result=$storage->unlink(self::getInternalPath($path)); - OC_Hook::emit( 'OC_Filesystem', 'post_delete', array( 'path' => $path)); - return $result; - } - } + return self::basicOperation('unlink',$path,array('delete')); } static public function rename($path1,$path2){ - if(self::canWrite($path1) and self::canWrite($path2)){ + if(OC_FileProxy::runPreProxies('rename',$path1,$path2) and self::canWrite($path1) and self::canWrite($path2)){ $run=true; OC_Hook::emit( 'OC_Filesystem', 'rename', array( 'oldpath' => $path1 ,'newpath'=>$path2, 'run' => &$run)); if($run){ @@ -392,7 +313,7 @@ class OC_Filesystem{ } } static public function copy($path1,$path2){ - if(self::canRead($path1) and self::canWrite($path2)){ + if(OC_FileProxy::runPreProxies('copy',$path1,$path2) and self::canRead($path1) and self::canWrite($path2)){ $run=true; OC_Hook::emit( 'OC_Filesystem', 'copy', array( 'oldpath' => $path1 ,'newpath'=>$path2, 'run' => &$run)); $exists=self::file_exists($path2); @@ -423,60 +344,35 @@ class OC_Filesystem{ } } static public function fopen($path,$mode){ - $allowed=((strpos($path,'r')===false and strpos($path,'r+')!==false and self::canRead) or self::canWrite($path)); - if($allowed){ - if($storage=self::getStorage($path)){ - $run=true; - $exists=self::file_exists($path); - $write=false; - switch($mode){ - case 'r': - OC_Hook::emit( 'OC_Filesystem', 'read', array( 'path' => $path)); - break; - case 'r+': - case 'w+': - case 'x+': - case 'a+': - OC_Hook::emit( 'OC_Filesystem', 'read', array( 'path' => $path)); - $write=true; - break; - case 'w': - case 'x': - case 'a': - $write=true; - break; - } - if($write){ - if(!$exists){ - OC_Hook::emit( 'OC_Filesystem', 'create', array( 'path' => $path)); - } - if($run){ - OC_Hook::emit( 'OC_Filesystem', 'write', array( 'path' => $path, 'run' => &$run)); - } - } - if($run){ - $result=$storage->fopen(self::getInternalPath($path),$mode); - if($write){ - if(!$exists){ - OC_Hook::emit( 'OC_Filesystem', 'post_create', array( 'path' => $path)); - } - if($run){ - OC_Hook::emit( 'OC_Filesystem', 'post_write', array( 'path' => $path)); - } - } - return $result; - } - } + $hooks=array(); + switch($mode){ + case 'r': + $hooks[]='read'; + break; + case 'r+': + case 'w+': + case 'x+': + case 'a+': + $hooks[]='read'; + $hooks[]='write'; + break; + case 'w': + case 'x': + case 'a': + $hooks[]='write'; + break; } + + return self::basicOperation('fopen',$path,$hooks); } static public function toTmpFile($path){ - if(self::canRead($path) and $storage=self::getStorage($path)){ + if(OC_FileProxy::runPreProxies('toTmpFile',$path) and self::canRead($path) and $storage=self::getStorage($path)){ OC_Hook::emit( 'OC_Filesystem', 'read', array( 'path' => $path)); return $storage->toTmpFile(self::getInternalPath($path)); } } static public function fromTmpFile($tmpFile,$path){ - if(self::canWrite($path) and $storage=self::getStorage($path)){ + if(OC_FileProxy::runPreProxies('copy',$tmpFile,$path) and self::canWrite($path) and $storage=self::getStorage($path)){ $run=true; $exists=self::file_exists($path); if(!$exists){ @@ -497,7 +393,7 @@ class OC_Filesystem{ } static public function fromUploadedFile($tmpFile,$path){ error_log('upload'); - if(self::canWrite($path) and $storage=self::getStorage($path)){ + if(OC_FileProxy::runPreProxies('fromUploadedFile',$tmpFile,$path) and self::canWrite($path) and $storage=self::getStorage($path)){ $run=true; $exists=self::file_exists($path); if(!$exists){ @@ -518,57 +414,14 @@ class OC_Filesystem{ } } static public function getMimeType($path){ - if(self::canRead($path) and $storage=self::getStorage($path)){ - return $storage->getMimeType(self::getInternalPath($path)); - } + return self::basicOperation('getMimeType',$path); } - static public function delTree($path){ - if(self::canWrite($path) and $storage=self::getStorage($path)){ - $run=true; - OC_Hook::emit( 'OC_Filesystem', 'delete', array( 'path' => $path, 'run' => &$run)); - if($run){ - return $storage->delTree(self::getInternalPath($path)); - } - } - } - static public function find($path){ - if($storage=self::getStorage($path)){ - $mp=self::getMountPoint($path); - $return=$storage->find(self::getInternalPath($path)); - foreach($return as &$file){ - $file=$mp.$file; - } - } - return $return; - } - static public function getTree($path){ - if(self::canRead($path) and $storage=self::getStorage($path)){ - $mp=self::getMountPoint($path); - $return=$storage->getTree(self::getInternalPath($path)); - foreach($return as &$file){ - if(substr($file,0,1)=='/'){ - $file=substr($file,1); - } - $file=$mp.$file; - $file=substr($file,strlen(self::$fakeRoot)); - if($file === '' || $file === false){ - $file = '/'; - } - } - return $return; - } - } - static public function hash($type,$path,$raw=false){ - if(self::canRead($path) and $storage=self::getStorage($path)){ - OC_Hook::emit( 'OC_Filesystem', 'read', array( 'path' => $path)); - return $storage->hash($type,self::getInternalPath($path),$raw); - } + static public function hash($type,$path){ + return self::basicOperation('hash',$path,array('read')); } static public function free_space($path='/'){ - if(self::canRead($path) and $storage=self::getStorage($path)){ - return $storage->free_space($path); - } + return self::basicOperation('free_space',$path); } static public function search($query){ @@ -590,4 +443,41 @@ class OC_Filesystem{ return $files; } + + /** + * abstraction for running most basic operations + * @param string $operation + * @param string #path + * @param array (optional) hooks + * @param mixed (optional) $extraParam + * @return mixed + */ + private static function basicOperation($operation,$path,$hooks=array(),$extraParam=null){ + if(OC_FileProxy::runPreProxies($operation,$path) and self::canRead($path) and $storage=self::getStorage($path)){ + $interalPath=self::getInternalPath($path); + $run=true; + foreach($hooks as $hook){ + if($hook!='read'){ + OC_Hook::emit( 'OC_Filesystem', $hook, array( 'path' => $path, 'run' => &$run)); + }else{ + OC_Hook::emit( 'OC_Filesystem', $hook, array( 'path' => $path)); + } + } + if($run){ + if($extraParam){ + $result=$storage->$operation($interalPath,$extraParam); + }else{ + $result=$storage->$operation($interalPath); + } + $result=OC_FileProxy::runPostProxies($operation,$path,$result); + foreach($hooks as $hook){ + if($hook!='read'){ + OC_Hook::emit( 'OC_Filesystem', 'post_'.$hook, array( 'path' => $path)); + } + } + return $result; + } + } + return null; + } } diff --git a/lib/util.php b/lib/util.php index 83d39b3dd21..0fdfa012305 100644 --- a/lib/util.php +++ b/lib/util.php @@ -74,6 +74,8 @@ class OC_Util { //jail the user into his "home" directory OC_Filesystem::chroot("/$user/$root"); + $quotaProxy=new OC_FileProxy_Quota(); + OC_FileProxy::register($quotaProxy); self::$fsSetup=true; } } |