forked from extern/egroupware
- 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:
parent
4ddfc607bc
commit
1f39e5c562
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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');
|
||||
|
@ -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','<\\1href><a href="\\2">\\2</a></\\3href><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','<\\1href><a href="\\2">\\2</a></\\3href>',$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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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');
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user