From e3ee4fb7dc40681b6e6017d71353ac43c4d1710b Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 7 Feb 2008 06:37:45 +0000 Subject: [PATCH] new egw_vfs class, with many static methods to access the new vfs, see the documentation in the header of egw_vfs --- phpgwapi/inc/class.egw_vfs.inc.php | 195 ++++++++++++++++++ phpgwapi/inc/class.vfs_stream_wrapper.inc.php | 18 +- 2 files changed, 211 insertions(+), 2 deletions(-) create mode 100644 phpgwapi/inc/class.egw_vfs.inc.php diff --git a/phpgwapi/inc/class.egw_vfs.inc.php b/phpgwapi/inc/class.egw_vfs.inc.php new file mode 100644 index 0000000000..810bdca2af --- /dev/null +++ b/phpgwapi/inc/class.egw_vfs.inc.php @@ -0,0 +1,195 @@ + + * @copyright (c) 2008 by Ralf Becker + * @version $Id$ + */ + +/** + * Class containing static methods to use the new eGW virtual file system + * + * This extension of the vfs stream-wrapper allows to use the following static functions, + * which only allow access to the eGW VFS and need no 'vfs://default' prefix for filenames: + * + * - resource egw_vfs::fopen($path,$mode) like fopen, returned resource can be used with fwrite etc. + * - resource egw_vfs::opendir($path) like opendir, returned resource can be used with readdir etc. + * - boolean egw_vfs::copy($from,$to) like copy + * - boolean egw_vfs::rename($old,$new) renaming or moving a file in the vfs + * - boolean egw_vfs::mkdir($path) creating a new dir in the vfs + * - boolean egw_vfs::rmdir($path) removing (an empty) directory + * - boolean egw_vfs::unlink($path) removing a file + * - boolean egw_vfs::touch($path,$mtime=null) touch a file + * - boolean egw_vfs::stat($path) returning status of file like stat(), but only with string keys (no numerical indexes)! + * + * With the exception of egw_vfs::touch() (not yet part of the stream_wrapper interface) + * you can always use the standard php functions, if you add a 'vfs://default' prefix + * to every filename or path. Be sure to always add the prefix, as the user otherwise gains + * access to the real filesystem of the server! + * + * The two following methods can be used to persitently mount further filesystems (without editing the code): + * + * - boolean/array egw_vfs::mount($url,$path) to mount $ur on $path or to return the fstab when called without argument + * - boolean egw_vfs::umount($path) to unmount a path or url + * + * The stream wrapper interface allows to access hugh files in junks to not be limited by the + * memory_limit setting of php. To do you should path a resource to the opened file and not the content: + * + * $file = egw_vfs::fopen('/home/user/somefile','r'); + * $content = fread($file,1024); + * + * You can also attach stream filters, to eg. base64 encode or compress it on the fly, + * without the need to hold the content of the whole file in memmory. + * + * If you want to copy a file, you can use stream_copy_to_stream to do a copy of a file far bigger then + * php's memory_limit: + * + * $from = egw_vfs::fopen('/home/user/fromfile','r'); + * $to = egw_vfs::fopen('/home/user/tofile','w'); + * + * stream_copy_to_stream($from,$to); + * + * The static egw_vfs::copy() method does exactly that, but you have to do it eg. on your own, if + * you want to copy eg. an uploaded file into the vfs. + */ +class egw_vfs extends vfs_stream_wrapper +{ + /** + * fopen working on just the eGW VFS + * + * @param string $path filename with absolute path in the eGW VFS + * @param string $mode 'r', 'w', ... like fopen + * @return resource + */ + static function fopen($path,$mode) + { + if ($path[0] != '/') + { + throw new egw_exception_assertion_failed("Filename '$path' is not an absolute path!"); + } + return fopen(self::SCHEME.'://default'.$path); + } + + /** + * opendir working on just the eGW VFS + * + * @param string $path filename with absolute path in the eGW VFS + * @return resource + */ + static function opendir($path) + { + if ($path[0] != '/') + { + throw new egw_exception_assertion_failed("Directory '$path' is not an absolute path!"); + } + return opendir(self::SCHEME.'://default'.$path); + } + + /** + * copy working on just the eGW VFS + * + * @param string $from + * @param string $to + * @return boolean + */ + static function copy($from,$to) + { + $ret = false; + + if (($from_fp = self::fopen($from,'r')) && + ($to_fp = self::fopen($to,'w'))) + { + $ret = stream_copy_to_stream($from,$to) !== false; + } + if ($from_fp) + { + fclose($from_fp); + } + if ($to_fp) + { + fclose($to_fp); + } + return $ret; + } + + /** + * stat working on just the eGW VFS (alias of url_stat) + * + * @param string $path filename with absolute path in the eGW VFS + * @return resource + */ + static function stat($path) + { + if ($path[0] != '/') + { + throw new egw_exception_assertion_failed("File '$path' is not an absolute path!"); + } + return self::url_stat($path); + } + + + /** + * Mounts $url under $path in the vfs, called without parameter it returns the fstab + * + * The fstab is stored in the eGW configuration and used for all eGW users. + * + * @param string $url=null url of the filesystem to mount, eg. oldvfs://default/ + * @param string $path=null path to mount the filesystem in the vfs, eg. / + * @return array/boolean array with fstab, if called without parameter or true on successful mount + */ + static function mount($url=null,$path=null) + { + if (is_null($url) || is_null($path)) + { + return self::$fstab; + } + if (isset(self::$fstab[$path])) + { + return true; // already mounted + } + if (stat($url) === false && opendir($url) === false) + { + return false; // url does not exist + } + self::$fstab[$path] = $url; + + uksort(self::$fstab,create_function('$a,$b','return strlen($a)-strlen($b);')); + + config::save_value('vfs_fstab',self::$fstab,'phpgwapi'); + $GLOBALS['egw_info']['server']['vfs_fstab'] = self::$fstab; + + return true; + } + + /** + * Unmounts a filesystem part of the vfs + * + * @param string $path url or path of the filesystem to unmount + */ + static function umount($path) + { + if (!isset(self::$fstab[$path]) && ($path = array_search($path,self::$fstab)) === false) + { + return false; // $path not mounted + } + unset(self::$fstab[$path]); + + config::save_value('vfs_fstab',self::$fstab,'phpgwapi'); + $GLOBALS['egw_info']['server']['vfs_fstab'] = self::$fstab; + + return true; + } + + /** + * Private constructor to prevent instanciating this class, only it's static methods should be used + */ + private function __construct() + { + + } +} diff --git a/phpgwapi/inc/class.vfs_stream_wrapper.inc.php b/phpgwapi/inc/class.vfs_stream_wrapper.inc.php index c645bce6c1..22bfe92b65 100644 --- a/phpgwapi/inc/class.vfs_stream_wrapper.inc.php +++ b/phpgwapi/inc/class.vfs_stream_wrapper.inc.php @@ -21,6 +21,10 @@ */ class vfs_stream_wrapper implements iface_stream_wrapper { + /** + * Scheme / protocoll used for this stream-wrapper + */ + const SCHEME = 'vfs'; /** * optional context param when opening the stream, null if no context passed * @@ -35,7 +39,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper * * @var array */ - static $fstab = array( + protected static $fstab = array( '/' => 'oldvfs://$user:$pass@$host/', // '/files' => 'oldvfs://$user:$pass@$host/home/Default', // '/images' => 'http://localhost/egroupware/phpgwapi/templates/idots/images', @@ -520,6 +524,16 @@ class vfs_stream_wrapper implements iface_stream_wrapper } return self::$wrappers; } + + static function init_static() + { + stream_register_wrapper(self::SCHEME,__CLASS__); + + if ($GLOBALS['egw_info']['server']['vfs_fstab'] && is_array($GLOBALS['egw_info']['server']['vfs_fstab'])) + { + self::$fstab = $GLOBALS['egw_info']['server']['vfs_fstab']; + } + } } -stream_register_wrapper('vfs','vfs_stream_wrapper'); +vfs_stream_wrapper::init_static(); \ No newline at end of file