mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-23 15:18:58 +01:00
- implemented principal-property-search report required for WebDAV ACL and used by Lightning to search for calendar-home-set
- had to implement a workaround for Lightning, as it wrongly interprets principal-property-search for calendar-home-set in the principal-collection-set matching our *DAV root returning all principals, as all have a matching calendar-home-set, as NOT supporting CalDAV scheduling --> search only current user's principal, when Lightning searches for calendar-home-set - OPTIONS / return now calendar-auto-scheduling too, as Lightning only searches there, to check if server supports CalDAV scheduling - fixed outbox freebusy request to cope with no X-CALENDARSERVER-MASK-UID and a single attendee
This commit is contained in:
parent
53c78cd9e2
commit
3f830b2bff
@ -713,7 +713,7 @@ class calendar_groupdav extends groupdav_handler
|
||||
}
|
||||
//print_r($event);
|
||||
$organizer = $component->getAttribute('ORGANIZER');
|
||||
$attendees = $component->getAttribute('ATTENDEE');
|
||||
$attendees = (array)$component->getAttribute('ATTENDEE');
|
||||
// X-CALENDARSERVER-MASK-UID specifies to exclude given event from busy-time
|
||||
$mask_uid = $component->getAttribute('X-CALENDARSERVER-MASK-UID');
|
||||
|
||||
@ -735,11 +735,12 @@ class calendar_groupdav extends groupdav_handler
|
||||
if (is_numeric($uid))
|
||||
{
|
||||
$xml->writeElementNs('C', 'request-status', null, '2.0;Success');
|
||||
$xml->writeElementNs('C', 'calendar-data', null, str_replace("\r", '', // CalDAV rfc example has no encoded "\r"
|
||||
$xml->writeElementNs('C', 'calendar-data', null,
|
||||
$handler->freebusy($uid, $event['end'], true, 'utf-8', $event['start'], 'REPLY', array(
|
||||
'UID' => $event['uid'],
|
||||
'ORGANIZER' => $organizer,
|
||||
'ATTENDEE' => $attendee,
|
||||
)+(empty($mask_uid) || !is_string($mask_uid) ? array() : array(
|
||||
'X-CALENDARSERVER-MASK-UID' => $mask_uid,
|
||||
))));
|
||||
}
|
||||
|
@ -295,13 +295,14 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
$dav[] = 'access-control';
|
||||
$dav[] = 'addressbook'; // CardDAV uses "addressbook" NOT "addressbook-access"
|
||||
break;
|
||||
default:
|
||||
default: // used eg. for root, and needs all above settings, as some clients only use these!
|
||||
if (!in_array(2,$dav)) $dav[] = 2;
|
||||
$dav[] = 'access-control';
|
||||
$dav[] = 'calendar-access';
|
||||
$dav[] = 'calendar-auto-schedule';
|
||||
$dav[] = 'calendar-proxy';
|
||||
$dav[] = 'addressbook';
|
||||
}
|
||||
// not yet implemented: $dav[] = 'access-control';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,6 +43,9 @@ class groupdav_principals extends groupdav_handler
|
||||
'acl-principal-prop-set' => array(
|
||||
// not sure why we return that report, if we not implement it ...
|
||||
),
|
||||
'principal-property-search' => array(
|
||||
'method' => 'principal_property_search_report',
|
||||
),
|
||||
'addressbook-findshared' => array(
|
||||
'ns' => groupdav::ADDRESSBOOKSERVER,
|
||||
'method' => 'addressbook_findshared_report',
|
||||
@ -155,6 +158,135 @@ class groupdav_principals extends groupdav_handler
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle principal-property-search report
|
||||
*
|
||||
* Current implementation runs a full infinity propfind and filters out not matching resources.
|
||||
*
|
||||
* Eg. from Lightning on the principal collection /principals/:
|
||||
* <D:principal-property-search xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
|
||||
* <D:property-search>
|
||||
* <D:prop>
|
||||
* <C:calendar-home-set/>
|
||||
* </D:prop>
|
||||
* <D:match>/egroupware/groupdav.php</D:match>
|
||||
* </D:property-search>
|
||||
* <D:prop>
|
||||
* <C:calendar-home-set/>
|
||||
* <C:calendar-user-address-set/>
|
||||
* <C:schedule-inbox-URL/>
|
||||
* <C:schedule-outbox-URL/>
|
||||
* </D:prop>
|
||||
* </D:principal-property-search>
|
||||
*
|
||||
* Hack for Lightning: it requests calendar-home-set matching our root (/egroupware/groupdav.php),
|
||||
* but interprets returning all principals (all have a matching calendar-home-set) as NOT supporting CalDAV scheduling
|
||||
* --> search only current user's principal, when Lightning searches for calendar-home-set
|
||||
*
|
||||
* @param string $path
|
||||
* @param array $options
|
||||
* @param array &$files
|
||||
* @param int $user account_id
|
||||
* @return mixed boolean true on success, false on failure or string with http status (eg. '404 Not Found')
|
||||
*/
|
||||
function principal_property_search_report($path,&$options,&$files,$user)
|
||||
{
|
||||
//error_log(__METHOD__."('$path', ".array2string($options).",, $user)");
|
||||
|
||||
// parse property-search prop(s) contained in $options['other']
|
||||
foreach($options['other'] as $n => $prop)
|
||||
{
|
||||
switch($prop['name'])
|
||||
{
|
||||
case 'apply-to-principal-collection-set': // optinal prop to apply search on principal-collection-set == '/principals/'
|
||||
$path = '/principals/';
|
||||
break;
|
||||
case 'property-search':
|
||||
$property_search = $n; // should be 1
|
||||
break;
|
||||
case 'prop':
|
||||
if (isset($property_search))
|
||||
{
|
||||
$search_props[$property_search] = array();
|
||||
}
|
||||
break;
|
||||
case 'match':
|
||||
if (isset($property_search) && is_array($search_props[$property_search]))
|
||||
{
|
||||
$search_props[$property_search]['match'] = $prop['data'];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (isset($property_search) && $search_props[$property_search] === array())
|
||||
{
|
||||
$search_props[$property_search] = $prop;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isset($property_search) || !$search_props || !isset($search_props[$property_search]['match']))
|
||||
{
|
||||
error_log(__METHOD__."('$path',...) Could not parse options[other]=".array2string($options['other']));
|
||||
return '400 Bad Request';
|
||||
}
|
||||
// make sure search property is included in toplevel props (can be missing and defaults to property-search/prop's)
|
||||
foreach($search_props as $prop)
|
||||
{
|
||||
if (!$this->groupdav->prop_requested($prop['name'], $prop['xmlns']))
|
||||
{
|
||||
$options['props'][] = array(
|
||||
'name' => $prop['name'],
|
||||
'xmlns' => $prop['xmlns'],
|
||||
);
|
||||
}
|
||||
// Hack for Lightning: it requests calendar-home-set matching our root (/egroupware/groupdav.php),
|
||||
// but interprets returning all principals (all have a matching calendar-home-set) as NOT supporting CalDAV scheduling
|
||||
// --> search only current user's principal
|
||||
if ($prop['name'] == 'calendar-home-set' && stripos($_SERVER['HTTP_USER_AGENT'], 'Lightning') !== false)
|
||||
{
|
||||
$path = '/principals/users/'.$GLOBALS['egw_info']['user']['account_lid'].'/';
|
||||
}
|
||||
}
|
||||
// run "regular" propfind
|
||||
$options['other'] = array();
|
||||
$options['root']['name'] = 'propfind';
|
||||
if (($ret = $this->propfind($path, $options, $files, $user)) !== true)
|
||||
{
|
||||
return $ret;
|
||||
}
|
||||
// now filter out not matching "files"
|
||||
foreach($files['files'] as $n => $resource)
|
||||
{
|
||||
if (count(explode('/', $resource['path'])) < 4) // hack to only return principals, not the collections itself
|
||||
{
|
||||
unset($files['files'][$n]);
|
||||
continue;
|
||||
}
|
||||
// search with all $search_props
|
||||
foreach($search_props as $search_prop)
|
||||
{
|
||||
// search resource for $search_prop
|
||||
foreach($resource['props'] as $prop) if ($prop['name'] === $search_prop['name']) break;
|
||||
if ($prop['name'] === $search_prop['name']) // search_prop NOT found
|
||||
{
|
||||
foreach((array)$prop['val'] as $value)
|
||||
{
|
||||
if (is_array($value)) $value = $value['val']; // eg. href prop
|
||||
if (stripos($value, $search_prop['match']) !== false) // prop does match
|
||||
{
|
||||
//error_log("$resource[path]: $search_prop[name]=".array2string($prop['name'] !== $search_prop['name'] ? null : $prop['val'])." does match '$search_prop[match]'");
|
||||
continue 2; // search next search_prop
|
||||
}
|
||||
}
|
||||
}
|
||||
//error_log("$resource[path]: $search_prop[name]=".array2string($prop['name'] !== $search_prop['name'] ? null : $prop['val'])." does NOT match '$search_prop[match]' --> remove from result");
|
||||
unset($files['files'][$n]);
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do propfind in /pricipals/users
|
||||
*
|
||||
@ -566,7 +698,7 @@ class groupdav_principals extends groupdav_handler
|
||||
|
||||
if ($options['depth'])
|
||||
{
|
||||
$options['depth'] = 0;
|
||||
if (is_numeric($options['depth'])) --$options['depth'];
|
||||
$files = array_merge($files,$this->propfind_users('','',$options));
|
||||
$files = array_merge($files,$this->propfind_groups('','',$options));
|
||||
//$files = array_merge($this->propfind_resources('','',$options));
|
||||
|
Loading…
Reference in New Issue
Block a user