- added WebDAV ACL props supported-privilege-set and current-user-privilege-set

+ currently only standard WebDAV privileges: read, read-current-user-privilege-set, write-content, bind and unbind used
  + they get only queried for collections, thought we dont report any write* on collections, as we dont allow to create calendars or change properties
- new groupdav::add_resource() method used to add all resources (incl. collections) to propfind or report requests
- improved autoindex to show nicely indented hierarchical properties
This commit is contained in:
Ralf Becker 2011-09-21 20:08:21 +00:00
parent 4ddfc607bc
commit 1f39e5c562
6 changed files with 404 additions and 187 deletions

View File

@ -76,13 +76,6 @@ class addressbook_groupdav extends groupdav_handler
*/
var $charset = 'utf-8';
/**
* Which attribute to use to contruct name part of url/path
*
* @var string
*/
static $path_attr = 'id';
/**
* Constructor
*
@ -99,7 +92,7 @@ class addressbook_groupdav extends groupdav_handler
if ($this->bo->account_repository != 'ldap' &&
version_compare($GLOBALS['egw_info']['apps']['phpgwapi']['version'], '1.9.007', '>='))
{
self::$path_attr = 'carddav_name';
groupdav_handler::$path_attr = 'carddav_name';
groupdav_handler::$path_extension = '';
}
else
@ -108,17 +101,6 @@ class addressbook_groupdav extends groupdav_handler
}
}
/**
* Create the path for a contact
*
* @param array $contact
* @return string
*/
static function get_path($contact)
{
return $contact[self::$path_attr].groupdav_handler::$path_extension;
}
/**
* Handle propfind in the addressbook folder
*
@ -188,25 +170,15 @@ class addressbook_groupdav extends groupdav_handler
foreach($contacts as &$contact)
{
$props = array(
HTTP_WebDAV_Server::mkprop('getetag',$this->get_etag($contact)),
HTTP_WebDAV_Server::mkprop('getcontenttype', 'text/vcard'),
// getlastmodified and getcontentlength are required by WebDAV and Cadaver eg. reports 404 Not found if not set
HTTP_WebDAV_Server::mkprop('getlastmodified', $contact['modified']),
'getcontenttype' => HTTP_WebDAV_Server::mkprop('getcontenttype', 'text/vcard'),
);
if ($address_data)
{
$content = $handler->getVCard($contact['id'],$this->charset,false);
$props[] = HTTP_WebDAV_Server::mkprop('getcontentlength',bytes($content));
$props['getcontentlength'] = bytes($content);
$props[] = HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'address-data',$content,true);
}
else
{
$props[] = HTTP_WebDAV_Server::mkprop('getcontentlength', ''); // expensive to calculate and no CalDAV client uses it
}
$files[] = array(
'path' => $path.self::get_path($contact),
'props' => $props,
);
$files[] = $this->add_resource($path, $contact, $props);
}
}
if ($this->debug) error_log(__METHOD__."($path,".array2string($filter).','.array2string($start).") took ".(microtime(true) - $starttime).' to return '.count($files).' items');
@ -512,7 +484,6 @@ class addressbook_groupdav extends groupdav_handler
HTTP_WebDAV_Server::mkprop('report',array(
HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'addressbook-multiget',''))))),
));
//$props = self::current_user_privilege_set($props);
return $props;
}

View File

@ -220,28 +220,17 @@ class calendar_groupdav extends groupdav_handler
$event['max_user_modified'] = $max_user_modified[$event['id']];
//header('X-EGROUPWARE-EVENT-'.$event['id'].': '.$event['title'].': '.date('Y-m-d H:i:s',$event['start']).' - '.date('Y-m-d H:i:s',$event['end']));
$props = array(
HTTP_WebDAV_Server::mkprop('getetag',$this->get_etag($event)),
HTTP_WebDAV_Server::mkprop('getcontenttype', $this->agent != 'kde' ?
'text/calendar; charset=utf-8; component=VEVENT' : 'text/calendar'),
// getlastmodified and getcontentlength are required by WebDAV and Cadaver eg. reports 404 Not found if not set
HTTP_WebDAV_Server::mkprop('getlastmodified', $event['modified']),
HTTP_WebDAV_Server::mkprop('resourcetype',''), // DAVKit requires that attribute!
'getcontenttype' => HTTP_WebDAV_Server::mkprop('getcontenttype', $this->agent != 'kde' ?
'text/calendar; charset=utf-8; component=VEVENT' : 'text/calendar'),
);
//error_log(__FILE__ . __METHOD__ . "Calendar Data : $calendar_data");
if ($calendar_data)
{
$content = $this->iCal($event,$filter['users']);
$props[] = HTTP_WebDAV_Server::mkprop('getcontentlength',bytes($content));
$props['getcontentlength'] = bytes($content);
$props[] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-data',$content);
}
else
{
$props[] = HTTP_WebDAV_Server::mkprop('getcontentlength', ''); // expensive to calculate and no CalDAV client uses it
}
$files[] = array(
'path' => $path.$this->get_path($event),
'props' => $props,
);
$files[] = $this->add_resource($path, $event, $props);
}
}
if ($this->debug)
@ -921,4 +910,3 @@ class calendar_groupdav extends groupdav_handler
return $handler;
}
}

View File

@ -78,7 +78,7 @@ class infolog_groupdav extends groupdav_handler
* @param array|int $info
* @return string
*/
static function get_path($info)
function get_path($info)
{
if (is_numeric($info) && self::$path_attr == 'info_id')
{
@ -208,27 +208,16 @@ class infolog_groupdav extends groupdav_handler
foreach($tasks as $task)
{
$props = array(
HTTP_WebDAV_Server::mkprop('getetag',$this->get_etag($task)),
HTTP_WebDAV_Server::mkprop('getcontenttype',$this->agent != 'kde' ?
'text/calendar; charset=utf-8; component=VTODO' : 'text/calendar'), // Konqueror (3.5) dont understand it otherwise
// getlastmodified and getcontentlength are required by WebDAV and Cadaver eg. reports 404 Not found if not set
HTTP_WebDAV_Server::mkprop('getlastmodified', $task['info_datemodified']),
HTTP_WebDAV_Server::mkprop('resourcetype',''), // DAVKit requires that attribute!
'getcontenttype' => $this->agent != 'kde' ? 'text/calendar; charset=utf-8; component=VTODO' : 'text/calendar', // Konqueror (3.5) dont understand it otherwise
'getlastmodified' => $task['info_datemodified'],
);
if ($calendar_data)
{
$content = $handler->exportVTODO($task,'2.0','PUBLISH');
$props[] = HTTP_WebDAV_Server::mkprop('getcontentlength',bytes($content));
$props['getcontentlength'] = bytes($content);
$props[] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-data',$content);
}
else
{
$props[] = HTTP_WebDAV_Server::mkprop('getcontentlength', ''); // expensive to calculate and no CalDAV client uses it
}
$files[] = array(
'path' => $path.self::get_path($task),
'props' => $props,
);
$files[] = $this->add_resource($path, $task, $props);
}
}
if ($this->debug) error_log(__METHOD__."($path) took ".(microtime(true) - $starttime).' to return '.count($files).' items');

View File

@ -78,15 +78,30 @@ class groupdav extends HTTP_WebDAV_Server
var $dav_powered_by = self::REALM;
var $http_auth_realm = self::REALM;
/**
* Folders in root or user home
*
* @var array
*/
var $root = array(
'calendar' => array(
'resourcetype' => array(self::GROUPDAV => 'vevent-collection', self::CALDAV => 'calendar'),
'component-set' => array(self::GROUPDAV => 'VEVENT'),
),
'addressbook' => array(
'resourcetype' => array(self::GROUPDAV => 'vcard-collection', self::CARDDAV => 'addressbook'),
'component-set' => array(self::GROUPDAV => 'VCARD'),
),
'calendar' => array(
'resourcetype' => array(self::GROUPDAV => 'vevent-collection', self::CALDAV => 'calendar'),
'component-set' => array(self::GROUPDAV => 'VEVENT'),
),
/*'inbox' => array(
'resourcetype' => array(self::CALDAV => 'schedule-inbox'),
'app' => 'calendar',
'no-root' => true,
),
'outbox' => array(
'resourcetype' => array(self::CALDAV => 'schedule-outbox'),
'app' => 'calendar',
'no-root' => true,
),*/
'infolog' => array(
'resourcetype' => array(self::GROUPDAV => 'vtodo-collection', self::CALDAV => 'calendar'),
'component-set' => array(self::GROUPDAV => 'VTODO'),
@ -127,6 +142,36 @@ class groupdav extends HTTP_WebDAV_Server
* @var accounts
*/
var $accounts;
/**
* Supported privileges with name and description
*
* privileges are hierarchical
*
* @var array
*/
var $supported_privileges = array(
'all' => array(
'*description*' => 'all privileges',
'read' => 'read resource',
'write' => array(
'*description*' => 'write resource',
'write-properties' => 'write resource properties',
'write-content' => 'write resource content',
'bind' => 'add child resource',
'unbind' => 'remove child resource',
),
'unlock' => 'unlock resource without ownership of lock',
'read-acl' => 'read resource access control list',
'write-acl' => 'write resource access control list',
'read-current-user-privilege-set' => 'read privileges for current principal',
),
);
/**
* $options parameter to PROPFIND request, eg. to check what props are requested
*
* @var array
*/
var $propfind_options;
function __construct()
{
@ -199,6 +244,8 @@ class groupdav extends HTTP_WebDAV_Server
*/
function app_handler($app)
{
if (isset($this->root[$app]['app'])) $app = $this->root[$app]['app'];
return groupdav_handler::app_handler($app,$this);
}
@ -218,9 +265,9 @@ class groupdav extends HTTP_WebDAV_Server
if (!in_array(2,$dav)) $dav[] = 2;
$dav[] = 'access-control';
$dav[] = 'calendar-access';
//$dav[] = 'calendar-schedule';
//$dav[] = 'calendar-auto-schedule';
$dav[] = 'calendar-proxy';
//$dav[] = 'calendar-avialibility';
//$dav[] = 'calendar-availibility';
//$dav[] = 'calendarserver-private-events';
break;
case 'addressbook':
@ -238,53 +285,6 @@ class groupdav extends HTTP_WebDAV_Server
// not yet implemented: $dav[] = 'access-control';
}
/**
* Add a collection to a PROPFIND request
*
* @param string $path
* @param array $props=array() extra properties 'resourcetype' is added anyway, name => value pairs or name => HTTP_WebDAV_Server([namespace,]name,value)
* @return array with values for keys 'path' and 'props'
*/
public function add_collection($path, array $props = array())
{
// resourcetype: collection
$props['resourcetype'][] = self::mkprop('collection','');
// props for all collections: current-user-principal and principal-collection-set
$props['current-user-principal'] = array(
self::mkprop('href',$this->current_user_principal));
$props['principal-collection-set'] = array(
self::mkprop('href',$this->base_uri.'/principals/'));
// required props per WebDAV standard
foreach(array(
'displayname' => basename($path),
'getetag' => 'EGw-no-etag-wGE',
'getcontentlength' => '',
'getlastmodified' => '',
'getcontenttype' => 'httpd/unix-directory',
) as $name => $default)
{
if (!isset($props[$name])) $props[$name] = $default;
}
if ($this->debug > 1) error_log(__METHOD__."(path='$path', props=".array2string($props).')');
// convert simple associative properties to HTTP_WebDAV_Server ones
foreach($props as $name => &$prop)
{
if (!is_array($prop) || !isset($prop['name']))
{
$prop = self::mkprop($name, $prop);
}
}
return array(
'path' => $path,
'props' => $props,
);
}
/**
* PROPFIND and REPORT method handler
*
@ -296,6 +296,9 @@ class groupdav extends HTTP_WebDAV_Server
{
if ($this->debug) error_log(__CLASS__."::$method(".array2string($options,true).')');
// make options (readonly) available to all class methods, eg. prop_requested
$this->propfind_options = $options;
// parse path in form [/account_lid]/app[/more]
if (!self::_parse_path($options['path'],$id,$app,$user,$user_prefix) && $app && !$user)
{
@ -327,7 +330,7 @@ class groupdav extends HTTP_WebDAV_Server
}
return true;
}
if ($app != 'principals' && !isset($GLOBALS['egw_info']['user']['apps'][$app]))
if ($app != 'principals' && !isset($GLOBALS['egw_info']['user']['apps'][$this->root[$app]['app'] ? $this->root[$app]['app'] : $app]))
{
if ($this->debug) error_log(__CLASS__."::$method(path=$options[path]) 403 Forbidden: no app rights for '$app'");
return "403 Forbidden: no app rights for '$app'"; // no rights for the given app
@ -336,16 +339,9 @@ class groupdav extends HTTP_WebDAV_Server
{
if ($method != 'REPORT' && !$id) // no self URL for REPORT requests (only PROPFIND) or propfinds on an id
{
$files['files'][0] = $this->add_collection($path.$app.'/',
// KAddressbook doubles the folder, if the self URL contains the GroupDAV/CalDAV resourcetypes
$this->_properties($app,$app=='addressbook'&&$handler->get_agent()=='kde',$user,$path));
// KAddressbook doubles the folder, if the self URL contains the GroupDAV/CalDAV resourcetypes
$files['files'][0] = $this->add_app($app,$app=='addressbook'&&$handler->get_agent()=='kde',$user,$path);
// add ctag if handler implements it (only for depth 0)
if (method_exists($handler,'getctag'))
{
$files['files'][0]['props']['getctag'] = self::mkprop(
groupdav::CALENDARSERVER,'getctag',$handler->getctag($options['path'],$user));
}
if (!$options['depth']) return true; // depth 0 --> show only the self url
}
return $handler->propfind($this->_slashify($options['path']),$options,$files,$user,$id);
@ -353,6 +349,143 @@ class groupdav extends HTTP_WebDAV_Server
return '501 Not Implemented';
}
/**
* Add a collection to a PROPFIND request
*
* @param string $path
* @param array $props=array() extra properties 'resourcetype' is added anyway, name => value pairs or name => HTTP_WebDAV_Server([namespace,]name,value)
* @param array $privileges=array('read') values for current-user-privilege-set
* @param array $supported_privileges=null default $this->supported_privileges
* @return array with values for keys 'path' and 'props'
*/
public function add_collection($path, array $props = array(), array $privileges=array('read','read-current-user-privilege-set'), array $supported_privileges=null)
{
// resourcetype: collection
$props['resourcetype'][] = self::mkprop('collection','');
if (!isset($props['getcontenttype'])) $props['getcontenttype'] = 'httpd/unix-directory';
return $this->add_resource($path, $props, $privileges, $supported_privileges);
}
/**
* Add a collection to a PROPFIND request
*
* @param string $path
* @param array $props=array() extra properties 'resourcetype' is added anyway, name => value pairs or name => HTTP_WebDAV_Server([namespace,]name,value)
* @param array $privileges=array('read') values for current-user-privilege-set
* @param array $supported_privileges=null default $this->supported_privileges
* @return array with values for keys 'path' and 'props'
*/
public function add_resource($path, array $props = array(), array $privileges=array('read','read-current-user-privilege-set'), array $supported_privileges=null)
{
// props for all collections: current-user-principal and principal-collection-set
$props['current-user-principal'] = array(
self::mkprop('href',$this->current_user_principal));
$props['principal-collection-set'] = array(
self::mkprop('href',$this->base_uri.'/principals/'));
// required props per WebDAV standard
foreach(array(
'displayname' => basename($path),
'getetag' => 'EGw-no-etag-wGE',
'getcontentlength' => '',
'getlastmodified' => '',
'getcontenttype' => '',
'resourcetype' => '',
) as $name => $default)
{
if (!isset($props[$name])) $props[$name] = $default;
}
// if requested add privileges
if (is_null($supported_privileges)) $supported_privileges = $this->supported_privileges;
if ($this->prop_requested('current-user-privilege-set') === true)
{
foreach($privileges as $name)
{
$props['current-user-privilege-set'][] = self::mkprop('privilege', array(
is_array($name) ? self::mkprop($name['ns'], $name['name'], '') : self::mkprop($name, '')));
}
}
if ($this->prop_requested('supported-privilege-set') === true)
{
foreach($supported_privileges as $name => $data)
{
$props['supported-privilege-set'][] = $this->supported_privilege($name, $data);
}
}
if (!isset($props['owner']) && $this->prop_requested('owner') === true)
{
$props['owner'] = '';
}
if ($this->debug > 1) error_log(__METHOD__."(path='$path', props=".array2string($props).')');
// convert simple associative properties to HTTP_WebDAV_Server ones
foreach($props as $name => &$prop)
{
if (!is_array($prop) || !isset($prop['name']))
{
$prop = self::mkprop($name, $prop);
}
}
return array(
'path' => $path,
'props' => $props,
);
}
/**
* Generate (hierachical) supported-privilege property
*
* @param string $name name of privilege
* @param string|array $data string with describtion or array with agregated privileges plus value for key '*description*'
* @return array of self::mkprop() arrays
*/
protected function supported_privilege($name, $data)
{
$props = array();
$props[] = self::mkprop('privilege', array(self::mkprop($name, '')));
$props[] = self::mkprop('description', is_array($data) ? $data['*description*'] : $data);
if (is_array($data))
{
unset($data['*description*']);
foreach($data as $name => $data)
{
$props[] = $this->supported_privilege($name, $data);
}
}
return self::mkprop('supported-privilege', $props);
}
/**
* Checks if a given property was requested in propfind request
*
* @param string $name property name
* @param string $ns=null namespace, if that is to be checked too
* @return boolean|string true: $name explicitly requested (or autoindex), 'allprop' requested, false: $name was not requested
*/
function prop_requested($name, $ns=null)
{
if (!is_array($this->propfind_options) || !isset($this->propfind_options['props']))
{
return true; // no props set, should happen only in autoindex, we return true to show all available props
}
$ret = false;
foreach($this->propfind_options['props'] as $prop)
{
if ($prop['name'] == $name && (is_null($ns) || $prop['ns'] == $ns))
{
$ret = true;
break;
}
if ($prop['name'] == 'allprop') $ret = 'allprop';
}
return $ret;
}
/**
* Add user home with addressbook, calendar, infolog
*
@ -399,7 +532,7 @@ class groupdav extends HTTP_WebDAV_Server
// self url
$files['files'][] = $this->add_collection($path, array(
'displayname' => $displayname,
'owner' => array(self::mkprop('href',$this->base_uri.'/principals/'.$principalType.'/'.$account_lid.'/')),
'owner' => $path == '/' ? '' : array(self::mkprop('href',$this->base_uri.'/principals/'.$principalType.'/'.$account_lid.'/')),
'calendar-user-address-set' => self::mkprop(groupdav::CALDAV,'calendar-user-address-set',$calendar_user_address_set),
'email-address-set' => self::mkprop(groupdav::CALENDARSERVER,'email-address-set',array(
self::mkprop(groupdav::CALENDARSERVER,'email-address',$GLOBALS['egw_info']['user']['email']))),
@ -412,31 +545,25 @@ class groupdav extends HTTP_WebDAV_Server
{
foreach($this->root as $app => $data)
{
if (!$GLOBALS['egw_info']['user']['apps'][$app]) continue; // no rights for the given app
$props = $this->_properties($app,false,$user,$path);
// add ctag if handler implements it
if (($handler = self::app_handler($app)) && method_exists($handler,'getctag'))
{
$props['getctag'] = self::mkprop(
groupdav::CALENDARSERVER,'getctag',$handler->getctag($path,$user));
}
$props['getetag'] = 'EGw-'.$app.'-wGE';
$files['files'][] = $this->add_collection($path.$app.'/',$props);
if (!$GLOBALS['egw_info']['user']['apps'][$data['app'] ? $data['app'] : $app]) continue; // no rights for the given app
if ($path == '/' && !empty($data['no-root'])) continue;
$files['files'][] = $this->add_app($app,false,$user,$path);
}
}
return true;
}
/**
* Get properties of an application collection
* Add an application collection to a user home or the root
*
* @param string $app
* @param boolean $no_extra_types=false should the GroupDAV and CalDAV types be added (KAddressbook has problems with it in self URL)
* @param int $user=null owner of the collection, default current user
* @param string $path='/'
* @return array of DAV properties
* @return array with values for keys 'path' and 'props'
*/
function _properties($app,$no_extra_types=false,$user=null,$path='/')
protected function add_app($app,$no_extra_types=false,$user=null,$path='/')
{
if ($this->debug) error_log(__METHOD__."(app='$app', no_extra_types=$no_extra_types, user='$user', path='$path')");
$user_preferences = $GLOBALS['egw_info']['user']['preferences'];
@ -497,6 +624,12 @@ class groupdav extends HTTP_WebDAV_Server
break;
case 'infolog':
break;
case 'inbox':
$displayname = lang('Scheduling inbox').' '.common::grab_owner_name($user);
break;
case 'outbox':
$displayname = lang('Scheduling outbox').' '.common::grab_owner_name($user);
break;
default:
$displayname = translation::convert(lang($app).' '.
common::grab_owner_name($user),$this->egw_charset,'utf-8');
@ -505,27 +638,38 @@ class groupdav extends HTTP_WebDAV_Server
foreach((array)$this->root[$app] as $prop => $values)
{
if ($prop == 'resourcetype')
switch($prop)
{
if (!$no_extra_types)
{
foreach($this->root[$app]['resourcetype'] as $ns => $type)
case 'resourcetype';
if (!$no_extra_types)
{
$props['resourcetype'][] = self::mkprop($ns,$type,'');
foreach($this->root[$app]['resourcetype'] as $ns => $type)
{
$props['resourcetype'][] = self::mkprop($ns,$type,'');
}
// add /addressbook/ as directory gateway
if ($app == 'addressbook' && $path == '/')
{
$props['resourcetype'][] = self::mkprop(self::CARDDAV, 'directory', '');
}
}
// add /addressbook/ as directory gateway
if ($app == 'addressbook' && $path == '/')
break;
case 'app':
case 'no-root':
break; // no props, already handled
default:
if (is_array($values))
{
$props['resourcetype'][] = self::mkprop(self::CARDDAV, 'directory', '');
foreach($values as $ns => $value)
{
$props[$prop] = self::mkprop($ns,$prop,$value);
}
}
}
}
else
{
foreach($values as $ns => $value)
{
$props[$prop] = self::mkprop($ns,$prop,$value);
}
else
{
$props[$prop] = $values;
}
break;
}
}
if (method_exists($app.'_groupdav','extra_properties'))
@ -535,7 +679,20 @@ class groupdav extends HTTP_WebDAV_Server
translation::charset(),'utf-8');
$props = ExecMethod2($app.'_groupdav::extra_properties',$props,$displayname,$this->base_uri);
}
return $props;
// add ctag if handler implements it
if (($handler = self::app_handler($app)))
{
if (method_exists($handler,'getctag') && $this->prop_requested('getctag') === true)
{
$props['getctag'] = self::mkprop(
groupdav::CALENDARSERVER,'getctag',$handler->getctag($path,$user));
}
}
$props['getetag'] = 'EGw-'.$app.'-wGE';
if ($handler) $privileges = $handler->current_user_privileges($user) ;
return $this->add_collection($path.$app.'/', $props, $privileges);
}
/**
@ -608,8 +765,8 @@ class groupdav extends HTTP_WebDAV_Server
header('Content-type: text/html; charset='.translation::charset());
echo "<html>\n<head>\n\t<title>".'EGroupware (Cal|Card|Group)DAV server '.htmlspecialchars($options['path'])."</title>\n";
echo "\t<meta http-equiv='content-type' content='text/html; charset=utf-8' />\n";
echo "\t<style type='text/css'>\n.th { background-color: #e0e0e0; }\n.row_on { background-color: #F1F1F1; }\n".
".row_off { background-color: #ffffff; }\ntd { padding-left: 5px; }\nth { padding-left: 5px; text-align: left; }\n\t</style>\n";
echo "\t<style type='text/css'>\n.th { background-color: #e0e0e0; }\n.row_on { background-color: #F1F1F1; vertical-align: top; }\n".
".row_off { background-color: #ffffff; vertical-align: top; }\ntd { padding-left: 5px; }\nth { padding-left: 5px; text-align: left; }\n\t</style>\n";
echo "</head>\n<body>\n";
echo '<h1>(Cal|Card|Group)DAV ';
@ -652,8 +809,8 @@ class groupdav extends HTTP_WebDAV_Server
echo "\t\t<td>".$props['DAV:getcontentlength']."</td>\n";
echo "\t\t<td>".(!empty($props['DAV:getlastmodified']) ? date('Y-m-d H:i:s',$props['DAV:getlastmodified']) : '')."</td>\n";
echo "\t\t<td>".$props['DAV:getetag']."</td>\n";
echo "\t\t<td>".htmlspecialchars($props['DAV:getcontenttype'])."</td>\n";
echo "\t\t<td>".self::prop_value($props['DAV:resourcetype'])."</td>\n\t</tr>\n";
echo "\t\t<td>".$props['DAV:getcontenttype']."</td>\n";
echo "\t\t<td>".$props['DAV:resourcetype']."</td>\n\t</tr>\n";
}
if (!$n)
{
@ -672,7 +829,7 @@ class groupdav extends HTTP_WebDAV_Server
$name = array_pop($ns);
$ns = implode(':',$ns);
echo "\t<tr class='$class'>\n\t\t<td>".htmlspecialchars($ns)."</td><td style='white-space: nowrap'>".htmlspecialchars($name)."</td>\n";
echo "\t\t<td>".self::prop_value($value)."</td>\n\t</tr>\n";
echo "\t\t<td>".$value."</td>\n\t</tr>\n";
}
echo "</table>\n";
@ -695,15 +852,27 @@ class groupdav extends HTTP_WebDAV_Server
{
$value = $this->_hierarchical_prop_encode($value);
}
$value = htmlspecialchars(array2string($value));
$value = array2string($value);
}
elseif (preg_match('/\<(D:)?href\>[^<]+\<\/(D:)?href\>/i',$value))
if ($value[0] == '<' && function_exists('tidy_repair_string'))
{
$value = preg_replace('/\<(D:)?href\>([^<]+)\<\/(D:)?href\>/i','&lt;\\1href&gt;<a href="\\2">\\2</a>&lt;/\\3href&gt;<br />',$value);
$value = tidy_repair_string($value, array(
'indent' => true,
'show-body-only' => true,
'output-encoding' => 'utf-8',
'input-encoding' => 'utf-8',
'input-xml' => true,
'output-xml' => true,
'wrap' => 0,
));
}
if (preg_match('/\<(D:)?href\>[^<]+\<\/(D:)?href\>/i',$value))
{
$value = '<pre>'.preg_replace('/\<(D:)?href\>([^<]+)\<\/(D:)?href\>/i','&lt;\\1href&gt;<a href="\\2">\\2</a>&lt;/\\3href&gt;',$value).'</pre>';
}
else
{
$value = htmlspecialchars($value);
$value = $value[0] == '<' ? '<pre>'.htmlspecialchars($value).'</pre>' : htmlspecialchars($value);
}
return $value;
}
@ -743,9 +912,13 @@ class groupdav extends HTTP_WebDAV_Server
$prop['val'] = $this->_hierarchical_prop_encode($prop['val'], $prop['ns'], $ns_defs, $ns_hash);
// hack to show real namespaces instead of not (visibly) defined shortcuts
unset($ns_hash['DAV:']);
$prop['val'] = strtr($prop['val'],array_flip($ns_hash));
$value = strtr($this->prop_value($prop['val']),array_flip($ns_hash));
}
$arr[$ns.':'.$prop['name']] = $prop['val'];
else
{
$value = $this->prop_value($prop['val']);
}
$arr[$ns.':'.$prop['name']] = $value;
}
return $arr;
}

View File

@ -37,6 +37,12 @@ abstract class groupdav_handler
* @var accounts
*/
var $accounts;
/**
* Reference to the ACL class
*
* @var acl
*/
var $acl;
/**
* Translates method names into ACL bits
*
@ -85,6 +91,13 @@ abstract class groupdav_handler
*/
static $path_extension = '.ics';
/**
* Which attribute to use to contruct name part of url/path
*
* @var string
*/
static $path_attr = 'id';
/**
* Constructor
*
@ -101,6 +114,9 @@ abstract class groupdav_handler
$this->agent = self::get_agent();
$this->egw_charset = translation::charset();
$this->accounts = $GLOBALS['egw']->accounts;
$this->acl = $GLOBALS['egw']->acl;
}
/**
@ -369,6 +385,90 @@ abstract class groupdav_handler
return $agent;
}
/**
* Return priviledges for current user, default is read and read-current-user-privilege-set
*
* Priviledges are for the collection, not the resources / entries!
*
* @param int $user=null owner of the collection, default current user
* @return array with privileges
*/
public function current_user_privileges($user=null)
{
static $grants;
if (is_null($grants))
{
$grants = $this->acl->get_grants($this->app, $this->app != 'addressbook');
}
$priviledes = array('read-current-user-privilege-set');
if (!$user || $grants[$user] & EGW_ACL_READ)
{
$priviledes[] = 'read';
}
if (!$user || $grants[$user] & EGW_ACL_ADD)
{
$priviledes[] = 'bind'; // PUT for new resources
}
if (!$user || $grants[$user] & EGW_ACL_EDIT)
{
$priviledes[] = 'unbind'; // DELETE
}
// copy/move of existing resources might require write-properties, thought we do not support an explicit PROPATCH
return $priviledes;
}
/**
* Create the path/name for an entry
*
* @param array $entry
* @return string
*/
function get_path($entry)
{
return $entry[self::$path_attr].self::$path_extension;
}
/**
* Add a resource
*
* @param string $path path of collection, NOT entry!
* @param array $entry
* @param array $props
* @return array with values for keys 'path' and 'props'
*/
public function add_resource($path, array $entry, array $props)
{
foreach(array(
'getetag' => $this->get_etag($entry),
'getcontenttype' => 'text/calendar',
'getlastmodified' => $entry['modified'],
'displayname' => $entry['title'],
) as $name => $value)
{
if (!isset($props[$name]))
{
$props[$name] = $value;
}
}
// if requested add privileges
$privileges = array('read', 'read-current-user-privilege-set');
if ($this->groupdav->prop_requested('current-user-privilege-set') === true && !isset($props['current-user-privilege-set']))
{
if ($this->check_access(EGW_ACL_EDIT, $entry))
{
$privileges[] = 'write-content';
}
}
if ($this->groupdav->prop_requested('owner') === true && !isset($props['owner']) &&
($account_lid = $this->accounts->name2id($entry['owner'])))
{
$type = $this->accounts->get_type($entry['owner']) == 'u' ? 'users' : 'groups';
$props['owner'] = HTTP_WebDAV_Server::mkprop('href', $this->base_uri.'/principals/'.$type.'/'.$account_lid.'/');
}
return $this->groupdav->add_resource($path.$this->get_path($entry), $props, $privileges);
}
}
/**

View File

@ -23,20 +23,6 @@
*/
class groupdav_principals extends groupdav_handler
{
/**
* Reference to the accounts class
*
* @var accounts
*/
var $accounts;
/**
* Reference to the ACL class
*
* @var acl
*/
var $acl;
/**
* Constructor
*
@ -46,9 +32,6 @@ class groupdav_principals extends groupdav_handler
function __construct($app, groupdav $groupdav)
{
parent::__construct($app, $groupdav);
$this->accounts = $GLOBALS['egw']->accounts;
$this->acl = $GLOBALS['egw']->acl;
}
/**
@ -673,4 +656,17 @@ class groupdav_principals extends groupdav_handler
($account['account_id'] == $GLOBALS['egw_info']['user']['account_id'] ?
':'.md5(serialize($GLOBALS['egw_info']['user']['preferences']['groupdav'])) : '').'-wGE';
}
/**
* Return priviledges for current user, default is read and read-current-user-privilege-set
*
* Priviledges are for the collection, not the resources / entries!
*
* @param int $user=null owner of the collection, default current user
* @return array with privileges
*/
public function current_user_privileges($user=null)
{
return array('read', 'read-current-user-privilege-set');
}
}