diff --git a/filemanager/ls.php b/filemanager/ls.php
index dae7e1892b..fb7ab4eea9 100755
--- a/filemanager/ls.php
+++ b/filemanager/ls.php
@@ -18,25 +18,6 @@ if (isset($_SERVER['HTTP_HOST'])) // security precaution: forbit calling ls as w
die('
'.basename(__FILE__).' must NOT be called as web-page --> exiting !!!
');
}
-/*
-// 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);
diff --git a/phpgwapi/inc/class.iface_stream_wrapper.inc.php b/phpgwapi/inc/class.iface_stream_wrapper.inc.php
index 5214db5d99..48da3c762a 100644
--- a/phpgwapi/inc/class.iface_stream_wrapper.inc.php
+++ b/phpgwapi/inc/class.iface_stream_wrapper.inc.php
@@ -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().
diff --git a/phpgwapi/inc/class.oldvfs_stream_wrapper.inc.php b/phpgwapi/inc/class.oldvfs_stream_wrapper.inc.php
index 7f344af441..1adb2f3ae8 100644
--- a/phpgwapi/inc/class.oldvfs_stream_wrapper.inc.php
+++ b/phpgwapi/inc/class.oldvfs_stream_wrapper.inc.php
@@ -7,7 +7,7 @@
* @package api
* @subpackage vfs
* @author Ralf Becker
- * @copyright (c) 2007 by Ralf Becker
+ * @copyright (c) 2007-8 by Ralf Becker
* @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');