mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-28 10:53:39 +01:00
Various GroupDAV fixes and extensions
This commit is contained in:
parent
55e14b525b
commit
306c9455c5
@ -51,10 +51,11 @@ class addressbook_groupdav extends groupdav_handler
|
||||
* @param string $app 'calendar', 'addressbook' or 'infolog'
|
||||
* @param int $debug=null debug-level to set
|
||||
* @param string $base_uri=null base url of handler
|
||||
* @param string $principalURL=null pricipal url of handler
|
||||
*/
|
||||
function __construct($app,$debug=null,$base_uri=null)
|
||||
function __construct($app,$debug=null,$base_uri=null,$principalURL=null)
|
||||
{
|
||||
parent::__construct($app,$debug,$base_uri);
|
||||
parent::__construct($app,$debug,$base_uri,$principalURL);
|
||||
|
||||
$this->bo = new addressbook_bo();
|
||||
}
|
||||
@ -309,7 +310,7 @@ class addressbook_groupdav extends groupdav_handler
|
||||
|
||||
/**
|
||||
* Query ctag for addressbook
|
||||
*
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getctag($path,$user)
|
||||
@ -319,9 +320,9 @@ class addressbook_groupdav extends groupdav_handler
|
||||
if ($user && $path != '/addressbook/') $filter['contact_owner'] = $user;
|
||||
// should we hide the accounts addressbook
|
||||
if ($GLOBALS['egw_info']['user']['preferences']['addressbook']['hide_accounts']) $filter['account_id'] = null;
|
||||
|
||||
|
||||
$result = $this->bo->search(array(),'MAX(contact_modified) AS contact_modified','','','','','',$filter);
|
||||
|
||||
|
||||
return '"'.$result[0]['modified'].'"';
|
||||
}
|
||||
|
||||
@ -342,11 +343,12 @@ class addressbook_groupdav extends groupdav_handler
|
||||
* </supported-report>
|
||||
* </D:supported-report-set>
|
||||
* @link http://www.mail-archive.com/calendarserver-users@lists.macosforge.org/msg01156.html
|
||||
*
|
||||
*
|
||||
* @param array $props=array() regular props by the groupdav handler
|
||||
* @param string $base_uri=null base url of handler
|
||||
* @return array
|
||||
*/
|
||||
static function extra_properties(array $props=array())
|
||||
static function extra_properties(array $props=array(), $base_uri=null)
|
||||
{
|
||||
// supported reports (required property for CardDAV)
|
||||
$props[] = HTTP_WebDAV_Server::mkprop('supported-report-set',array(
|
||||
|
@ -23,6 +23,8 @@ class calendar_groupdav extends groupdav_handler
|
||||
*/
|
||||
var $bo;
|
||||
|
||||
const DAV = 'DAV:';
|
||||
|
||||
var $filter_prop2cal = array(
|
||||
'SUMMARY' => 'cal_title',
|
||||
'UID' => 'cal_uid',
|
||||
@ -58,10 +60,11 @@ class calendar_groupdav extends groupdav_handler
|
||||
* @param string $app 'calendar', 'addressbook' or 'infolog'
|
||||
* @param int $debug=null debug-level to set
|
||||
* @param string $base_uri=null base url of handler
|
||||
* @param string $principalURL=null pricipal url of handler
|
||||
*/
|
||||
function __construct($app,$debug=null, $base_uri=null)
|
||||
function __construct($app,$debug=null, $base_uri=null,$principalURL=null)
|
||||
{
|
||||
parent::__construct($app,$debug,$base_uri);
|
||||
parent::__construct($app,$debug,$base_uri,$principalURL);
|
||||
|
||||
$this->bo = new calendar_boupdate();
|
||||
}
|
||||
@ -172,8 +175,10 @@ class calendar_groupdav extends groupdav_handler
|
||||
'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',''), // iPhone requires that attribute!
|
||||
HTTP_WebDAV_Server::mkprop('resourcetype',''), // DAVKit requires that attribute!
|
||||
);
|
||||
//$props[] = HTTP_WebDAV_Server::mkprop('current-user-principal',array(self::mkprop('href','MAILTO:'.$GLOBALS['egw_info']['user']['email'])));
|
||||
//$props = self::current_user_privilege_set($props);
|
||||
//error_log(__FILE__ . __METHOD__ . "Calendar Data : $calendar_data");
|
||||
if ($calendar_data)
|
||||
{
|
||||
@ -229,7 +234,7 @@ class calendar_groupdav extends groupdav_handler
|
||||
return false; // return nothing for now, todo: check if we can pass it on to the infolog handler
|
||||
// todos are handled by the infolog handler
|
||||
//$infolog_handler = new groupdav_infolog();
|
||||
//return $infolog_handler->propfind($path,$options,$files,$user,$method);
|
||||
//return $infolog_handler->propfind($options['path'],$options,$options['files'],$user,$method);
|
||||
case 'VCALENDAR':
|
||||
case 'VEVENT':
|
||||
break; // that's our default anyway
|
||||
@ -357,7 +362,7 @@ class calendar_groupdav extends groupdav_handler
|
||||
{
|
||||
$events[0]['uid'] .= '-'.$event['id']; // force a different uid
|
||||
}
|
||||
return $handler->exportVCal($events,'2.0','PUBLISH');
|
||||
return $handler->exportVCal($events,'2.0','PUBLISH',0,$this->principalURL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -444,13 +449,10 @@ class calendar_groupdav extends groupdav_handler
|
||||
}
|
||||
$handler = $this->_get_handler();
|
||||
|
||||
if (!is_numeric($id) && ($foundEntries = $handler->find_event($options['content'], 'exact')))
|
||||
{
|
||||
$id = array_shift($foundEntries);
|
||||
}
|
||||
$vCalendar = htmlspecialchars_decode($options['content']);
|
||||
|
||||
if (!($cal_id = $handler->importVCal($options['content'],is_numeric($id) ? $id : -1,
|
||||
self::etag2value($this->http_if_match))))
|
||||
if (!($cal_id = $handler->importVCal($vCalendar, is_numeric($id) ? $id : -1,
|
||||
self::etag2value($this->http_if_match), false, 0, $this->principalURL)))
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."(,$id) importVCal($options[content]) returned false");
|
||||
return '403 Forbidden';
|
||||
@ -463,6 +465,11 @@ class calendar_groupdav extends groupdav_handler
|
||||
header('Location: '.$this->base_uri.self::get_path($cal_id));
|
||||
return '201 Created';
|
||||
}
|
||||
if (strpos($_SERVER[HTTP_USER_AGENT], 'Mac OS X') !== false)
|
||||
{
|
||||
//return '205 Reset Content'; // would be nicer
|
||||
return '400 Event updated, please reload'; // Enforce a reload by iCal
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -636,23 +643,75 @@ class calendar_groupdav extends groupdav_handler
|
||||
}
|
||||
|
||||
/**
|
||||
* Add extra properties for calendar collections
|
||||
* Add the privileges of the current user
|
||||
*
|
||||
* @param array $props=array() regular props by the groupdav handler
|
||||
* @return array
|
||||
*/
|
||||
static function extra_properties(array $props=array())
|
||||
static function current_user_privilege_set(array $props=array())
|
||||
{
|
||||
// calendaring URL of the current user
|
||||
$props[] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-home-set',$_SERVER['SCRIPT_NAME'].'/');
|
||||
$props[] = HTTP_WebDAV_Server::mkprop(self::DAV,'current-user-privilege-set',
|
||||
array(HTTP_WebDAV_Server::mkprop(self::DAV,'privilege',
|
||||
array(//HTTP_WebDAV_Server::mkprop(self::DAV,'all',''),
|
||||
HTTP_WebDAV_Server::mkprop(self::DAV,'read',''),
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'read-free-busy',''),
|
||||
//HTTP_WebDAV_Server::mkprop(self::DAV,'read-current-user-privilege-set',''),
|
||||
HTTP_WebDAV_Server::mkprop(self::DAV,'bind',''),
|
||||
HTTP_WebDAV_Server::mkprop(self::DAV,'unbind',''),
|
||||
HTTP_WebDAV_Server::mkprop(self::DAV,'schedule-post',''),
|
||||
HTTP_WebDAV_Server::mkprop(self::DAV,'schedule-post-vevent',''),
|
||||
HTTP_WebDAV_Server::mkprop(self::DAV,'schedule-respond',''),
|
||||
HTTP_WebDAV_Server::mkprop(self::DAV,'schedule-respond-vevent',''),
|
||||
HTTP_WebDAV_Server::mkprop(self::DAV,'schedule-deliver',''),
|
||||
HTTP_WebDAV_Server::mkprop(self::DAV,'schedule-deliver-vevent',''),
|
||||
HTTP_WebDAV_Server::mkprop(self::DAV,'write',''),
|
||||
HTTP_WebDAV_Server::mkprop(self::DAV,'write-properties',''),
|
||||
HTTP_WebDAV_Server::mkprop(self::DAV,'write-content',''),
|
||||
))));
|
||||
return $props;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add extra properties for calendar collections
|
||||
*
|
||||
* @param array $props=array() regular props by the groupdav handler
|
||||
* @param string $base_uri=null base url of handler
|
||||
* @return array
|
||||
*/
|
||||
static function extra_properties(array $props=array(), $base_uri=null)
|
||||
{
|
||||
// calendar description
|
||||
$displayname = $GLOBALS['egw']->translation->convert(lang('Calendar of'). ' ' .
|
||||
$GLOBALS['egw_info']['user']['account_fullname'],
|
||||
$GLOBALS['egw']->translation->charset(),'utf-8');
|
||||
$props[] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-description',$displayname);
|
||||
// BOX URLs of the current user
|
||||
/*
|
||||
$props[] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'schedule-inbox-URL',
|
||||
array(HTTP_WebDAV_Server::mkprop(self::DAV,'href',$base_uri.'/calendar/')));
|
||||
$props[] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'schedule-outbox-URL',
|
||||
array(HTTP_WebDAV_Server::mkprop(self::DAV,'href',$base_uri.'/calendar/')));
|
||||
$props[] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'schedule-default-calendar-URL',
|
||||
array(HTTP_WebDAV_Server::mkprop(self::DAV,'href',$base_uri.'/calendar/')));
|
||||
$props[] = HTTP_WebDAV_Server::mkprop(groupdav::CALENDARSERVER,'dropbox-home-URL',
|
||||
array(HTTP_WebDAV_Server::mkprop(self::DAV,'href',$base_uri.'/calendar/')));
|
||||
$props[] = HTTP_WebDAV_Server::mkprop(groupdav::CALENDARSERVER,'notifications-URL',
|
||||
array(HTTP_WebDAV_Server::mkprop(self::DAV,'href',$base_uri.'/calendar/')));
|
||||
*/
|
||||
// email of the current user, see caldav-sheduling draft
|
||||
$props[] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-user-address-set','MAILTO:'.$GLOBALS['egw_info']['user']['email']);
|
||||
// supported components, currently only VEVENT
|
||||
$props[] = $sc = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'supported-calendar-component-set',array(
|
||||
$props[] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'supported-calendar-component-set',array(
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'comp',array('name' => 'VEVENT')),
|
||||
// HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'comp',array('name' => 'VTODO')), // not yet supported
|
||||
// HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'comp',array('name' => 'VTODO')), // not yet supported
|
||||
));
|
||||
|
||||
/*
|
||||
$props[] = HTTP_WebDAV_Server::mkprop('supported-report-set',array(
|
||||
HTTP_WebDAV_Server::mkprop('supported-report',array(
|
||||
HTTP_WebDAV_Server::mkprop('report',
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-multiget'))))));
|
||||
*/
|
||||
//$props = self::current_user_privilege_set($props);
|
||||
return $props;
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,7 @@ class calendar_ical extends calendar_boupdate
|
||||
'DECLINED' => 'R',
|
||||
'TENTATIVE' => 'T',
|
||||
'DELEGATED' => 'D',
|
||||
'X-UNINVITED' => 'G', // removed
|
||||
);
|
||||
|
||||
/**
|
||||
@ -188,21 +189,29 @@ class calendar_ical extends calendar_boupdate
|
||||
if ($this->log) $this->logfile = $GLOBALS['egw_info']['server']['temp_dir']."/log-vcal";
|
||||
$this->clientProperties = $_clientProperties;
|
||||
$this->vCalendar = new Horde_iCalendar;
|
||||
$this->addressbook = new addressbook_bo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Exports one calendar event to an iCalendar item
|
||||
*
|
||||
* @param int/array $events (array of) cal_id or array of the events
|
||||
* @param int|array $events (array of) cal_id or array of the events
|
||||
* @param string $version='1.0' could be '2.0' too
|
||||
* @param string $method='PUBLISH'
|
||||
* @param int $recur_date=0 if set export the next recurrence at or after the timestamp,
|
||||
* default 0 => export whole series (or events, if not recurring)
|
||||
* @return string/boolean string with iCal or false on error (eg. no permission to read the event)
|
||||
* @param string $principalURL='' Used for CalDAV exports
|
||||
* @return string|boolean string with iCal or false on error (eg. no permission to read the event)
|
||||
*/
|
||||
function &exportVCal($events, $version='1.0', $method='PUBLISH', $recur_date=0)
|
||||
function &exportVCal($events, $version='1.0', $method='PUBLISH', $recur_date=0, $principalURL='')
|
||||
{
|
||||
if ($this->log)
|
||||
{
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
|
||||
"($version, $method, $recur_date, $principalURL)\n",
|
||||
3, $this->logfile);
|
||||
}
|
||||
$egwSupportedFields = array(
|
||||
'CLASS' => 'public',
|
||||
'SUMMARY' => 'title',
|
||||
@ -242,7 +251,7 @@ class calendar_ical extends calendar_boupdate
|
||||
|
||||
foreach ($events as $event)
|
||||
{
|
||||
$mailtoOrganizer = false;
|
||||
$organizerURL = '';
|
||||
$organizerCN = false;
|
||||
$recurrence = $this->date2usertime($recur_date);
|
||||
if (!is_array($event)
|
||||
@ -436,11 +445,19 @@ class calendar_ical extends calendar_boupdate
|
||||
foreach ((array)$event['participants'] as $uid => $status)
|
||||
{
|
||||
if (!($info = $this->resource_info($uid))) continue;
|
||||
$mailtoParticipant = $info['email'] ? 'MAILTO:'.$info['email'] : '';
|
||||
$participantURL = $info['email'] ? 'MAILTO:'.$info['email'] : '';
|
||||
$participantCN = '"' . ($info['cn'] ? $info['cn'] : $info['name']) . '"';
|
||||
calendar_so::split_status($status, $quantity, $role);
|
||||
if ($uid == $event['owner'])
|
||||
{
|
||||
$role = 'CHAIR';
|
||||
}
|
||||
else
|
||||
{
|
||||
$role = 'REQ-PARTICIPANT';
|
||||
}
|
||||
// RB: MAILTO href contains only the email-address, NO cn!
|
||||
$attributes['ATTENDEE'][] = $mailtoParticipant;
|
||||
$attributes['ATTENDEE'][] = $participantURL;
|
||||
// RSVP={TRUE|FALSE} // resonse expected, not set in eGW => status=U
|
||||
$rsvp = $status == 'U' ? 'TRUE' : 'FALSE';
|
||||
// PARTSTAT={NEEDS-ACTION|ACCEPTED|DECLINED|TENTATIVE|DELEGATED|COMPLETED|IN-PROGRESS} everything from delegated is NOT used by eGW atm.
|
||||
@ -487,21 +504,28 @@ class calendar_ical extends calendar_boupdate
|
||||
break;
|
||||
|
||||
case 'ORGANIZER':
|
||||
// according to iCalendar standard, ORGANIZER not used for events in the own calendar
|
||||
if (!$organizerCN &&
|
||||
($event['owner'] != $this->user
|
||||
|| $this->productManufacturer != 'groupdav'
|
||||
|| $this->productName == 'kde'))
|
||||
$organizerURL = $GLOBALS['egw']->accounts->id2name($event['owner'],'account_email');
|
||||
$organizerURL = $organizerURL ? 'MAILTO:'.$organizerURL : '';
|
||||
$organizerCN = '"' . trim($GLOBALS['egw']->accounts->id2name($event['owner'],'account_firstname')
|
||||
. ' ' . $GLOBALS['egw']->accounts->id2name($event['owner'],'account_lastname')) . '"';
|
||||
if (!isset($event['participants'][$event['owner']]))
|
||||
{
|
||||
$mailtoOrganizer = $GLOBALS['egw']->accounts->id2name($event['owner'],'account_email');
|
||||
$mailtoOrganizer = $mailtoOrganizer ? 'MAILTO:'.$mailtoOrganizer : '';
|
||||
$organizerCN = '"' . trim($GLOBALS['egw']->accounts->id2name($event['owner'],'account_firstname')
|
||||
. ' ' . $GLOBALS['egw']->accounts->id2name($event['owner'],'account_lastname')) . '"';
|
||||
$attributes['ATTENDEE'][] = $organizerURL;
|
||||
$parameters['ATTENDEE'][] = array(
|
||||
'CN' => $organizerCN,
|
||||
'ROLE' => 'CHAIR',
|
||||
'PARTSTAT' => 'DELEGATED',
|
||||
'CUTYPE' => 'INDIVIDUAL',
|
||||
'RSVP' => 'FALSE',
|
||||
'X-EGROUPWARE-UID' => $event['owner'],
|
||||
);
|
||||
}
|
||||
if ($organizerCN)
|
||||
if ($this->productManufacturer != 'groupdav'
|
||||
|| !$this->check_perms(EGW_ACL_EDIT,$event['id']))
|
||||
{
|
||||
$attributes['ORGANIZER'] = $mailtoOrganizer;
|
||||
$attributes['ORGANIZER'] = $organizerURL;
|
||||
$parameters['ORGANIZER']['CN'] = $organizerCN;
|
||||
$parameters['ORGANIZER']['X-EGROUPWARE-UID'] = $event['owner'];
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1004,13 +1028,14 @@ class calendar_ical extends calendar_boupdate
|
||||
* @param boolean $merge=false merge data with existing entry
|
||||
* @param int $recur_date=0 if set, import the recurrence at this timestamp,
|
||||
* default 0 => import whole series (or events, if not recurring)
|
||||
* @param string $principalURL='' Used for CalDAV imports
|
||||
* @return int|boolean cal_id > 0 on success, false on failure or 0 for a failed etag
|
||||
*/
|
||||
function importVCal($_vcalData, $cal_id=-1, $etag=null, $merge=false, $recur_date=0)
|
||||
function importVCal($_vcalData, $cal_id=-1, $etag=null, $merge=false, $recur_date=0, $principalURL='')
|
||||
{
|
||||
if (!is_array($this->supportedFields)) $this->setSupportedFields();
|
||||
|
||||
if (!($events = $this->icaltoegw($_vcalData)))
|
||||
if (!($events = $this->icaltoegw($_vcalData, $principalURL)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -1055,8 +1080,9 @@ class calendar_ical extends calendar_boupdate
|
||||
}
|
||||
if ($this->log)
|
||||
{
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n" .
|
||||
array2string($event)."\n",3,$this->logfile);
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__
|
||||
."($cal_id, $etag, $recur_date, $principalURL)\n"
|
||||
. array2string($event)."\n",3,$this->logfile);
|
||||
}
|
||||
$updated_id = false;
|
||||
$event_info = $this->get_event_info($event);
|
||||
@ -1108,7 +1134,7 @@ class calendar_ical extends calendar_boupdate
|
||||
else
|
||||
{
|
||||
// no merge
|
||||
if(!isset($this->supportedFields['category']))
|
||||
if(!isset($this->supportedFields['category']) || !isset($event['category']))
|
||||
{
|
||||
$event['category'] = $event_info['stored_event']['category'];
|
||||
}
|
||||
@ -1830,11 +1856,18 @@ class calendar_ical extends calendar_boupdate
|
||||
// __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
}
|
||||
|
||||
function icaltoegw($_vcalData)
|
||||
/**
|
||||
* Convert vCalendar data in EGw events
|
||||
*
|
||||
* @param string $_vcalData
|
||||
* @param string $principalURL='' Used for CalDAV imports
|
||||
* @return array|boolean events on success, false on failure
|
||||
*/
|
||||
function icaltoegw($_vcalData, $principalURL='')
|
||||
{
|
||||
if ($this->log)
|
||||
{
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n" .
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."($principalURL)\n" .
|
||||
array2string($_vcalData)."\n",3,$this->logfile);
|
||||
}
|
||||
|
||||
@ -1848,10 +1881,6 @@ class calendar_ical extends calendar_boupdate
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
|
||||
"(): No vCalendar Container found!\n",3,$this->logfile);
|
||||
}
|
||||
if ($this->tzid)
|
||||
{
|
||||
date_default_timezone_set($GLOBALS['egw_info']['server']['server_timezone']);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
$version = $vcal->getAttribute('VERSION');
|
||||
@ -1861,7 +1890,12 @@ class calendar_ical extends calendar_boupdate
|
||||
{
|
||||
if (is_a($component, 'Horde_iCalendar_vevent'))
|
||||
{
|
||||
if ($event = $this->vevent2egw($component, $version, $this->supportedFields))
|
||||
if ($this->log)
|
||||
{
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.'()' .
|
||||
get_class($component)." found\n",3,$this->logfile);
|
||||
}
|
||||
if ($event = $this->vevent2egw($component, $version, $this->supportedFields, $principalURL))
|
||||
{
|
||||
if ($this->isWholeDay($event)) $event['whole_day'] = true;
|
||||
//common adjustments
|
||||
@ -1958,6 +1992,14 @@ class calendar_ical extends calendar_boupdate
|
||||
$events[] = $event;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($this->log)
|
||||
{
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.'()' .
|
||||
get_class($component)." found\n",3,$this->logfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $events;
|
||||
@ -1969,12 +2011,21 @@ class calendar_ical extends calendar_boupdate
|
||||
* @param array $component VEVENT
|
||||
* @param string $version vCal version (1.0/2.0)
|
||||
* @param array $supportedFields supported fields of the device
|
||||
* @param string $principalURL='' Used for CalDAV imports
|
||||
*
|
||||
* @return array|boolean event on success, false on failure
|
||||
*/
|
||||
function vevent2egw(&$component, $version, $supportedFields)
|
||||
function vevent2egw(&$component, $version, $supportedFields, $principalURL='')
|
||||
{
|
||||
if (!is_a($component, 'Horde_iCalendar_vevent')) return false;
|
||||
if (!is_a($component, 'Horde_iCalendar_vevent'))
|
||||
{
|
||||
if ($this->log)
|
||||
{
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.'()' .
|
||||
get_class($component)." found\n",3,$this->logfile);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'])) {
|
||||
$minimum_uid_length = $GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'];
|
||||
@ -2014,11 +2065,24 @@ class calendar_ical extends calendar_boupdate
|
||||
$vcardData['end'] = $dtend_ts;
|
||||
}
|
||||
}
|
||||
if (!isset($vcardData['start'])) return false; // not a valid entry
|
||||
|
||||
if (!isset($vcardData['start']))
|
||||
{
|
||||
if ($this->log)
|
||||
{
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__
|
||||
. "() DTSTART missing!\n",3,$this->logfile);
|
||||
}
|
||||
return false; // not a valid entry
|
||||
}
|
||||
// lets see what we can get from the vcard
|
||||
foreach ($component->_attributes as $attributes)
|
||||
{
|
||||
if ($this->log)
|
||||
{
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__
|
||||
. '(): ' . $attributes['name'] . ' => '
|
||||
. $attributes['value'] . "\n",3,$this->logfile);
|
||||
}
|
||||
switch ($attributes['name'])
|
||||
{
|
||||
case 'AALARM':
|
||||
@ -2358,14 +2422,64 @@ class calendar_ical extends calendar_boupdate
|
||||
{
|
||||
$status = 'X'; // client did not return the status
|
||||
}
|
||||
$cn = '';
|
||||
if (preg_match('/MAILTO:([@.a-z0-9_-]+)|MAILTO:"?([.a-z0-9_ -]*)"?[ ]*<([@.a-z0-9_-]*)>/i',
|
||||
$uid = $email = $cn = '';
|
||||
$quantity = 1;
|
||||
$role = 'REQ-PARTICIPANT';
|
||||
if (!empty($attributes['params']['ROLE']))
|
||||
{
|
||||
$role = $attributes['params']['ROLE'];
|
||||
}
|
||||
// try pricipal url from CalDAV
|
||||
if (strpos($attributes['value'], 'http') === 0)
|
||||
{
|
||||
if (!empty($principalURL) && strstr($attributes['value'], $principalURL) !== false)
|
||||
{
|
||||
$uid = $this->user;
|
||||
if ($this->log)
|
||||
{
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__
|
||||
. "(): Found myself: '$uid'\n",3,$this->logfile);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($this->log)
|
||||
{
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__
|
||||
. '(): Unknown URI: ' . $attributes['value']
|
||||
. "\n",3,$this->logfile);
|
||||
}
|
||||
$attributes['value'] = '';
|
||||
}
|
||||
}
|
||||
// try X-EGROUPWARE-UID
|
||||
if (!$uid && !empty($attributes['params']['X-EGROUPWARE-UID']))
|
||||
{
|
||||
$uid = $attributes['params']['X-EGROUPWARE-UID'];
|
||||
if (!empty($attributes['params']['X-EGROUPWARE-QUANTITY']))
|
||||
{
|
||||
$quantity = $attributes['params']['X-EGROUPWARE-QUANTITY'];
|
||||
}
|
||||
if ($this->log)
|
||||
{
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__
|
||||
. "(): Found X-EGROUPWARE-UID: '$uid'\n",3,$this->logfile);
|
||||
}
|
||||
}
|
||||
elseif ($attributes['value'] == 'Unknown')
|
||||
{
|
||||
// we use the current user
|
||||
$uid = $this->user;
|
||||
}
|
||||
// try to find an email address
|
||||
elseif (preg_match('/MAILTO:([@.a-z0-9_-]+)|MAILTO:"?([.a-z0-9_ -]*)"?[ ]*<([@.a-z0-9_-]*)>/i',
|
||||
$attributes['value'],$matches))
|
||||
{
|
||||
$email = $matches[1] ? $matches[1] : $matches[3];
|
||||
$cn = isset($matches[2]) ? $matches[2]: '';
|
||||
}
|
||||
elseif (preg_match('/"?([.a-z0-9_ -]*)"?[ ]*<([@.a-z0-9_-]*)>/i',
|
||||
elseif (!empty($attributes['value']) &&
|
||||
preg_match('/"?([.a-z0-9_ -]*)"?[ ]*<([@.a-z0-9_-]*)>/i',
|
||||
$attributes['value'],$matches))
|
||||
{
|
||||
$cn = $matches[1];
|
||||
@ -2375,82 +2489,92 @@ class calendar_ical extends calendar_boupdate
|
||||
{
|
||||
$email = $attributes['value'];
|
||||
}
|
||||
else
|
||||
if (!$uid && $email && ($uid = $GLOBALS['egw']->accounts->name2id($email, 'account_email')))
|
||||
{
|
||||
$email = false; // no email given
|
||||
}
|
||||
$searcharray = array();
|
||||
if ($email)
|
||||
{
|
||||
$searcharray = array('email' => $email, 'email_home' => $email);
|
||||
}
|
||||
if (isset($attributes['params']['CN']) && $attributes['params']['CN'])
|
||||
{
|
||||
if ($attributes['params']['CN'][0] == '"'
|
||||
&& substr($attributes['params']['CN'],-1) == '"')
|
||||
// we use the account we found
|
||||
if ($this->log)
|
||||
{
|
||||
$attributes['params']['CN'] = substr($attributes['params']['CN'],1,-1);
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__
|
||||
. "() Found account: '$uid', '$cn', '$email'\n",3,$this->logfile);
|
||||
}
|
||||
$searcharray['n_fn'] = $attributes['params']['CN'];
|
||||
}
|
||||
elseif ($cn)
|
||||
if (!$uid)
|
||||
{
|
||||
$searcharray['n_fn'] = $cn;
|
||||
}
|
||||
if (($uid = $attributes['params']['X-EGROUPWARE-UID'])
|
||||
&& ($info = $this->resource_info($uid))
|
||||
&& (!$email || $info['email'] == $email))
|
||||
{
|
||||
// we use the (checked) X-EGROUPWARE-UID
|
||||
}
|
||||
|
||||
//elseif (//$attributes['params']['CUTYPE'] == 'GROUP'
|
||||
elseif (preg_match('/(.*) Group/', $searcharray['n_fn'], $matches))
|
||||
{
|
||||
if (($uid = $GLOBALS['egw']->accounts->name2id($matches[1], 'account_lid', 'g')))
|
||||
$searcharray = array();
|
||||
// search for provided email address ...
|
||||
if ($email)
|
||||
{
|
||||
//Horde::logMessage("vevent2egw: group participant $uid",
|
||||
// __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
if ($status != 'X' && $status != 'U')
|
||||
$searcharray = array('email' => $email, 'email_home' => $email);
|
||||
}
|
||||
// ... and for provided CN
|
||||
if (!empty($attributes['params']['CN']))
|
||||
{
|
||||
if ($attributes['params']['CN'][0] == '"'
|
||||
&& substr($attributes['params']['CN'],-1) == '"')
|
||||
{
|
||||
// User tries to reply to the group invitiation
|
||||
$members = $GLOBALS['egw']->accounts->members($uid, true);
|
||||
if (in_array($this->user, $members))
|
||||
$cn = substr($attributes['params']['CN'],1,-1);
|
||||
}
|
||||
$searcharray['n_fn'] = $cn;
|
||||
}
|
||||
elseif ($cn)
|
||||
{
|
||||
$searcharray['n_fn'] = $cn;
|
||||
}
|
||||
|
||||
//elseif (//$attributes['params']['CUTYPE'] == 'GROUP'
|
||||
if (preg_match('/(.*) Group/', $cn, $matches))
|
||||
{
|
||||
if (($uid = $GLOBALS['egw']->accounts->name2id($matches[1], 'account_lid', 'g')))
|
||||
{
|
||||
//Horde::logMessage("vevent2egw: group participant $uid",
|
||||
// __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
if (!isset($vcardData['participants'][$this->user]) &&
|
||||
$status != 'X' && $status != 'U')
|
||||
{
|
||||
//Horde::logMessage("vevent2egw: set status to " . $status,
|
||||
// __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
$vcardData['participants'][$this->user] =
|
||||
calendar_so::combine_status($status);
|
||||
// User tries to reply to the group invitiation
|
||||
$members = $GLOBALS['egw']->accounts->members($uid, true);
|
||||
if (in_array($this->user, $members))
|
||||
{
|
||||
//Horde::logMessage("vevent2egw: set status to " . $status,
|
||||
// __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
$vcardData['participants'][$this->user] =
|
||||
calendar_so::combine_status($status,$quantity,$role);
|
||||
}
|
||||
}
|
||||
$status = 'U'; // keep the group
|
||||
}
|
||||
else continue; // can't find this group
|
||||
}
|
||||
else continue; // can't find this group
|
||||
}
|
||||
elseif ($attributes['value'] == 'Unknown')
|
||||
{
|
||||
$uid = $this->user;
|
||||
}
|
||||
elseif ($email && ($uid = $GLOBALS['egw']->accounts->name2id($email,'account_email')))
|
||||
{
|
||||
// we use the account we found
|
||||
}
|
||||
elseif (!$searcharray)
|
||||
{
|
||||
continue; // participants without email AND CN --> ignore it
|
||||
}
|
||||
elseif ((list($data) = ExecMethod2('addressbook.addressbook_bo.search',$searcharray,
|
||||
array('id','egw_addressbook.account_id as account_id','n_fn'),'egw_addressbook.account_id IS NOT NULL DESC, n_fn IS NOT NULL DESC','','',false,'OR')))
|
||||
{
|
||||
$uid = $data['account_id'] ? (int)$data['account_id'] : 'c'.$data['id'];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!$email)
|
||||
elseif (empty($searcharray))
|
||||
{
|
||||
$email = 'no-email@egroupware.org'; // set dummy email to store the CN
|
||||
continue; // participants without email AND CN --> ignore it
|
||||
}
|
||||
elseif ((list($data) = $this->addressbook->search($searcharray,
|
||||
array('id','egw_addressbook.account_id as account_id','n_fn'),
|
||||
'egw_addressbook.account_id IS NOT NULL DESC, n_fn IS NOT NULL DESC',
|
||||
'','',false,'OR')))
|
||||
{
|
||||
// found an addressbook entry
|
||||
$uid = $data['account_id'] ? (int)$data['account_id'] : 'c'.$data['id'];
|
||||
if ($this->log)
|
||||
{
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__
|
||||
. "() Found addressbook entry: '$uid', '$cn', '$email'\n",3,$this->logfile);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!$email)
|
||||
{
|
||||
$email = 'no-email@egroupware.org'; // set dummy email to store the CN
|
||||
}
|
||||
$uid = 'e'. ($cn ? '"' . $cn . '" <' . $email . '>' : $email);
|
||||
if ($this->log)
|
||||
{
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__
|
||||
. "() Not Found, create dummy: '$uid', '$cn', '$email'\n",3,$this->logfile);
|
||||
}
|
||||
}
|
||||
$uid = 'e'.($attributes['params']['CN'] ? $attributes['params']['CN'].' <'.$email.'>' : $email);
|
||||
}
|
||||
switch($attributes['name'])
|
||||
{
|
||||
@ -2461,9 +2585,15 @@ class calendar_ical extends calendar_boupdate
|
||||
// for multiple entries the ACCEPT wins
|
||||
// add quantity and role
|
||||
$vcardData['participants'][$uid] =
|
||||
calendar_so::combine_status($status,
|
||||
$attributes['params']['X-EGROUPWARE-QUANTITY'],
|
||||
$attributes['params']['ROLE']);
|
||||
calendar_so::combine_status($status, $quantity, $role);
|
||||
|
||||
if (!$this->calendarOwner && is_numeric($uid) &&
|
||||
$role == 'CHAIR' &&
|
||||
is_a($component->getAttribute('ORGANIZER'), 'PEAR_Error'))
|
||||
{
|
||||
// we can store the ORGANIZER as event owner
|
||||
$event['owner'] = $uid;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2475,7 +2605,7 @@ class calendar_ical extends calendar_boupdate
|
||||
$vcardData['participants'][$uid] =
|
||||
calendar_so::combine_status($status, $quantity, 'CHAIR');
|
||||
}
|
||||
if (is_numeric($uid) && ($uid == $this->calendarOwner || !$this->calendarOwner))
|
||||
if (!$this->calendarOwner && is_numeric($uid))
|
||||
{
|
||||
// we can store the ORGANIZER as event owner
|
||||
$event['owner'] = $uid;
|
||||
@ -2488,7 +2618,7 @@ class calendar_ical extends calendar_boupdate
|
||||
{
|
||||
// save the ORGANIZER as event CHAIR
|
||||
$vcardData['participants'][$uid] =
|
||||
calendar_so::combine_status('U', 1, 'CHAIR');
|
||||
calendar_so::combine_status('D', 1, 'CHAIR');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2563,7 +2693,7 @@ class calendar_ical extends calendar_boupdate
|
||||
|
||||
if ($this->log)
|
||||
{
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n" .
|
||||
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."($principalURL)\n" .
|
||||
array2string($event)."\n",3,$this->logfile);
|
||||
}
|
||||
//Horde::logMessage("vevent2egw:\n" . print_r($event, true),
|
||||
|
@ -43,7 +43,6 @@ class HTTP_WebDAV_Server
|
||||
*/
|
||||
var $uri;
|
||||
|
||||
|
||||
/**
|
||||
* base URI for this request
|
||||
*
|
||||
@ -431,6 +430,26 @@ class HTTP_WebDAV_Server
|
||||
// dummy entry for PHPDoc
|
||||
}
|
||||
*/
|
||||
// }}}
|
||||
|
||||
// {{{ LOCK()
|
||||
|
||||
/**
|
||||
* ACL implementation
|
||||
*
|
||||
* ACL implementation
|
||||
*
|
||||
* @abstract
|
||||
* @param array &$params
|
||||
* @returns int HTTP-Statuscode
|
||||
*/
|
||||
|
||||
/* abstract
|
||||
function ACL()
|
||||
{
|
||||
// dummy entry for PHPDoc
|
||||
}
|
||||
*/
|
||||
// }}}
|
||||
|
||||
// }}}
|
||||
@ -592,13 +611,27 @@ class HTTP_WebDAV_Server
|
||||
}
|
||||
}
|
||||
|
||||
// now we generate the reply header ...
|
||||
$this->http_status("207 Multi-Status");
|
||||
// now we generate the reply header ...
|
||||
if ($propinfo->root['name'] == 'principal-search-property-set')
|
||||
{
|
||||
$this->http_status('200 OK');
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->http_status('207 Multi-Status');
|
||||
}
|
||||
header('Content-Type: text/xml; charset="utf-8"');
|
||||
|
||||
// ... and payload
|
||||
echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
|
||||
echo "<D:multistatus xmlns:D=\"DAV:\">\n";
|
||||
if ($propinfo->root['name'] == 'principal-search-property-set')
|
||||
{
|
||||
echo "<D:principal-search-property-set xmlns:D=\"DAV:\">\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "<D:multistatus xmlns:D=\"DAV:\">\n";
|
||||
}
|
||||
|
||||
// using an ArrayIterator to prevent foreach from copying the array,
|
||||
// as we cant loop by reference, when an iterator is given in $files['files']
|
||||
@ -715,7 +748,7 @@ class HTTP_WebDAV_Server
|
||||
$path = $file['path'];
|
||||
if (!is_string($path) || $path==="") continue;
|
||||
|
||||
echo " <D:response $ns_defs>\n";
|
||||
if ($propinfo->root['name'] != 'principal-search-property-set') echo " <D:response $ns_defs>\n";
|
||||
|
||||
/* TODO right now the user implementation has to make sure
|
||||
collections end in a slash, this should be done in here
|
||||
@ -723,13 +756,15 @@ class HTTP_WebDAV_Server
|
||||
// path needs to be urlencoded (only basic version of this class!)
|
||||
$href = $this->_urlencode($this->_mergePathes($this->base_uri, $path));
|
||||
|
||||
echo " <D:href>$href</D:href>\n";
|
||||
if ($propinfo->root['name'] != 'principal-search-property-set') echo " <D:href>$href</D:href>\n";
|
||||
|
||||
// report all found properties and their values (if any)
|
||||
if (isset($file["props"]) && is_array($file["props"])) {
|
||||
echo " <D:propstat>\n";
|
||||
echo " <D:prop>\n";
|
||||
|
||||
if ($propinfo->root['name'] != 'principal-search-property-set')
|
||||
{
|
||||
echo " <D:propstat>\n";
|
||||
echo " <D:prop>\n";
|
||||
}
|
||||
foreach ($file["props"] as &$prop) {
|
||||
|
||||
if (!is_array($prop)) continue;
|
||||
@ -757,8 +792,40 @@ class HTTP_WebDAV_Server
|
||||
. gmdate("D, d M Y H:i:s ", $prop['val'])
|
||||
. "GMT</D:getlastmodified>\n";
|
||||
break;
|
||||
/* @Todo: breaks CalDAV - 2010/03/01 jlehrke
|
||||
case "resourcetype":
|
||||
if (!is_array($prop['val'])) {
|
||||
echo ' <D:resourcetype><D:'.$prop['val']."/></D:resourcetype>\n";
|
||||
} else { // multiple resourcetypes from different namespaces as required by GroupDAV
|
||||
$vals = $extra_ns = '';
|
||||
foreach($prop['val'] as $subprop)
|
||||
{
|
||||
if ($subprop['ns'] && $subprop['ns'] != 'DAV:') {
|
||||
// register property namespace if not known yet
|
||||
if (!isset($ns_hash[$subprop['ns']])) {
|
||||
$ns_name = "ns".(count($ns_hash) + 1);
|
||||
$ns_hash[$subprop['ns']] = $ns_name;
|
||||
} else {
|
||||
$ns_name = $ns_hash[$subprop['ns']];
|
||||
}
|
||||
if (strchr($extra_ns,$extra=' xmlns:'.$ns_name.'="'.$subprop['ns'].'"') === false) {
|
||||
$extra_ns .= $extra;
|
||||
}
|
||||
$ns_name .= ':';
|
||||
} elseif ($subprop['ns'] == 'DAV:') {
|
||||
$ns_name = 'D:';
|
||||
} else {
|
||||
$ns_name = '';
|
||||
}
|
||||
$vals .= "<$ns_name$subprop[val]/>";
|
||||
}
|
||||
echo " <D:resourcetype$extra_ns>$vals</D:resourcetype>\n";
|
||||
//error_log("resourcetype: <D:resourcetype$extra_ns>$vals</D:resourcetype>");
|
||||
}
|
||||
break;
|
||||
*/
|
||||
case "supportedlock":
|
||||
echo " <D:supportedlock>$prop[val]</D:supportedlock>\n";
|
||||
echo " <D:supportedlock>$prop[val]</D:supportedlock>\n";
|
||||
break;
|
||||
case "lockdiscovery":
|
||||
echo " <D:lockdiscovery>\n";
|
||||
@ -768,7 +835,7 @@ class HTTP_WebDAV_Server
|
||||
default:
|
||||
echo " <D:$prop[name]>".
|
||||
(is_array($prop['val']) ?
|
||||
$this->_hierarchical_prop_encode($prop['val']) :
|
||||
$this->_hierarchical_prop_encode($prop['val']) :
|
||||
$this->_prop_encode(htmlspecialchars($prop['val']))).
|
||||
"</D:$prop[name]>\n";
|
||||
break;
|
||||
@ -829,10 +896,12 @@ class HTTP_WebDAV_Server
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo " </D:prop>\n";
|
||||
echo " <D:status>HTTP/1.1 200 OK</D:status>\n";
|
||||
echo " </D:propstat>\n";
|
||||
if ($propinfo->root['name'] != 'principal-search-property-set')
|
||||
{
|
||||
echo " </D:prop>\n";
|
||||
echo " <D:status>HTTP/1.1 200 OK</D:status>\n";
|
||||
echo " </D:propstat>\n";
|
||||
}
|
||||
}
|
||||
|
||||
// now report all properties requested but not found
|
||||
@ -855,10 +924,18 @@ class HTTP_WebDAV_Server
|
||||
echo " </D:propstat>\n";
|
||||
}
|
||||
|
||||
echo " </D:response>\n";
|
||||
if ($propinfo->root['name'] != 'principal-search-property-set') echo " </D:response>\n";
|
||||
}
|
||||
|
||||
if ($propinfo->root['name'] == 'principal-search-property-set')
|
||||
{
|
||||
echo "</D:principal-search-property-set>\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "</D:multistatus>\n";
|
||||
}
|
||||
|
||||
echo "</D:multistatus>\n";
|
||||
}
|
||||
|
||||
|
||||
@ -1550,6 +1627,49 @@ class HTTP_WebDAV_Server
|
||||
|
||||
// }}}
|
||||
|
||||
// {{{ http_UNLOCK()
|
||||
|
||||
/**
|
||||
* ACL method handler
|
||||
*
|
||||
* @param void
|
||||
* @return void
|
||||
*/
|
||||
function http_ACL()
|
||||
{
|
||||
$options = Array();
|
||||
$options['path'] = $this->path;
|
||||
$options['errors'] = array();
|
||||
|
||||
if (isset($this->_SERVER['HTTP_DEPTH'])) {
|
||||
$options['depth'] = $this->_SERVER['HTTP_DEPTH'];
|
||||
} else {
|
||||
$options['depth'] = 'infinity';
|
||||
}
|
||||
|
||||
// call user method
|
||||
$status = $this->ACL($options);
|
||||
|
||||
// now we generate the reply header ...
|
||||
$this->http_status($status);
|
||||
$content = '';
|
||||
|
||||
if (is_array($options['errors']) && count($options['errors'])) {
|
||||
header('Content-Type: text/xml; charset="utf-8"');
|
||||
// ... and payload
|
||||
$content .= "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
|
||||
$content .= "<D:error xmlns:D=\"DAV:\"> \n";
|
||||
foreach ($options['errors'] as $violation) {
|
||||
$content .= "<D:$violation/>\n";
|
||||
}
|
||||
$content .= "</D:error>\n";
|
||||
}
|
||||
header("Content-length: ".$this->bytes($content));
|
||||
if ($content) echo $options['content'];
|
||||
}
|
||||
|
||||
// }}}
|
||||
|
||||
// }}}
|
||||
|
||||
// {{{ _copymove()
|
||||
@ -2087,7 +2207,7 @@ class HTTP_WebDAV_Server
|
||||
|
||||
/**
|
||||
* Encode a hierarchical properties like:
|
||||
*
|
||||
*
|
||||
* <D:supported-report-set>
|
||||
* <supported-report>
|
||||
* <report>
|
||||
@ -2100,7 +2220,7 @@ class HTTP_WebDAV_Server
|
||||
* </report>
|
||||
* </supported-report>
|
||||
* </D:supported-report-set>
|
||||
*
|
||||
*
|
||||
* @param array $props
|
||||
* @return string
|
||||
*/
|
||||
@ -2108,14 +2228,14 @@ class HTTP_WebDAV_Server
|
||||
{
|
||||
//error_log(__METHOD__.'('.array2string($props).')');
|
||||
if (isset($props['name'])) $props = array($props);
|
||||
|
||||
|
||||
$ret = '';
|
||||
foreach($props as $prop)
|
||||
{
|
||||
$ret .= '<'.$prop['name'].
|
||||
($prop['ns'] != 'DAV:' ? ' xmlns="'.$prop['ns'].'"' : '').
|
||||
(empty($prop['val']) ? ' />' : '>'.
|
||||
(is_array($prop['val']) ?
|
||||
(is_array($prop['val']) ?
|
||||
$this->_hierarchical_prop_encode($prop['val']) :
|
||||
$this->_prop_encode($prop['val'])).
|
||||
'</'.$prop['name'].'>');
|
||||
|
@ -837,7 +837,8 @@ class infolog_bo
|
||||
function &search(&$query)
|
||||
{
|
||||
//echo "<p>boinfolog::search(".print_r($query,True).")</p>\n";
|
||||
if (!empty($query['start']))
|
||||
if (!empty($query['start']) &&
|
||||
(!isset($query['date_format']) || $query['date_format'] != 'server'))
|
||||
{
|
||||
$query['start'] -= $this->tz_offset_s;
|
||||
}
|
||||
@ -864,7 +865,8 @@ class infolog_bo
|
||||
date('Y', $data['info_enddate']));
|
||||
}
|
||||
|
||||
if ($this->tz_offset_s)
|
||||
if ($this->tz_offset_s &&
|
||||
(!isset($query['date_format']) || $query['date_format'] != 'server'))
|
||||
{
|
||||
// convert system- to user-time
|
||||
foreach ($this->timestamps as $time)
|
||||
@ -875,9 +877,14 @@ class infolog_bo
|
||||
$data[$time] += $this->tz_offset_s;
|
||||
}
|
||||
}
|
||||
// pre-cache title and file access
|
||||
self::set_link_cache($data);
|
||||
}
|
||||
elseif (!$this->tz_offset_s)
|
||||
{
|
||||
// pre-cache title and file access
|
||||
self::set_link_cache($data);
|
||||
}
|
||||
// pre-cache title and file access
|
||||
self::set_link_cache($data);
|
||||
}
|
||||
}
|
||||
//echo "<p>boinfolog::search(".print_r($query,True).")=<pre>".print_r($ret,True)."</pre>\n";
|
||||
|
@ -29,10 +29,11 @@ class infolog_groupdav extends groupdav_handler
|
||||
* @param string $app 'calendar', 'addressbook' or 'infolog'
|
||||
* @param int $debug=null debug-level to set
|
||||
* @param string $base_uri=null base url of handler
|
||||
* @param string $principalURL=null pricipal url of handler
|
||||
*/
|
||||
function __construct($app,$debug=null,$base_uri=null)
|
||||
function __construct($app,$debug=null,$base_uri=null,$principalURL=null)
|
||||
{
|
||||
parent::__construct($app,$debug,$base_uri);
|
||||
parent::__construct($app,$debug,$base_uri,$principalURL);
|
||||
|
||||
$this->bo = new infolog_bo();
|
||||
}
|
||||
@ -72,6 +73,42 @@ class infolog_groupdav extends groupdav_handler
|
||||
{
|
||||
$starttime = microtime(true);
|
||||
|
||||
if ($options['filters'])
|
||||
{
|
||||
|
||||
foreach($options['filters'] as $filter)
|
||||
{
|
||||
switch($filter['name'])
|
||||
{
|
||||
case 'comp-filter':
|
||||
if ($this->debug > 1) error_log(__METHOD__."($options[path],...) comp-filter='{$filter['attrs']['name']}'");
|
||||
|
||||
switch($filter['attrs']['name'])
|
||||
{
|
||||
case 'VCALENDAR':
|
||||
continue;
|
||||
case 'VTODO':
|
||||
break 3;
|
||||
default: // We don't handle this
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if we have to return the full calendar data or just the etag's
|
||||
if (!($calendar_data = $options['props'] == 'all' && $options['root']['ns'] == groupdav::CALDAV) && is_array($options['props']))
|
||||
{
|
||||
foreach($options['props'] as $prop)
|
||||
{
|
||||
if ($prop['name'] == 'calendar-data')
|
||||
{
|
||||
$calendar_data = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// todo add a filter to limit how far back entries from the past get synced
|
||||
$filter = array(
|
||||
'info_type' => 'task',
|
||||
@ -84,21 +121,35 @@ class infolog_groupdav extends groupdav_handler
|
||||
'sort' => 'DESC',
|
||||
'filter' => 'own', // filter my: entries user is responsible for,
|
||||
// filter own: entries the user own or is responsible for
|
||||
'date_format' => 'server',
|
||||
'col_filter' => $filter,
|
||||
))))
|
||||
{
|
||||
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!
|
||||
HTTP_WebDAV_Server::mkprop('getcontentlength',''),
|
||||
);
|
||||
if ($calendar_data)
|
||||
{
|
||||
$handler = $this->_get_handler();
|
||||
$content = $handler->exportVTODO($task,'2.0','PUBLISH');
|
||||
$props[] = HTTP_WebDAV_Server::mkprop('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['files'][] = array(
|
||||
'path' => self::get_path($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('getcontentlength',''),
|
||||
),
|
||||
'props' => $props,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -120,7 +171,7 @@ class infolog_groupdav extends groupdav_handler
|
||||
return $task;
|
||||
}
|
||||
$handler = $this->_get_handler();
|
||||
$options['data'] = $handler->exportVTODO($id,'2.0',false,false); // keep UID the client set and no extra charset attributes
|
||||
$options['data'] = $handler->exportVTODO($id,'2.0','PUBLISH');
|
||||
$options['mimetype'] = 'text/calendar; charset=utf-8';
|
||||
header('Content-Encoding: identity');
|
||||
header('ETag: '.$this->get_etag($task));
|
||||
@ -215,6 +266,36 @@ class infolog_groupdav extends groupdav_handler
|
||||
return '"'.$info['info_id'].':'.$info['info_datemodified'].'"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add extra properties for calendar collections
|
||||
*
|
||||
* @param array $props=array() regular props by the groupdav handler
|
||||
* @param string $base_uri=null base url of handler
|
||||
* @return array
|
||||
*/
|
||||
static function extra_properties(array $props=array(), $base_uri=null)
|
||||
{
|
||||
// calendar description
|
||||
$displayname = $GLOBALS['egw']->translation->convert(lang('Tasks of') . ' ' .
|
||||
$GLOBALS['egw_info']['user']['account_fullname'],
|
||||
$GLOBALS['egw']->translation->charset(),'utf-8');
|
||||
$props[] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-description',$displayname);
|
||||
// email of the current user, see caldav-sheduling draft
|
||||
$props[] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-user-address-set','MAILTO:'.$GLOBALS['egw_info']['user']['email']);
|
||||
// supported components, currently only VEVENT
|
||||
$props[] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'supported-calendar-component-set',array(
|
||||
// HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'comp',array('name' => 'VEVENT')),
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'comp',array('name' => 'VTODO')),
|
||||
));
|
||||
/*
|
||||
$props[] = HTTP_WebDAV_Server::mkprop('supported-report-set',array(
|
||||
HTTP_WebDAV_Server::mkprop('supported-report',array(
|
||||
HTTP_WebDAV_Server::mkprop('report',
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-multiget'))))));
|
||||
*/
|
||||
return $props;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the handler and set the supported fields
|
||||
*
|
||||
|
@ -111,12 +111,12 @@ class infolog_ical extends infolog_bo
|
||||
/**
|
||||
* Exports one InfoLog tast to an iCalendar VTODO
|
||||
*
|
||||
* @param int $_taskID info_id
|
||||
* @param int|array $task infolog_id or infolog-tasks data
|
||||
* @param string $_version='2.0' could be '1.0' too
|
||||
* @param string $_method='PUBLISH'
|
||||
* @return string/boolean string with vCal or false on error (eg. no permission to read the event)
|
||||
*/
|
||||
function exportVTODO($_taskID, $_version='2.0',$_method='PUBLISH')
|
||||
function exportVTODO($task, $_version='2.0',$_method='PUBLISH')
|
||||
{
|
||||
if ($this->useServerTZ)
|
||||
{
|
||||
@ -126,7 +126,14 @@ class infolog_ical extends infolog_bo
|
||||
{
|
||||
$date_format = 'ts';
|
||||
}
|
||||
if (!($taskData = $this->read($_taskID, true, $date_format))) return false;
|
||||
if (is_array($task))
|
||||
{
|
||||
$taskData = $task;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!($taskData = $this->read($task, true, $date_format))) return false;
|
||||
}
|
||||
|
||||
if ($taskData['info_id_parent'])
|
||||
{
|
||||
|
@ -70,7 +70,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
'component-set' => array(self::GROUPDAV => 'VCARD'),
|
||||
),
|
||||
'infolog' => array(
|
||||
'resourcetype' => array(self::GROUPDAV => 'vtodo-collection'),
|
||||
'resourcetype' => array(self::GROUPDAV => 'vtodo-collection', self::CALDAV => 'calendar'),
|
||||
'component-set' => array(self::GROUPDAV => 'VTODO'),
|
||||
),
|
||||
);
|
||||
@ -101,6 +101,13 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
* @var groupdav_handler
|
||||
*/
|
||||
var $handler;
|
||||
/**
|
||||
* principal URL
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
var $principalURL;
|
||||
|
||||
|
||||
function __construct()
|
||||
{
|
||||
@ -120,6 +127,15 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
|
||||
$this->translation =& $GLOBALS['egw']->translation;
|
||||
$this->egw_charset = $this->translation->charset();
|
||||
if (strpos($this->base_uri, 'http') === 0)
|
||||
{
|
||||
$this->principalURL = $this->_slashify($this->base_uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->principalURL = (@$_SERVER["HTTPS"] === "on" ? "https:" : "http:") .
|
||||
'//' . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'] . '/';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,7 +146,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
*/
|
||||
function app_handler($app)
|
||||
{
|
||||
return groupdav_handler::app_handler($app,$this->debug,$this->base_uri);
|
||||
return groupdav_handler::app_handler($app,$this->debug,$this->base_uri,$this->principalURL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -146,6 +162,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
switch($app)
|
||||
{
|
||||
case 'calendar':
|
||||
case 'infolog':
|
||||
$dav[] = 'calendar-access';
|
||||
break;
|
||||
case 'addressbook':
|
||||
@ -178,15 +195,26 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
|
||||
if (!$app) // root folder containing apps
|
||||
{
|
||||
if (empty($user_prefix))
|
||||
{
|
||||
$displayname = 'EGroupware (Cal|Card|Group)DAV server';
|
||||
}
|
||||
else
|
||||
{
|
||||
$displayname = $this->translation->convert($GLOBALS['egw_info']['user']['account_fullname'],$this->egw_charset,'utf-8');
|
||||
}
|
||||
// self url
|
||||
$files['files'][] = array(
|
||||
'path' => $user_prefix.'/',
|
||||
'props' => array(
|
||||
self::mkprop('displayname','EGroupware (Cal|Card|Group)DAV server'),
|
||||
self::mkprop('displayname',$displayname),
|
||||
self::mkprop('resourcetype','collection'),
|
||||
// adding the calendar extra property (calendar-home-set, etc.) here, allows apple iCal to "autodetect" the URL
|
||||
self::mkprop(groupdav::CALDAV,'calendar-home-set',$this->base_uri.'/calendar/'),
|
||||
self::mkprop('current-user-principal',array(self::mkprop('href',$this->base_uri.'/principals/'.$GLOBALS['egw_info']['user']['account_lid'].'/'))),
|
||||
self::mkprop(groupdav::CALDAV,'calendar-home-set',array(self::mkprop('href',$this->base_uri.'/calendar/'))),
|
||||
self::mkprop('current-user-principal',array(self::mkprop('href',$this->principalURL))),
|
||||
self::mkprop(groupdav::CALDAV,'calendar-user-address-set','MAILTO:'.$GLOBALS['egw_info']['user']['email']),
|
||||
//self::mkprop('principal-URL',array(self::mkprop('href',$this->principalURL))),
|
||||
//self::mkprop('principal-collection-set',array(self::mkprop('href',$this->base_uri.'/principals/'))),
|
||||
),
|
||||
);
|
||||
if ($options['depth'])
|
||||
@ -197,18 +225,22 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
$files['files'][] = array(
|
||||
'path' => '/principals/',
|
||||
'props' => array(
|
||||
self::mkprop('displayname',lang('Accounts')),
|
||||
self::mkprop('resourcetype','collection'),
|
||||
self::mkprop('current-user-principal',array(self::mkprop('href',$this->base_uri.'/principals/'.$GLOBALS['egw_info']['user']['account_lid'].'/'))),
|
||||
),
|
||||
);
|
||||
self::mkprop('displayname',lang('Accounts')),
|
||||
self::mkprop('resourcetype','collection'),
|
||||
self::mkprop('current-user-principal',array(self::mkprop('href',$this->principalURL))),
|
||||
self::mkprop(groupdav::CALDAV,'calendar-home-set',array(self::mkprop('href',$this->base_uri.'/calendar/'))),
|
||||
//self::mkprop('principal-URL',array(self::mkprop('href',$this->principalURL))),
|
||||
),
|
||||
);
|
||||
// groups collection
|
||||
$files['files'][] = array(
|
||||
'path' => '/groups/',
|
||||
'props' => array(
|
||||
self::mkprop('displayname',lang('Groups')),
|
||||
self::mkprop('resourcetype','collection'),
|
||||
self::mkprop('current-user-principal',array(self::mkprop('href',$this->base_uri.'/principals/'.$GLOBALS['egw_info']['user']['account_lid'].'/'))),
|
||||
self::mkprop('current-user-principal',array(self::mkprop('href',$this->principalURL))),
|
||||
self::mkprop(groupdav::CALDAV,'calendar-home-set',array(self::mkprop('href',$this->base_uri.'/calendar/'))),
|
||||
//self::mkprop('principal-URL',array(self::mkprop('href',$this->principalURL))),
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -239,7 +271,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
'props' => $this->_properties($app,$app=='addressbook'&&strpos($_SERVER['HTTP_USER_AGENT'],'KHTML') !== false),
|
||||
);
|
||||
}
|
||||
if (!$options['depth'] && !$id)
|
||||
if (isset($options['depth']) && !$options['depth'] && !$id)
|
||||
{
|
||||
// add ctag if handler implements it (only for depth 0)
|
||||
if (method_exists($handler,'getctag'))
|
||||
@ -265,11 +297,26 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
function _properties($app,$no_extra_types=false,$user=null)
|
||||
{
|
||||
if (!$user) $user = $GLOBALS['egw_info']['user']['account_fullname'];
|
||||
|
||||
$displayname = $this->translation->convert($GLOBALS['egw_info']['user']['account_fullname'],$this->egw_charset,'utf-8');
|
||||
$props = array(
|
||||
self::mkprop('displayname',$this->translation->convert(lang($app).' '.common::grab_owner_name($user),$this->egw_charset,'utf-8')),
|
||||
self::mkprop('current-user-principal',array(self::mkprop('href',$this->base_uri.'/principals/'.$GLOBALS['egw_info']['user']['account_lid'].'/'))),
|
||||
);
|
||||
self::mkprop('current-user-principal',array(self::mkprop('href',$this->principalURL))),
|
||||
self::mkprop('owner',$displayname),
|
||||
//self::mkprop('principal-URL',array(self::mkprop('href',$this->principalURL))),
|
||||
//self::mkprop('principal-collection-set',array(self::mkprop('href',$this->base_uri.'/principals/'))),
|
||||
);
|
||||
|
||||
switch ($app)
|
||||
{
|
||||
case 'calendar':
|
||||
$props[] = self::mkprop(groupdav::CALDAV,'calendar-home-set',array(self::mkprop('href',$this->base_uri.'/calendar/')));
|
||||
break;
|
||||
case 'infolog':
|
||||
$props[] = self::mkprop(groupdav::CALDAV,'calendar-home-set',array(self::mkprop('href',$this->base_uri.'/infolog/')));
|
||||
default:
|
||||
$displayname = $this->translation->convert(lang($app).' '.common::grab_owner_name($user),$this->egw_charset,'utf-8');
|
||||
}
|
||||
$props[] = self::mkprop('displayname',$displayname);
|
||||
|
||||
foreach((array)$this->root[$app] as $prop => $values)
|
||||
{
|
||||
if ($prop == 'resourcetype')
|
||||
@ -296,7 +343,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
}
|
||||
if (method_exists($app.'_groupdav','extra_properties'))
|
||||
{
|
||||
$props = ExecMethod($app.'_groupdav::extra_properties',$props);
|
||||
$props = ExecMethod2($app.'_groupdav::extra_properties',$props,$this->base_uri);
|
||||
}
|
||||
return $props;
|
||||
}
|
||||
@ -664,6 +711,34 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
return egw_vfs::checkLock($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* ACL method handler
|
||||
*
|
||||
* @param array general parameter passing array
|
||||
* @return string HTTP status
|
||||
*/
|
||||
function ACL(&$options)
|
||||
{
|
||||
self::_parse_path($options['path'],$id,$app,$user);
|
||||
|
||||
if ($this->debug) error_log(__METHOD__.'('.array2string($options).") path=$path");
|
||||
|
||||
$options['errors'] = array();
|
||||
switch ($app)
|
||||
{
|
||||
case 'calendar':
|
||||
case 'addressbook':
|
||||
case 'infolog':
|
||||
$status = '200 OK'; // grant all
|
||||
break;
|
||||
default:
|
||||
$options['errors'][] = 'no-inherited-ace-conflict';
|
||||
$status = '403 Forbidden';
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a path into it's id, app and user parts
|
||||
*
|
||||
|
@ -29,10 +29,11 @@ class groupdav_groups extends groupdav_handler
|
||||
* @param string $app 'calendar', 'addressbook' or 'infolog'
|
||||
* @param int $debug=null debug-level to set
|
||||
* @param string $base_uri=null base url of handler
|
||||
* @param string $principalURL=null pricipal url of handler
|
||||
*/
|
||||
function __construct($app,$debug=null,$base_uri=null)
|
||||
function __construct($app,$debug=null,$base_uri=null,$principalURL=null)
|
||||
{
|
||||
parent::__construct($app,$debug,$base_uri);
|
||||
parent::__construct($app,$debug,$base_uri,$principalURL);
|
||||
|
||||
$this->accounts = $GLOBALS['egw']->accounts;
|
||||
}
|
||||
@ -56,8 +57,8 @@ class groupdav_groups extends groupdav_handler
|
||||
HTTP_WebDAV_Server::mkprop('getetag',$this->get_etag($account)),
|
||||
HTTP_WebDAV_Server::mkprop('resourcetype','principal'),
|
||||
HTTP_WebDAV_Server::mkprop('alternate-URI-set',''),
|
||||
HTTP_WebDAV_Server::mkprop('principal-URL',$this->base_uri.'/groups/'.$account['account_lid']),
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-home-set',$this->base_uri.'/calendar/'),
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-home-set',$this->base_uri.'/'.$account['account_lid'].'/calendar/'),
|
||||
//HTTP_WebDAV_Server::mkprop('principal-URL',array(self::mkprop('href',$this->principalURL))),
|
||||
);
|
||||
foreach($this->accounts->members($account['account_id']) as $uid => $user)
|
||||
{
|
||||
|
@ -59,6 +59,12 @@ abstract class groupdav_handler
|
||||
* @var string
|
||||
*/
|
||||
var $base_uri;
|
||||
/**
|
||||
* principal URL
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
var $principalURL;
|
||||
/**
|
||||
* HTTP_IF_MATCH / etag of current request / last call to _common_get_put_delete() method
|
||||
*
|
||||
@ -78,13 +84,24 @@ abstract class groupdav_handler
|
||||
* @param string $app 'calendar', 'addressbook' or 'infolog'
|
||||
* @param int $debug=null debug-level to set
|
||||
* @param string $base_uri=null base url of handler
|
||||
* @param string $principalURL=null pricipal url of handler
|
||||
*/
|
||||
function __construct($app,$debug=null,$base_uri=null)
|
||||
function __construct($app,$debug=null,$base_uri=null,$principalURL=null)
|
||||
{
|
||||
//error_log(__METHOD__." called");
|
||||
$this->app = $app;
|
||||
#if (!is_null($debug)) $this->debug = $debug = 3;
|
||||
if (!is_null($debug)) $this->debug = $debug;
|
||||
$this->base_uri = is_null($base_uri) ? $base_uri : $_SERVER['SCRIPT_NAME'];
|
||||
if (is_null($principalURL))
|
||||
{
|
||||
$this->principalURL = (@$_SERVER["HTTPS"] === "on" ? "https:" : "http:") .
|
||||
'//'.$_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'] . '/';
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->principalURL = $principalURL;
|
||||
}
|
||||
|
||||
$this->agent = self::get_agent();
|
||||
|
||||
$this->translation =& $GLOBALS['egw']->translation;
|
||||
@ -161,9 +178,10 @@ abstract class groupdav_handler
|
||||
* Add extra properties for collections
|
||||
*
|
||||
* @param array $props=array() regular props by the groupdav handler
|
||||
* @param string $base_uri=null base url of handler
|
||||
* @return array
|
||||
*/
|
||||
static function extra_properties(array $props=array())
|
||||
static function extra_properties(array $props=array(), $base_uri=null)
|
||||
{
|
||||
return $props;
|
||||
}
|
||||
@ -262,9 +280,10 @@ abstract class groupdav_handler
|
||||
* @param string $app 'calendar', 'addressbook' or 'infolog'
|
||||
* @param int $debug=null debug-level to set
|
||||
* @param string $base_uri=null base url of handler
|
||||
* @param string $principalURL=null pricipal url of handler
|
||||
* @return groupdav_handler
|
||||
*/
|
||||
static function &app_handler($app,$debug=null,$base_uri=null)
|
||||
static function &app_handler($app,$debug=null,$base_uri=null,$principalURL=null)
|
||||
{
|
||||
static $handler_cache = array();
|
||||
|
||||
@ -273,8 +292,12 @@ abstract class groupdav_handler
|
||||
$class = $app.'_groupdav';
|
||||
if (!class_exists($class) && !class_exists($class = 'groupdav_'.$app)) return null;
|
||||
|
||||
$handler_cache[$app] = new $class($app,$debug,$base_uri);
|
||||
$handler_cache[$app] = new $class($app,$debug,$base_uri,$principalURL);
|
||||
}
|
||||
$handler_cache[$app]->$debug = $debug;
|
||||
$handler_cache[$app]->$base_uri = $base_uri;
|
||||
$handler_cache[$app]->$principalURL = $principalURL;
|
||||
if ($debug) error_log(__METHOD__."($app, $base_uri, $principalURL)");
|
||||
return $handler_cache[$app];
|
||||
}
|
||||
|
||||
|
@ -29,10 +29,11 @@ class groupdav_principals extends groupdav_handler
|
||||
* @param string $app 'calendar', 'addressbook' or 'infolog'
|
||||
* @param int $debug=null debug-level to set
|
||||
* @param string $base_uri=null base url of handler
|
||||
* @param string $principalURL=null pricipal url of handler
|
||||
*/
|
||||
function __construct($app,$debug=null,$base_uri=null)
|
||||
function __construct($app,$debug=null,$base_uri=null,$principalURL=null)
|
||||
{
|
||||
parent::__construct($app,$debug,$base_uri);
|
||||
parent::__construct($app,$debug,$base_uri,$principalURL);
|
||||
|
||||
$this->accounts = $GLOBALS['egw']->accounts;
|
||||
}
|
||||
@ -48,25 +49,43 @@ class groupdav_principals extends groupdav_handler
|
||||
*/
|
||||
function propfind($path,$options,&$files,$user)
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."($path,".array2string($options).",,$user,$id)");
|
||||
|
||||
list(,,$id) = explode('/',$path);
|
||||
|
||||
if ($id && !($id = $this->accounts->id2name($id)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
foreach($id ? array($this->accounts->read($id)) : $this->accounts->search(array('type' => 'accounts')) as $account)
|
||||
{
|
||||
$props = array(
|
||||
HTTP_WebDAV_Server::mkprop('displayname',trim($account['account_firstname'].' '.$account['account_lastname'])),
|
||||
HTTP_WebDAV_Server::mkprop('getetag',$this->get_etag($account)),
|
||||
HTTP_WebDAV_Server::mkprop('resourcetype','principal'),
|
||||
HTTP_WebDAV_Server::mkprop('alternate-URI-set',''),
|
||||
HTTP_WebDAV_Server::mkprop('principal-URL',$_SERVER['SCRIPT_NAME'].'/principals/'.$account['account_lid']),
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-home-set',$_SERVER['SCRIPT_NAME'].'/'),
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-user-address-set','MAILTO:'.$account['account_email']),
|
||||
);
|
||||
foreach($this->accounts->memberships($account['account_id']) as $gid => $group)
|
||||
$displayname = $GLOBALS['egw']->translation->convert($account['account_fullname'],
|
||||
$GLOBALS['egw']->translation->charset(),'utf-8');
|
||||
if ($options['root']['name'] == 'principal-search-property-set')
|
||||
{
|
||||
$props[] = HTTP_WebDAV_Server::mkprop('group-membership',$_SERVER['SCRIPT_NAME'].'/groups/'.$group);
|
||||
$props = array(HTTP_WebDAV_Server::mkprop('principal-search-property',
|
||||
array(HTTP_WebDAV_Server::mkprop('prop',
|
||||
array(HTTP_WebDAV_Server::mkprop('displayname',$displayname))
|
||||
),
|
||||
HTTP_WebDAV_Server::mkprop('description', 'Full name')))
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$props = array(
|
||||
HTTP_WebDAV_Server::mkprop('displayname',$displayname),
|
||||
HTTP_WebDAV_Server::mkprop('getetag',$this->get_etag($account)),
|
||||
HTTP_WebDAV_Server::mkprop('resourcetype','principal'),
|
||||
HTTP_WebDAV_Server::mkprop('alternate-URI-set',''),
|
||||
HTTP_WebDAV_Server::mkprop('current-user-principal',array(HTTP_WebDAV_Server::mkprop('href',$this->principalURL))),
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-home-set',array(HTTP_WebDAV_Server::mkprop('href',$this->base_uri.'/'.$account['account_lid'].'/calendar/'))),
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-user-address-set','MAILTO:'.$account['account_email']),
|
||||
//HTTP_WebDAV_Server::mkprop('principal-URL',array(HTTP_WebDAV_Server::mkprop('href',$this->principalURL))),
|
||||
);
|
||||
foreach($this->accounts->memberships($account['account_id']) as $gid => $group)
|
||||
{
|
||||
$props[] = HTTP_WebDAV_Server::mkprop('group-membership',$this->base_uri.'/groups/'.$group);
|
||||
}
|
||||
}
|
||||
$files['files'][] = array(
|
||||
'path' => '/principals/'.$account['account_lid'],
|
||||
@ -90,9 +109,12 @@ class groupdav_principals extends groupdav_handler
|
||||
{
|
||||
return $account;
|
||||
}
|
||||
$displayname = $GLOBALS['egw']->translation->convert(
|
||||
trim($account['account_firstname'].' '.$account['account_lastname']),
|
||||
$GLOBALS['egw']->translation->charset(),'utf-8');
|
||||
$options['data'] = 'Principal: '.$account['account_lid'].
|
||||
"\nURL: ".$_SERVER['SCRIPT_NAME'].$options['path'].
|
||||
"\nName: ".$account['account_firstname'].' '.$account['account_lastname'].
|
||||
"\nURL: ".$this->base_uri.$options['path'].
|
||||
"\nName: ".$displayname.
|
||||
"\nEmail: ".$account['account_email'].
|
||||
"\nMemberships: ".implode(', ',$this->accounts->memberships($id))."\n";
|
||||
$options['mimetype'] = 'text/plain; charset=utf-8';
|
||||
|
Loading…
Reference in New Issue
Block a user