- fixed bug in egw_vfs::check_access for a user different from current one: need to clear the stat-cache after the call too, as the next call might be the regular user again!

- new method egw_vfs::copy_uploaded() to copy a file into vfs and set properties (eg. the comment), while treating the whole operation notification-wise atomar (one notification about an added file).
- using that method for egw_link too
- fixed egw_link not displaying comments
This commit is contained in:
Ralf Becker 2011-06-28 20:43:47 +00:00
parent e6470f6b58
commit bd7407ed88
3 changed files with 87 additions and 36 deletions

View File

@ -961,19 +961,14 @@ class egw_link extends solink
}
if (file_exists($entry_dir) || ($Ok = mkdir($entry_dir,0,true)))
{
// use vfs:// url, to ensure vfs_add|modified hook get called
$fname = egw_vfs::PREFIX.self::vfs_path($app,$id,egw_vfs::encodePathComponent($file['name']),true);
if (($Ok = copy($file['tmp_name'], $fname)) && ($stat = egw_vfs::url_stat($fname, 0)) && $comment)
{
egw_vfs::proppatch(parse_url($fname,PHP_URL_PATH),array(array('name'=>'comment','val'=>$comment))); // set comment
}
//error_log(__METHOD__."('$app', '$id', ".array2string($file).", '$comment') called copy('$file[tmp_name]', '$fname')=".array2string($Ok).', stat='.array2string($stat));
$Ok = egw_vfs::copy_uploaded($file, $p=self::vfs_path($app,$id,'',true), $comment);
error_log(__METHOD__."('$app', '$id', ".array2string($file).", '$comment') called egw_vfs::copy('$file[tmp_name]', '$p')=".array2string($Ok));
}
else
{
error_log(__METHOD__."($app,$id,".array2string($file).",$comment) Can't mkdir $entry_dir!");
}
return $Ok ? -$stat['ino'] : false;
return $Ok ? -$Ok['ino'] : false;
}
/**
@ -1094,9 +1089,9 @@ class egw_link extends solink
foreach($url2stats as $url => &$fileinfo)
{
$link = self::fileinfo2link($fileinfo,$url);
if (isset($props[$path = parse_url($url,PHP_URL_PATH)]))
if ($props && isset($props[$url]))
{
foreach($props[$path] as $prop)
foreach($props[$url] as $prop)
{
if ($prop['ns'] == egw_vfs::DEFAULT_PROP_NAMESPACE && $prop['name'] == 'comment')
{

View File

@ -181,37 +181,19 @@ class egw_vfs extends vfs_stream_wrapper
$ret = false;
$old_props = self::file_exists($to) ? self::propfind($to,null) : array();
// copy properties (eg. file comment), if there are any and evtl. existing old properties
$props = self::propfind($from,null);
if (($from_fp = self::fopen($from,'r')) &&
($to_fp = self::fopen($to,'w')))
foreach($old_props as $prop)
{
$ret = stream_copy_to_stream($from_fp,$to_fp) !== false;
}
if ($from_fp)
{
fclose($from_fp);
}
if ($to_fp)
{
fclose($to_fp);
if ($ret) // successful copyied file
if (!self::find_prop($props,$prop))
{
// copy properties (eg. file comment), if there are any and evtl. existing old properties
$props = self::propfind($from,null);
foreach($old_props as $prop)
{
if (!self::find_prop($props,$prop))
{
$prop['val'] = null; // null = delete prop
$props[] = $prop;
}
}
if ($props) self::proppatch($to, $props);
$prop['val'] = null; // null = delete prop
$props[] = $prop;
}
}
return $ret;
// using self::copy_uploaded() to treat copying incl. properties as atomar operation in respect of notifications
return self::copy_uploaded(self::PREFIX.$from,$to,$props,false); // false = no is_uploaded_file check!
}
/**
@ -781,6 +763,8 @@ class egw_vfs extends vfs_stream_wrapper
self::clearstatcache($path);
$path_user_stat[$path][$user] = self::url_stat($path, 0);
self::clearstatcache($path); // we need to clear the stat-cache after the call too, as the next call might be the regular user again!
}
if (($stat = $path_user_stat[$path][$user]))
{
@ -1705,6 +1689,64 @@ class egw_vfs extends vfs_stream_wrapper
}
}
}
/**
* Copy an uploaded file into the vfs, optionally set some properties (eg. comment or other cf's)
*
* Treat copying incl. properties as atomar operation in respect of notifications (one notification about an added file).
*
* @param array|string $src path to uploaded file or etemplate file array (value for key 'tmp_name')
* @param string $target path or directory to copy uploaded file
* @param array|string $props=null array with properties (name => value pairs, eg. 'comment' => 'FooBar','#cfname' => 'something'),
* array as for proppatch (array of array with values for keys 'name', 'val' and optional 'ns') or string with comment
* @param boolean $check_is_uploaded_file=true should method perform an is_uploaded_file check, default yes
* @return boolean|array stat array on success, false on error
*/
static public function copy_uploaded($src,$target,$props=null,$check_is_uploaded_file=true)
{
$tmp_name = is_array($src) ? $src['tmp_name'] : $src;
if (self::stat($target) && self::is_dir($target))
{
$target = self::concat($target, self::encodePathComponent(is_array($src) ? $src['name'] : basename($tmp_name)));
}
if ($check_is_uploaded_file && !is_uploaded_file($tmp_name) ||
!(self::is_writable($target) || self::is_writable(self::dirname($target))))
{
if (self::LOG_LEVEL) error_log(__METHOD__."($tmp_name, $target, ".array2string($props).") returning false");
return false;
}
if ($props)
{
if (!is_array($props)) $props = array(array('name' => 'comment','val' => $props));
// if $props is name => value pairs, convert it to internal array or array with values for keys 'name', 'val' and optional 'ns'
if (!isset($props[0]))
{
foreach($props as $name => $val)
{
if (($name == 'comment' || $name[0] == '#') && $val) // only copy 'comment' and cfs
{
$vfs_props[] = array(
'name' => $name,
'val' => $val,
);
}
}
$props = $vfs_props;
}
// set props before copying the file, so notifications already contain them
if (!self::stat($target))
{
self::touch($target); // create empty file, to be able to attach properties
self::$treat_as_new = true; // notify as new
}
self::proppatch($target, $props);
}
$ret = copy($tmp_name,self::PREFIX.$target) ? self::stat($target) : false;
if (self::LOG_LEVEL > 1) error_log(__METHOD__."($tmp_name, $target, ".array2string($props).") returning ".array2string($ret));
return $ret;
}
}
egw_vfs::init_static();

View File

@ -255,6 +255,13 @@ class vfs_stream_wrapper implements iface_stream_wrapper
return null;
}
/**
* Can be used from egw_vfs to tell vfs notifications to treat an opened file as a new file
*
* @var boolean
*/
static protected $treat_as_new;
/**
* This method is called immediately after your stream object is created.
*
@ -284,6 +291,13 @@ class vfs_stream_wrapper implements iface_stream_wrapper
$this->opened_stream_url = $url;
$this->opened_stream_is_new = !$stat;
// are we requested to treat the opened file as new file (only for files opened NOT for reading)
if ($mode[0] != 'r' && !$this->opened_stream_is_new && self::$treat_as_new)
{
$this->opened_stream_is_new = true;
//error_log(__METHOD__."($path,$mode,...) stat=$stat, treat_as_new=".self::$treat_as_new." --> ".array2string($this->opened_stream_is_new));
self::$treat_as_new = null;
}
return true;
}