mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-26 00:29:38 +01:00
- unlink/mkdir/rmdir methods
- caching the information for dir_open vfs_sql::ls() to use it in url_stat, to not read it again from the db - implemented a static touch method, which is not (yet) part of the stream-wrapper interface
This commit is contained in:
parent
fbc8aa7be7
commit
399e087f2c
@ -18,25 +18,6 @@ if (isset($_SERVER['HTTP_HOST'])) // security precaution: forbit calling ls as w
|
||||
die('<h1>'.basename(__FILE__).' must NOT be called as web-page --> exiting !!!</h1>');
|
||||
}
|
||||
|
||||
/*
|
||||
// this is kind of a hack, as the autocreate_session_callback can not change the type of the loaded account-class
|
||||
// so we need to make sure the right one is loaded by setting the domain before the header gets included.
|
||||
$arg0s = explode(',',@$arguments[0]);
|
||||
@list(,$_GET['domain']) = explode('@',$arg0s[0]);
|
||||
|
||||
if (is_dir('/tmp')) ini_set('session.save_path','/tmp'); // regular users may have no rights to apache's session dir
|
||||
|
||||
$GLOBALS['egw_info'] = array(
|
||||
'flags' => array(
|
||||
'currentapp' => 'admin',
|
||||
'noheader' => true,
|
||||
'autocreate_session_callback' => 'user_pass_from_argv',
|
||||
)
|
||||
);
|
||||
|
||||
include('../header.inc.php');
|
||||
*/
|
||||
|
||||
/**
|
||||
* callback if the session-check fails, redirects via xajax to login.php
|
||||
*
|
||||
@ -64,14 +45,19 @@ function user_pass_from_argv(&$account)
|
||||
function usage($action=null,$ret=0)
|
||||
{
|
||||
$cmd = basename(__FILE__);
|
||||
echo "Usage: $cmd URL\n";
|
||||
echo "\t$cmd --cat URL\n";
|
||||
echo "Usage:\t$cmd URL [URL2 ...]\n";
|
||||
echo "\t$cmd --cat URL [URL2 ...]\n";
|
||||
echo "\t$cmd --cp URL-from URL-to\n";
|
||||
echo "\t$cmd --cp URL-from1 [URL-from2 ...] URL-to-directory\n";
|
||||
echo "\t$cmd --cp URL-from [URL-from2 ...] URL-to-directory\n";
|
||||
echo "\t$cmd --rm URL [URL2 ...]\n";
|
||||
echo "\t$cmd --mkdir [-p|--parents] URL [URL2 ...]\n";
|
||||
echo "\t$cmd --rmdir URL [URL2 ...]\n";
|
||||
echo "\t$cmd --touch [-d|--date time] URL [URL2 ...]\n";
|
||||
echo "URL: oldvfs://user:password@domain/home/user/file, /dir/file, ...\n";
|
||||
|
||||
exit;
|
||||
}
|
||||
$long = $numeric = false;
|
||||
$long = $numeric = $recursive = false;
|
||||
$argv = $_SERVER['argv'];
|
||||
$cmd = basename(array_shift($argv),'.php');
|
||||
|
||||
@ -97,9 +83,24 @@ foreach($argv as $key => $option)
|
||||
$numeric = true;
|
||||
continue 2; // switch is counting too!
|
||||
|
||||
case '-r': case '--recursive':
|
||||
case '-p': case '--parents':
|
||||
$recursive = true;
|
||||
continue 2; // switch is counting too!
|
||||
|
||||
case '-d': case '--date':
|
||||
$time = strtotime($argv[$key+1]);
|
||||
unset($argv[$key+1]);
|
||||
break;
|
||||
|
||||
case '--cat': // cat files (!) to stdout
|
||||
case '--cp': // cp files
|
||||
case '--rm': // rm files
|
||||
case '--cp': // copy files
|
||||
case '--rm': // remove files
|
||||
case '--ls': // list files
|
||||
case '--rmdir': // remove dirs
|
||||
case '--mkdir': // make directories
|
||||
case '--rename':// rename
|
||||
case '--touch': // touch
|
||||
$cmd = substr($option,2);
|
||||
continue 2; // switch is counting too!
|
||||
}
|
||||
@ -113,49 +114,90 @@ switch($cmd)
|
||||
do_cp($argv);
|
||||
break;
|
||||
|
||||
case 'rename':
|
||||
if (count($argv) != 2) usage(null,3);
|
||||
load_wrapper($argv[0]);
|
||||
load_wrapper($argv[1]);
|
||||
rename($argv[0],$argv[1]);
|
||||
break;
|
||||
|
||||
default:
|
||||
while($url = array_shift($argv))
|
||||
{
|
||||
load_wrapper($url);
|
||||
//echo "$cmd $url (long=".(int)$long.", numeric=".(int)$numeric.")\n";
|
||||
|
||||
if ($cmd == 'rm')
|
||||
switch($cmd)
|
||||
{
|
||||
unlink($url);
|
||||
}
|
||||
elseif (is_dir($url) && ($dir = opendir($url)))
|
||||
{
|
||||
if ($argc)
|
||||
{
|
||||
echo "\n".basename(parse_url($url,PHP_URL_PATH)).":\n";
|
||||
}
|
||||
while(($file = readdir($dir)) !== false)
|
||||
{
|
||||
do_stat($url.'/'.$file,$long,$numeric);
|
||||
}
|
||||
closedir($dir);
|
||||
}
|
||||
elseif ($cmd == 'cat')
|
||||
{
|
||||
if (!($f = fopen($url,'r')))
|
||||
{
|
||||
echo "File $url not found !!!\n\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($argc)
|
||||
case 'rm':
|
||||
unlink($url);
|
||||
break;
|
||||
|
||||
case 'rmdir':
|
||||
rmdir($url);
|
||||
break;
|
||||
|
||||
case 'mkdir':
|
||||
mkdir($url,null,$recursive);
|
||||
break;
|
||||
|
||||
case 'touch':
|
||||
if (($scheme = parse_url($url,PHP_URL_SCHEME)))
|
||||
{
|
||||
echo "\n".basename(parse_url($url,PHP_URL_PATH)).":\n";
|
||||
load_wrapper($url);
|
||||
if (class_exists($class = $scheme.'_stream_wrapper') && method_exists($class,'touch'))
|
||||
{
|
||||
call_user_func(array($scheme.'_stream_wrapper','touch'),$url,$time);
|
||||
}
|
||||
else
|
||||
{
|
||||
die("Can't touch for scheme $scheme!\n");
|
||||
}
|
||||
}
|
||||
fpassthru($f);
|
||||
fclose($f);
|
||||
}
|
||||
else
|
||||
{
|
||||
touch($url,$time);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'cat':
|
||||
case 'ls':
|
||||
default:
|
||||
if (is_dir($url) && ($dir = opendir($url)))
|
||||
{
|
||||
if ($argc)
|
||||
{
|
||||
echo "\n".basename(parse_url($url,PHP_URL_PATH)).":\n";
|
||||
}
|
||||
while(($file = readdir($dir)) !== false)
|
||||
{
|
||||
do_stat($url.'/'.$file,$long,$numeric);
|
||||
}
|
||||
closedir($dir);
|
||||
}
|
||||
elseif ($cmd == 'cat')
|
||||
{
|
||||
if (!($f = fopen($url,'r')))
|
||||
{
|
||||
echo "File $url not found !!!\n\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($argc)
|
||||
{
|
||||
echo "\n".basename(parse_url($url,PHP_URL_PATH)).":\n";
|
||||
}
|
||||
fpassthru($f);
|
||||
fclose($f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
do_stat($url,$long,$numeric);
|
||||
}
|
||||
if (!$long && $cmd == 'ls') echo "\n";
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
do_stat($url,$long,$numeric);
|
||||
}
|
||||
if (!$long && $cmd == 'ls') echo "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,12 +208,13 @@ switch($cmd)
|
||||
*/
|
||||
function load_wrapper($url)
|
||||
{
|
||||
switch(parse_url($url,PHP_URL_SCHEME))
|
||||
switch($scheme = parse_url($url,PHP_URL_SCHEME))
|
||||
{
|
||||
case 'webdav':
|
||||
require_once('HTTP/WebDAV/Client.php');
|
||||
break;
|
||||
case 'oldvfs':
|
||||
case 'vfs':
|
||||
if (!isset($GLOBALS['egw_info']))
|
||||
{
|
||||
$_GET['domain'] = parse_url($url,PHP_URL_HOST);
|
||||
@ -193,13 +236,16 @@ function load_wrapper($url)
|
||||
|
||||
include('../header.inc.php');
|
||||
}
|
||||
require_once(EGW_API_INC.'/class.oldvfs_stream_wrapper.inc.php');
|
||||
require_once(EGW_API_INC.'/class.'.$scheme.'_stream_wrapper.inc.php');
|
||||
break;
|
||||
case '':
|
||||
case 'ftp':
|
||||
case '': // default scheme is file and alsways available
|
||||
break;
|
||||
default:
|
||||
die("Unknown scheme in $url !!!\n\n");
|
||||
if (!in_array($scheme,stream_get_wrappers()))
|
||||
{
|
||||
die("Unknown scheme '$scheme' in $url !!!\n\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,9 +261,8 @@ function do_stat($url,$long=false,$numeric=false)
|
||||
//echo "do_stat($url,$long,$numeric)\n";
|
||||
$bname = basename(parse_url($url,PHP_URL_PATH));
|
||||
|
||||
if ($long)
|
||||
if ($long && ($stat = stat($url)))
|
||||
{
|
||||
$stat = stat($url);
|
||||
//print_r($stat);
|
||||
|
||||
$perms = verbosePerms($stat['mode']);
|
||||
@ -233,13 +278,13 @@ function do_stat($url,$long=false,$numeric=false)
|
||||
$uid = isset($GLOBALS['egw']) ? $GLOBALS['egw']->accounts->id2name($stat['uid']) : posix_getpwuid($stat['uid']);
|
||||
if (is_array($uid)) $uid = $uid['name'];
|
||||
}
|
||||
if (!isset($uid)) $uid = 'none';
|
||||
if (!isset($uid)) $uid = 'root';
|
||||
if ($stat['gid'])
|
||||
{
|
||||
$gid = isset($GLOBALS['egw']) ? $GLOBALS['egw']->accounts->id2name($stat['gid']) : posix_getgrgid($stat['gid']);
|
||||
if (is_array($gid)) $gid = $gid['name'];
|
||||
}
|
||||
if (!isset($gid)) $gid = 'none';
|
||||
if (!isset($gid)) $gid = 'root';
|
||||
}
|
||||
$size = hsize($stat['size']);
|
||||
$mtime = date('Y-m-d H:i:s',$stat['mtime']);
|
||||
@ -322,7 +367,7 @@ function do_cp($argv)
|
||||
|
||||
if (count($argv) > 1 && !is_dir($to))
|
||||
{
|
||||
die ("Usage: cp from-file to-file | cp file1 [file2 ...] dir\n\n");
|
||||
usage(null,4);
|
||||
}
|
||||
if (count($argv) > 1)
|
||||
{
|
||||
@ -337,7 +382,7 @@ function do_cp($argv)
|
||||
|
||||
if (!($from_fp = fopen($from,'r')))
|
||||
{
|
||||
die("File $from not found!");
|
||||
die("File $from not found!\n");
|
||||
}
|
||||
if (is_dir($to))
|
||||
{
|
||||
@ -346,7 +391,7 @@ function do_cp($argv)
|
||||
}
|
||||
if (!($to_fp = fopen($to,'w')))
|
||||
{
|
||||
die("Can't open $to from writing!");
|
||||
die("Can't open $to for writing!\n");
|
||||
}
|
||||
$count = stream_copy_to_stream($from_fp,$to_fp);
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
*
|
||||
* The interface is according to the docu on php.net
|
||||
*
|
||||
* @link http://de.php.net/manual/de/function.stream-wrapper-register.php
|
||||
* @link http://www.php.net/manual/en/function.stream-wrapper-register.php
|
||||
*/
|
||||
interface iface_stream_wrapper
|
||||
{
|
||||
@ -149,11 +149,13 @@ interface iface_stream_wrapper
|
||||
* It should attempt to rename the item specified by path_from to the specification given by path_to.
|
||||
* In order for the appropriate error message to be returned, do not define this method if your wrapper does not support renaming.
|
||||
*
|
||||
* The regular filesystem stream-wrapper returns an error, if $url_from and $url_to are not either both files or both dirs!
|
||||
*
|
||||
* @param string $path_from
|
||||
* @param string $path_to
|
||||
* @return boolean TRUE on success or FALSE on failure
|
||||
*/
|
||||
function rename ( $path_from, $path_to );
|
||||
static function rename ( $path_from, $path_to );
|
||||
|
||||
/**
|
||||
* This method is called in response to mkdir() calls on URL paths associated with the wrapper.
|
||||
@ -166,7 +168,7 @@ interface iface_stream_wrapper
|
||||
* @param int $options Posible values include STREAM_REPORT_ERRORS and STREAM_MKDIR_RECURSIVE
|
||||
* @return boolean TRUE on success or FALSE on failure
|
||||
*/
|
||||
function mkdir ( $path, $mode, $options );
|
||||
static function mkdir ( $path, $mode, $options );
|
||||
|
||||
/**
|
||||
* This method is called in response to rmdir() calls on URL paths associated with the wrapper.
|
||||
@ -178,7 +180,7 @@ interface iface_stream_wrapper
|
||||
* @param int $options Possible values include STREAM_REPORT_ERRORS.
|
||||
* @return boolean TRUE on success or FALSE on failure.
|
||||
*/
|
||||
function rmdir ( $path, $options );
|
||||
static function rmdir ( $path, $options );
|
||||
|
||||
/**
|
||||
* This method is called immediately when your stream object is created for examining directory contents with opendir().
|
||||
@ -211,9 +213,10 @@ interface iface_stream_wrapper
|
||||
* This flag is set in response to calls to lstat(), is_link(), or filetype().
|
||||
* - STREAM_URL_STAT_QUIET If this flag is set, your wrapper should not raise any errors. If this flag is not set,
|
||||
* you are responsible for reporting errors using the trigger_error() function during stating of the path.
|
||||
* stat triggers it's own warning anyway, so it makes no sense to trigger one by our stream-wrapper!
|
||||
* @return array
|
||||
*/
|
||||
function url_stat ( $path, $flags );
|
||||
static function url_stat ( $path, $flags );
|
||||
|
||||
/**
|
||||
* This method is called in response to readdir().
|
||||
|
@ -7,7 +7,7 @@
|
||||
* @package api
|
||||
* @subpackage vfs
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2007 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2007-8 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
@ -30,12 +30,17 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
*
|
||||
*/
|
||||
const USE_FILESYSTEM_DIRECT = true;
|
||||
/**
|
||||
* Mime type of directories, the old vfs uses 'Directory', while eg. WebDAV uses 'httpd/unix-directory'
|
||||
*
|
||||
*/
|
||||
const DIR_MIME_TYPE = 'Directory';
|
||||
/**
|
||||
* How much should be logged to the apache error-log
|
||||
*
|
||||
* 0 = Nothing
|
||||
* 1 = only errors
|
||||
* 2 = all function calls and errors
|
||||
* 2 = all function calls and errors (contains passwords too!)
|
||||
*/
|
||||
const LOG_LEVEL = 1;
|
||||
|
||||
@ -78,20 +83,22 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
*/
|
||||
protected $opened_pos;
|
||||
/**
|
||||
* Global vfs::ls() cache
|
||||
* Directory vfs::ls() of dir opened with dir_opendir()
|
||||
*
|
||||
* This static var gets overwritten by each new dir_opendir, it helps to not read the entries twice.
|
||||
*
|
||||
* @var array $path => info-array pairs
|
||||
*/
|
||||
static private $stat_cache;
|
||||
/**
|
||||
* Array with filenames of dir opened with dir_opendir
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
static protected $cache=array();
|
||||
/**
|
||||
* Directory vfs::ls() of path opened with dir_opendir()
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $opened_dir;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Constructor, only called for the non-static stream_* methods!
|
||||
*
|
||||
* @return oldvfs_stream_wrapper
|
||||
*/
|
||||
@ -138,7 +145,12 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
'operation' => EGW_ACL_ADD,
|
||||
)))
|
||||
{
|
||||
self::remove_password($url);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."($url,$mode,$options) file does not exist or can not be created!");
|
||||
if (!($options & STREAM_URL_STAT_QUIET))
|
||||
{
|
||||
trigger_error(__METHOD__."($url,$mode,$options) file does not exist or can not be created!",E_USER_WARNING);
|
||||
}
|
||||
$this->opened_data = $this->opened_path = $this->opened_mode = null;
|
||||
return false;
|
||||
}
|
||||
@ -152,7 +164,12 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
'operation' => EGW_ACL_EDIT,
|
||||
)))
|
||||
{
|
||||
self::remove_password($url);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."($url,$mode,$options) file can not be edited!");
|
||||
if (!($options & STREAM_URL_STAT_QUIET))
|
||||
{
|
||||
trigger_error(__METHOD__."($url,$mode,$options) file can not be edited!",E_USER_WARNING);
|
||||
}
|
||||
$this->opened_data = $this->opened_path = $this->opened_mode = null;
|
||||
return false;
|
||||
}
|
||||
@ -311,8 +328,10 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
$len = bytes($this->opened_data);
|
||||
$eof = $this->opened_pos >= $len;
|
||||
}
|
||||
if (self::LOG_LEVEL > 1) error_log(__METHOD__."() pos=$this->opened_pos >= $len=len --> ".($eof ? 'true' : 'false'));
|
||||
|
||||
if (self::LOG_LEVEL > 1)
|
||||
{
|
||||
error_log(__METHOD__."() pos=$this->opened_pos >= $len=len --> ".($eof ? 'true' : 'false'));
|
||||
}
|
||||
return $eof;
|
||||
}
|
||||
|
||||
@ -385,6 +404,7 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
{
|
||||
return fflush($this->opened_data);
|
||||
}
|
||||
// we cant flush, as the old vfs can only write the whole data as once
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -415,13 +435,15 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
* It should attempt to delete the item specified by path.
|
||||
* In order for the appropriate error message to be returned, do not define this method if your wrapper does not support unlinking!
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $url
|
||||
* @return boolean TRUE on success or FALSE on failure
|
||||
*/
|
||||
static function unlink ( $path )
|
||||
static function unlink ( $url )
|
||||
{
|
||||
if (self::LOG_LEVEL > 1) error_log(__METHOD__."($path)");
|
||||
if (self::LOG_LEVEL > 1) error_log(__METHOD__."($url)");
|
||||
|
||||
$path = parse_url($url,PHP_URL_PATH);
|
||||
|
||||
if (!is_object(self::$old_vfs))
|
||||
{
|
||||
self::$old_vfs =& new vfs_home();
|
||||
@ -431,12 +453,16 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
);
|
||||
if (!self::$old_vfs->acl_check($data+array(
|
||||
'operation' => EGW_ACL_DELETE
|
||||
)) /*|| ($type = self::$old_vfs->file_type($data)) === 'Directory'*/)
|
||||
'operation' => EGW_ACL_DELETE,
|
||||
'must_exist' => true,
|
||||
)) || ($type = self::$old_vfs->file_type($data)) === self::DIR_MIME_TYPE)
|
||||
{
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."($path) (type=$type) permission denied!");
|
||||
self::remove_password($url);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."($url) (type=$type) permission denied!");
|
||||
return false; // no permission or file does not exist
|
||||
}
|
||||
unset(self::$stat_cache[$path]);
|
||||
|
||||
return self::$old_vfs->rm($data);
|
||||
}
|
||||
|
||||
@ -445,15 +471,67 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
*
|
||||
* It should attempt to rename the item specified by path_from to the specification given by path_to.
|
||||
* In order for the appropriate error message to be returned, do not define this method if your wrapper does not support renaming.
|
||||
*
|
||||
* The regular filesystem stream-wrapper returns an error, if $url_from and $url_to are not either both files or both dirs!
|
||||
*
|
||||
* @param string $path_from
|
||||
* @param string $path_to
|
||||
* @param string $url_from
|
||||
* @param string $url_to
|
||||
* @return boolean TRUE on success or FALSE on failure
|
||||
*/
|
||||
function rename ( $path_from, $path_to )
|
||||
static function rename ( $url_from, $url_to )
|
||||
{
|
||||
error_log(__METHOD__."($path_from, $path_to) not yet implemented!");
|
||||
if (self::LOG_LEVEL > 1) error_log(__METHOD__."($url_from,$url_to)");
|
||||
|
||||
$path_from = parse_url($url_from,PHP_URL_PATH);
|
||||
$path_to = parse_url($url_to,PHP_URL_PATH);
|
||||
|
||||
if (!is_object(self::$old_vfs))
|
||||
{
|
||||
self::$old_vfs =& new vfs_home();
|
||||
}
|
||||
$data_from = array(
|
||||
'string' => $path_from,
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
);
|
||||
if (!self::$old_vfs->acl_check($data_from+array(
|
||||
'operation' => EGW_ACL_DELETE,
|
||||
'must_exist'=> true,
|
||||
)))
|
||||
{
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."($url_from,$url_to): $path_from permission denied!");
|
||||
return false; // no permission or file does not exist
|
||||
}
|
||||
$data_to = array(
|
||||
'string' => $path_to,
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
);
|
||||
if (!self::$old_vfs->acl_check($data_to+array(
|
||||
'operation' => EGW_ACL_ADD,
|
||||
)))
|
||||
{
|
||||
self::remove_password($url_from);
|
||||
self::remove_password($url_to);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."($url_from,$url_to): $path_to permission denied!");
|
||||
return false; // no permission or file does not exist
|
||||
}
|
||||
// the filesystem stream-wrapper does NOT allow to rename files to directories, as this makes problems
|
||||
// for our vfs too, we give abort here with an error, like the filesystem one does
|
||||
if (($type_to = self::$old_vfs->file_type($data_to)) &&
|
||||
($type_to === self::DIR_MIME_TYPE) !== (self::$old_vfs->file_type($data_from) === self::DIR_MIME_TYPE))
|
||||
{
|
||||
$is_dir = $type_to === self::DIR_MIME_TYPE ? 'a' : 'no';
|
||||
self::remove_password($url_from);
|
||||
self::remove_password($url_to);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."($url_to,$url_from) $path_to is $is_dir directory!");
|
||||
return false; // no permission or file does not exist
|
||||
}
|
||||
unset(self::$stat_cache[$path_from]);
|
||||
|
||||
return self::$old_vfs->mv(array(
|
||||
'from' => $path_from,
|
||||
'to' => $path_to,
|
||||
'relatives' => array(RELATIVE_ROOT,RELATIVE_ROOT),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -462,15 +540,51 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
* It should attempt to create the directory specified by path.
|
||||
* In order for the appropriate error message to be returned, do not define this method if your wrapper does not support creating directories.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $url
|
||||
* @param int $mode
|
||||
* @param int $options Posible values include STREAM_REPORT_ERRORS and STREAM_MKDIR_RECURSIVE
|
||||
* @return boolean TRUE on success or FALSE on failure
|
||||
*/
|
||||
function mkdir ( $path, $mode, $options )
|
||||
static function mkdir ( $url, $mode, $options )
|
||||
{
|
||||
error_log(__METHOD__."($path, $mode, $options) not yet implemented!");
|
||||
if (self::LOG_LEVEL > 1) error_log(__METHOD__."($url,$mode,$options)");
|
||||
|
||||
$path = parse_url($url,PHP_URL_PATH);
|
||||
|
||||
if (!is_object(self::$old_vfs))
|
||||
{
|
||||
self::$old_vfs =& new vfs_home();
|
||||
}
|
||||
// check if we should also create all non-existing path components and our parent does not exist,
|
||||
// if yes call ourself recursive with the parent directory
|
||||
if (($options & STREAM_MKDIR_RECURSIVE) && $path != '/' && !self::$old_vfs->file_exists(array(
|
||||
'string' => dirname($path),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
)))
|
||||
{
|
||||
if (!self::mkdir(dirname($path),$mode,$options))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$data=array(
|
||||
'string' => $path,
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
);
|
||||
if (!self::$old_vfs->acl_check($data+array(
|
||||
'operation' => EGW_ACL_ADD,
|
||||
'must_exist' => false,
|
||||
)))
|
||||
{
|
||||
self::remove_password($url);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."($url) permission denied!");
|
||||
if (!($options & STREAM_URL_STAT_QUIET))
|
||||
{
|
||||
trigger_error(__METHOD__."('$url',$mode,$options) permission denied!",E_USER_WARNING);
|
||||
}
|
||||
return false; // no permission or file does not exist
|
||||
}
|
||||
return self::$old_vfs->mkdir($data);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -479,16 +593,80 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
* It should attempt to remove the directory specified by path.
|
||||
* In order for the appropriate error message to be returned, do not define this method if your wrapper does not support removing directories.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $url
|
||||
* @param int $options Possible values include STREAM_REPORT_ERRORS.
|
||||
* @return boolean TRUE on success or FALSE on failure.
|
||||
*/
|
||||
function rmdir ( $path, $options )
|
||||
static function rmdir ( $url, $options )
|
||||
{
|
||||
error_log(__METHOD__."($path, $options) not yet implemented!");
|
||||
if (self::LOG_LEVEL > 1) error_log(__METHOD__."($url)");
|
||||
|
||||
$path = parse_url($url,PHP_URL_PATH);
|
||||
|
||||
if (!is_object(self::$old_vfs))
|
||||
{
|
||||
self::$old_vfs =& new vfs_home();
|
||||
}
|
||||
$data=array(
|
||||
'string' => $path,
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
);
|
||||
if (!self::$old_vfs->acl_check($data+array(
|
||||
'operation' => EGW_ACL_DELETE,
|
||||
'must_exist' => true,
|
||||
)) || ($type = self::$old_vfs->file_type($data)) !== self::DIR_MIME_TYPE)
|
||||
{
|
||||
self::remove_password($url);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."($url,$options) (type=$type) permission denied!");
|
||||
if (!($options & STREAM_URL_STAT_QUIET))
|
||||
{
|
||||
trigger_error(__METHOD__."('$url',$options) (type=$type) permission denied!",E_USER_WARNING);
|
||||
}
|
||||
return false; // no permission or file does not exist
|
||||
}
|
||||
// abort with an error, if the dir is not empty
|
||||
// our vfs deletes recursive, while the stream-wrapper interface does not!
|
||||
if (($files = self::$old_vfs->ls($data)))
|
||||
{
|
||||
self::remove_password($url);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."($url,$options) dir is not empty!");
|
||||
if (!($options & STREAM_URL_STAT_QUIET))
|
||||
{
|
||||
trigger_error(__METHOD__."('$url',$options) dir is not empty!",E_USER_WARNING);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
unset(self::$stat_cache[$path]);
|
||||
|
||||
return self::$old_vfs->rm($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is not (yet) a stream-wrapper function, but it's necessary and can be used static
|
||||
*
|
||||
* @param string $url
|
||||
* @param int $time=null modification time (unix timestamp), default null = current time
|
||||
* @param int $atime=null access time (unix timestamp), default null = current time, not implemented in the vfs!
|
||||
*/
|
||||
static function touch($url,$time=null,$atime=null)
|
||||
{
|
||||
if (self::LOG_LEVEL > 1) error_log(__METHOD__."($url)");
|
||||
|
||||
$path = parse_url($url,PHP_URL_PATH);
|
||||
|
||||
if (!is_object(self::$old_vfs))
|
||||
{
|
||||
self::$old_vfs =& new vfs_home();
|
||||
}
|
||||
$data=array(
|
||||
'string' => $path,
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
);
|
||||
if (!is_null($time)) $data['time'] = $time;
|
||||
|
||||
return self::$old_vfs->touch($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called immediately when your stream object is created for examining directory contents with opendir().
|
||||
*
|
||||
@ -499,6 +677,8 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
function dir_opendir ( $url, $options )
|
||||
{
|
||||
if (self::LOG_LEVEL > 1) error_log(__METHOD__."('$url',$options)");
|
||||
|
||||
$this->opened_dir = null;
|
||||
|
||||
if (!is_object(self::$old_vfs))
|
||||
{
|
||||
@ -506,22 +686,30 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
}
|
||||
$path = parse_url($url,PHP_URL_PATH);
|
||||
|
||||
$this->opened_dir = self::$old_vfs->ls(array(
|
||||
$files = self::$old_vfs->ls(array(
|
||||
'string' => $path,
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
'checksubdirs' => false,
|
||||
'nofiles' => false,
|
||||
//'orderby' => '',
|
||||
'orderby' => 'name',
|
||||
//'mime_type' => '',
|
||||
));
|
||||
if (!is_array($this->opened_dir) ||
|
||||
if (!is_array($files) ||
|
||||
// we also need to return false, if $url is not a directory!
|
||||
count($this->opened_dir) == 1 && $path == $this->opened_dir[0]['directory'].'/'.$this->opened_dir[0]['name'] &&
|
||||
$this->opened_dir[0]['mime_type'] != 'Directory')
|
||||
count($files) == 1 && $path == $files[0]['directory'].'/'.$files[0]['name'] &&
|
||||
$files[0]['mime_type'] != self::DIR_MIME_TYPE)
|
||||
{
|
||||
self::remove_password($url);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."('$url',$options) $url is not directory!");
|
||||
$this->opened_dir = null;
|
||||
return false;
|
||||
}
|
||||
self::$stat_cache = $this->opened_dir = array();
|
||||
foreach($files as $file)
|
||||
{
|
||||
$this->opened_dir[] = $file['name'];
|
||||
self::$stat_cache[$file['directory'].'/'.$file['name']] = $file;
|
||||
}
|
||||
//print_r($this->opened_dir);
|
||||
reset($this->opened_dir);
|
||||
|
||||
@ -551,39 +739,42 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
* This flag is set in response to calls to lstat(), is_link(), or filetype().
|
||||
* - STREAM_URL_STAT_QUIET If this flag is set, your wrapper should not raise any errors. If this flag is not set,
|
||||
* you are responsible for reporting errors using the trigger_error() function during stating of the path.
|
||||
* stat triggers it's own warning anyway, so it makes no sense to trigger one by our stream-wrapper!
|
||||
* @return array
|
||||
*/
|
||||
function url_stat ( $url, $flags )
|
||||
static function url_stat ( $url, $flags )
|
||||
{
|
||||
if (self::LOG_LEVEL > 1) error_log(__METHOD__."('$url',$flags)");
|
||||
|
||||
/*return array(
|
||||
'mode' => 0100666,
|
||||
'name' => basename(parse_url($path,PHP_URL_PATH)),
|
||||
'size' => strlen(basename(parse_url($path,PHP_URL_PATH))),
|
||||
'nlink' => 1,
|
||||
'uid' => 1000,
|
||||
'gid' => 100,
|
||||
'mtime' => time(),
|
||||
);*/
|
||||
|
||||
$path = parse_url($url,PHP_URL_PATH);
|
||||
|
||||
// check if we already have the info from the last dir_open call, as the old vfs reads it anyway from the db
|
||||
if (self::$stat_cache && isset(self::$stat_cache[$path]))
|
||||
{
|
||||
return self::_vfsinfo2stat(self::$stat_cache[$path]);
|
||||
}
|
||||
|
||||
if (!is_object(self::$old_vfs))
|
||||
{
|
||||
self::$old_vfs =& new vfs_home();
|
||||
}
|
||||
$path = parse_url($url,PHP_URL_PATH);
|
||||
|
||||
list($info) = self::$old_vfs->ls(array(
|
||||
'string' => $path,
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
'checksubdirs' => false,
|
||||
'nofiles' => true,
|
||||
//'orderby' => '',
|
||||
//'orderby' => 'name',
|
||||
//'mime_type' => '',
|
||||
));
|
||||
//print_r($info);
|
||||
if (!$info)
|
||||
{
|
||||
self::remove_password($url);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."('$url',$flags) file or directory not found!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return $info ? $this->vfsinfo2stat($info) : false;
|
||||
return self::_vfsinfo2stat($info);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -595,13 +786,13 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
*/
|
||||
function dir_readdir ( )
|
||||
{
|
||||
if (self::LOG_LEVEL > 1) error_log(__METHOD__."($this->opened_dir_path)");
|
||||
if (self::LOG_LEVEL > 1) error_log(__METHOD__."( )");
|
||||
|
||||
if (!is_array($this->opened_dir)) return false;
|
||||
|
||||
$file = current($this->opened_dir); next($this->opened_dir);
|
||||
|
||||
return $file ? $file['name'] : false;
|
||||
return $file ? $file : false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -614,7 +805,7 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
*/
|
||||
function dir_rewinddir ( )
|
||||
{
|
||||
if (self::LOG_LEVEL > 1) error_log(__METHOD__."($this->opened_dir_path)");
|
||||
if (self::LOG_LEVEL > 1) error_log(__METHOD__."( )");
|
||||
|
||||
if (!is_array($this->opened_dir)) return false;
|
||||
|
||||
@ -632,11 +823,11 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
*/
|
||||
function dir_closedir ( )
|
||||
{
|
||||
if (self::LOG_LEVEL > 1) error_log(__METHOD__."($this->opened_dir_path)");
|
||||
if (self::LOG_LEVEL > 1) error_log(__METHOD__."( )");
|
||||
|
||||
if (!is_array($this->opened_dir)) return false;
|
||||
|
||||
$this->opened_dir = $this->opened_dir_path = null;
|
||||
$this->opened_dir = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -647,18 +838,20 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
* @param array $info
|
||||
* @return array
|
||||
*/
|
||||
function vfsinfo2stat($info)
|
||||
static private function _vfsinfo2stat($info)
|
||||
{
|
||||
$stat = array(
|
||||
'ino' => $info['file_id'],
|
||||
'name' => $info['name'],
|
||||
'mode' => $info['mime_type'] == 'Directory' ? 040700 : 0100600,
|
||||
'mode' => $info['owner_id'] > 0 ?
|
||||
($info['mime_type'] == self::DIR_MIME_TYPE ? 040700 : 0100600) :
|
||||
($info['mime_type'] == self::DIR_MIME_TYPE ? 040070 : 0100060),
|
||||
'size' => $info['size'],
|
||||
'uid' => $info['owner_id'] > 0 ? $info['owner_id'] : 0,
|
||||
'gid' => $info['owner_id'] < 0 ? $info['owner_id'] : 0,
|
||||
'mtime' => strtotime($info['modified'] ? $info['modified'] : $info['created']),
|
||||
'ctime' => strtotime($info['created']),
|
||||
'nlink' => $info['mime_type'] == 'Directory' ? 2 : 1,
|
||||
'nlink' => $info['mime_type'] == self::DIR_MIME_TYPE ? 2 : 1,
|
||||
);
|
||||
//print_r($stat);
|
||||
return $stat;
|
||||
@ -680,6 +873,22 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
|
||||
return $func_overload & 2 ? mb_substr($str,$start,$length,'ascii') : substr($str,$start,$length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the password of an url with '...' for error messages
|
||||
*
|
||||
* @param string &$url
|
||||
*/
|
||||
static private function remove_password(&$url)
|
||||
{
|
||||
$parts = parse_url($url);
|
||||
|
||||
if ($parts['pass'] || $parts['scheme'])
|
||||
{
|
||||
$url = $parts['scheme'].'://'.($parts['user'] ? $parts['user'].($parts['pass']?':...':'').'@' : '').
|
||||
$parts['host'].$parts['path'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stream_register_wrapper('oldvfs','oldvfs_stream_wrapper');
|
||||
|
Loading…
Reference in New Issue
Block a user