diff --git a/addressbook/inc/class.addressbook_groupdav.inc.php b/addressbook/inc/class.addressbook_groupdav.inc.php
index 66b054cef8..2f47a2256c 100644
--- a/addressbook/inc/class.addressbook_groupdav.inc.php
+++ b/addressbook/inc/class.addressbook_groupdav.inc.php
@@ -68,7 +68,7 @@ class addressbook_groupdav extends groupdav_handler
*/
static function get_path($contact)
{
- return '/addressbook/'.$contact[self::PATH_ATTRIBUTE].'.vcf';
+ return $contact[self::PATH_ATTRIBUTE].'.vcf';
}
/**
@@ -96,8 +96,9 @@ class addressbook_groupdav extends groupdav_handler
}
if ($this->debug) error_log(__METHOD__."($path,".array2string($options).",,$user,$id) filter=".array2string($filter));
- // check if we have to return the full calendar data or just the etag's
- if (!($filter['address_data'] = $options['props'] == 'all' && $options['root']['ns'] == groupdav::CARDDAV) && is_array($options['props']))
+ // check if we have to return the full contact data or just the etag's
+ if (!($filter['address_data'] = $options['props'] == 'all' &&
+ $options['root']['ns'] == groupdav::CARDDAV) && is_array($options['props']))
{
foreach($options['props'] as $prop)
{
@@ -109,7 +110,7 @@ class addressbook_groupdav extends groupdav_handler
}
}
// return iterator, calling ourself to return result in chunks
- $files['files'] = new groupdav_propfind_iterator($this,$filter,$files['files']);
+ $files['files'] = new groupdav_propfind_iterator($this,$path,$filter,$files['files']);
return true;
}
@@ -117,11 +118,12 @@ class addressbook_groupdav extends groupdav_handler
/**
* Callback for profind interator
*
+ * @param string $path
* @param array $filter
* @param array|boolean $start=false false=return all or array(start,num)
* @return array with "files" array with values for keys path and props
*/
- function &propfind_callback(array $filter,$start=false)
+ function &propfind_callback($path,array $filter,$start=false)
{
$starttime = microtime(true);
@@ -139,7 +141,7 @@ class addressbook_groupdav extends groupdav_handler
{
$props = array(
HTTP_WebDAV_Server::mkprop('getetag',$this->get_etag($contact)),
- HTTP_WebDAV_Server::mkprop('getcontenttype', 'text/x-vcard'),
+ 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']),
);
@@ -147,19 +149,19 @@ class addressbook_groupdav extends groupdav_handler
{
$content = $handler->getVCard($contact,$this->charset,false);
$props[] = HTTP_WebDAV_Server::mkprop('getcontentlength',bytes($content));
- $props[] = HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'address-data',$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' => self::get_path($contact),
+ 'path' => $path.self::get_path($contact),
'props' => $props,
);
}
}
- if ($this->debug) error_log(__METHOD__.'('.array2string($filter).','.array2string($start).") took ".(microtime(true) - $starttime).' to return '.count($files).' items');
+ if ($this->debug) error_log(__METHOD__."($path,".array2string($filter).','.array2string($start).") took ".(microtime(true) - $starttime).' to return '.count($files).' items');
return $files;
}
@@ -266,14 +268,24 @@ class addressbook_groupdav extends groupdav_handler
*/
function put(&$options,$id,$user=null)
{
+ if ($this->debug) error_log(__METHOD__.'('.array2string($options).",$id,$user)");
$ok = $this->_common_get_put_delete('PUT',$options,$id);
if (!is_null($ok) && !is_array($ok))
{
return $ok;
}
$handler = self::_get_handler();
- $contact = $handler->vcardtoegw($options['content']);
-
+ $vCard = htmlspecialchars_decode($options['content']);
+ $contactId = (is_array($ok) ? -1 : $ok['id']);
+ $contact = $handler->vcardtoegw($vCard, $contactId);
+ if (is_array($contact['category']))
+ {
+ $contact['category'] = implode(',',$this->bo->find_or_add_categories($contact['category'], $contactId));
+ }
+ elseif ($contactId > 0)
+ {
+ $contact['category'] = $ok['category'];
+ }
if (!is_null($ok))
{
$contact['id'] = $ok['id'];
@@ -282,6 +294,10 @@ class addressbook_groupdav extends groupdav_handler
$contact['owner'] = $ok['owner'];
$contact['private'] = $ok['private'];
}
+ else
+ {
+ $contact['owner'] = $user;
+ }
if ($this->http_if_match) $contact['etag'] = self::etag2value($this->http_if_match);
if (!($save_ok = $this->bo->save($contact)))
@@ -295,13 +311,14 @@ class addressbook_groupdav extends groupdav_handler
}
if (!isset($contact['etag']))
{
- $contact = $this->read($contact['id']);
+ $contact = $this->read($save_ok);
}
header('ETag: '.$this->get_etag($contact));
if (is_null($ok))
{
- header($h='Location: '.$this->base_uri.self::get_path($contact));
+ $path = preg_replace('|(.*)/[^/]*|', '\1/', $options['path']);
+ header($h='Location: '.$path.self::get_path($contact));
if ($this->debug) error_log(__METHOD__."($method,,$id) header('$h'): 201 Created");
return '201 Created';
}
@@ -323,7 +340,37 @@ class addressbook_groupdav extends groupdav_handler
$result = $this->bo->search(array(),'MAX(contact_modified) AS contact_modified','','','','','',$filter);
- return '"'.$result[0]['modified'].'"';
+ $ctag = 'EGw-'.$result[0]['modified'].'-wGE';
+ return $ctag;
+ }
+
+ /**
+ * Add the privileges of the current user
+ *
+ * @param array $props=array() regular props by the groupdav handler
+ * @return array
+ */
+ static function current_user_privilege_set(array $props=array())
+ {
+ $props[] = HTTP_WebDAV_Server::mkprop(groupdav::DAV,'current-user-privilege-set',
+ array(HTTP_WebDAV_Server::mkprop(groupdav::DAV,'privilege',
+ array(//HTTP_WebDAV_Server::mkprop(groupdav::DAV,'all',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'read',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'read-free-busy',''),
+ //HTTP_WebDAV_Server::mkprop(groupdav::DAV,'read-current-user-privilege-set',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'bind',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'unbind',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'schedule-post',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'schedule-post-vevent',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'schedule-respond',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'schedule-respond-vevent',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'schedule-deliver',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'schedule-deliver-vevent',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'write',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'write-properties',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'write-content',''),
+ ))));
+ return $props;
}
/**
@@ -345,11 +392,17 @@ class addressbook_groupdav extends groupdav_handler
* @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 $displayname
* @param string $base_uri=null base url of handler
* @return array
*/
- static function extra_properties(array $props=array(), $base_uri=null)
+ static function extra_properties(array $props=array(), $displayname, $base_uri=null)
{
+ // addressbook description
+ $displayname = $GLOBALS['egw']->translation->convert(lang('Addressbook of') . ' ' .
+ $displayname,
+ $GLOBALS['egw']->translation->charset(),'utf-8');
+ $props[] = HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'addressbook-description',$displayname);
// supported reports (required property for CardDAV)
$props[] = HTTP_WebDAV_Server::mkprop('supported-report-set',array(
HTTP_WebDAV_Server::mkprop('supported-report',array(
@@ -359,6 +412,7 @@ class addressbook_groupdav extends groupdav_handler
HTTP_WebDAV_Server::mkprop('report',
HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'addressbook-multiget','')))),
));
+ //$props = self::current_user_privilege_set($props);
return $props;
}
@@ -392,7 +446,7 @@ class addressbook_groupdav extends groupdav_handler
{
return '412 Precondition Failed';
}
- return $ok;
+ //return $ok;
}
/**
diff --git a/addressbook/inc/class.addressbook_so.inc.php b/addressbook/inc/class.addressbook_so.inc.php
index 8eb0713c3e..42c6fe13cc 100755
--- a/addressbook/inc/class.addressbook_so.inc.php
+++ b/addressbook/inc/class.addressbook_so.inc.php
@@ -526,8 +526,8 @@ class addressbook_so
/**
* reads contact data including custom fields
*
- * @param int/string $contact_id contact_id or 'a'.account_id
- * @return array/boolean data if row could be retrived else False
+ * @param int|string $contact_id contact_id or 'a'.account_id
+ * @return array|boolean data if row could be retrived else False
*/
function read($contact_id)
{
diff --git a/addressbook/inc/class.addressbook_vcal.inc.php b/addressbook/inc/class.addressbook_vcal.inc.php
index c180240c71..bf2b48cb2f 100644
--- a/addressbook/inc/class.addressbook_vcal.inc.php
+++ b/addressbook/inc/class.addressbook_vcal.inc.php
@@ -123,7 +123,7 @@ class addressbook_vcal extends addressbook_bo
*/
function addVCard($_vcard, $_abID=null, $merge=false)
{
- if (!$contact = $this->vcardtoegw($_vcard, $_abID))
+ if (!$contact = $this->vcardtoegw($_vcard))
{
return false;
}
@@ -148,6 +148,15 @@ class addressbook_vcal extends addressbook_bo
{
$contact['account_id'] = $old_contact['account_id'];
}
+ if (is_array($contact['category']))
+ {
+ $contact['category'] = implode(',',$this->find_or_add_categories($contact['category'], $_abID));
+ }
+ else
+ {
+ // restore from orignal
+ $contact['category'] = $old_contact['category'];
+ }
}
}
// update entry
@@ -160,6 +169,10 @@ class addressbook_vcal extends addressbook_bo
{
$contact['owner'] = $GLOBALS['egw_info']['user']['account_primary_group'];
}
+ if (is_array($contact['category']))
+ {
+ $contact['category'] = implode(',',$this->find_or_add_categories($contact['category'], -1));
+ }
}
return $this->save($contact);
}
@@ -455,8 +468,13 @@ class addressbook_vcal extends addressbook_bo
{
$result = array();
- if (($contact = $this->vcardtoegw($_vcard, $contentID)))
+ if (($contact = $this->vcardtoegw($_vcard)))
{
+ if (is_array($contact['category']))
+ {
+ $contact['category'] = implode(',',$this->find_or_add_categories($contact['category'],
+ $contentID ? $contentID : -1));
+ }
if ($contentID)
{
$contact['id'] = $contentID;
@@ -475,7 +493,7 @@ class addressbook_vcal extends addressbook_bo
if (is_array($_supportedFields)) $this->supportedFields = $_supportedFields;
}
- function vcardtoegw($_vcard, $_abID=null)
+ function vcardtoegw($_vcard)
{
// the horde class does the charset conversion. DO NOT CONVERT HERE.
// be as flexible as possible
@@ -889,7 +907,7 @@ class addressbook_vcal extends addressbook_bo
break;
case 'cat_id':
- $contact[$fieldName] = implode(',',$this->find_or_add_categories($vcardValues[$vcardKey]['values'], $_abID));
+ $contact[$fieldName] = $vcardValues[$vcardKey]['values'];
break;
case 'jpegphoto':
diff --git a/calendar/inc/class.calendar_groupdav.inc.php b/calendar/inc/class.calendar_groupdav.inc.php
index faf5dfa574..cd27414acf 100644
--- a/calendar/inc/class.calendar_groupdav.inc.php
+++ b/calendar/inc/class.calendar_groupdav.inc.php
@@ -23,8 +23,6 @@ class calendar_groupdav extends groupdav_handler
*/
var $bo;
- const DAV = 'DAV:';
-
var $filter_prop2cal = array(
'SUMMARY' => 'cal_title',
'UID' => 'cal_uid',
@@ -86,7 +84,7 @@ class calendar_groupdav extends groupdav_handler
if (!is_array($event)) $event = $this->bo->read($event);
$name = $event[self::PATH_ATTRIBUTE];
}
- return '/calendar/'.$name.'.ics';
+ return $name.'.ics';
}
/**
@@ -191,7 +189,7 @@ class calendar_groupdav extends groupdav_handler
$props[] = HTTP_WebDAV_Server::mkprop('getcontentlength', ''); // expensive to calculate and no CalDAV client uses it
}
$files['files'][] = array(
- 'path' => self::get_path($event),
+ 'path' => $path.self::get_path($event),
'props' => $props,
);
}
@@ -447,12 +445,19 @@ class calendar_groupdav extends groupdav_handler
if ($this->debug) error_log(__METHOD__.print_r($event,true).function_backtrace());
return $event;
}
- $handler = $this->_get_handler();
+ if (is_null($event) && !$this->bo->check_perms(EGW_ACL_ADD, 0, $user))
+ {
+ // we have not permission on this user's calendar
+ if ($this->debug) error_log(__METHOD__."(,$user) we have not enough rights on this calendar");
+ return '403 Forbidden';
+ }
+
+ $handler = $this->_get_handler();
$vCalendar = htmlspecialchars_decode($options['content']);
if (!($cal_id = $handler->importVCal($vCalendar, is_numeric($id) ? $id : -1,
- self::etag2value($this->http_if_match), false, 0, $this->principalURL)))
+ self::etag2value($this->http_if_match), false, 0, $this->principalURL, $user)))
{
if ($this->debug) error_log(__METHOD__."(,$id) importVCal($options[content]) returned false");
return '403 Forbidden';
@@ -461,15 +466,11 @@ class calendar_groupdav extends groupdav_handler
header('ETag: '.$this->get_etag($cal_id));
if (is_null($event) || !$return_no_access) // let lightning think the event is added
{
+ $path = preg_replace('|(.*)/[^/]*|', '\1/', $options['path']);
if ($this->debug) error_log(__METHOD__."(,$id,$user) cal_id=$cal_id, is_null(\$event)=".(int)is_null($event));
- header('Location: '.$this->base_uri.self::get_path($cal_id));
+ header('Location: '.$path.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;
}
@@ -580,8 +581,7 @@ class calendar_groupdav extends groupdav_handler
*/
function read($id)
{
- //$cal_read = $this->bo->read($id,null,false,'server');//njv: do we actually get anything
- if ($this->debug > 1) error_log("bo-ical read :$id:");//njv:
+ if ($this->debug > 1) error_log("bo-ical read :$id:");
return $this->bo->read($id,null,false,'server');
}
@@ -622,12 +622,12 @@ class calendar_groupdav extends groupdav_handler
{
if ($recurrence['reference']) // ignore series master
{
- $etag .= ':'.substr($this->get_etag($recurrence),1,-1);
+ $etag .= ':'.substr($this->get_etag($recurrence),4,-4);
}
}
}
//error_log(__METHOD__ . "($entry[id] ($entry[etag]): $entry[title] --> etag=$etag");
- return '"'.$etag.'"';
+ return 'EGw-'.$etag.'-wGE';
}
/**
@@ -650,23 +650,23 @@ class calendar_groupdav extends groupdav_handler
*/
static function current_user_privilege_set(array $props=array())
{
- $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',''),
+ $props[] = HTTP_WebDAV_Server::mkprop(groupdav::DAV,'current-user-privilege-set',
+ array(HTTP_WebDAV_Server::mkprop(groupdav::DAV,'privilege',
+ array(//HTTP_WebDAV_Server::mkprop(groupdav::DAV,'all',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::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',''),
+ //HTTP_WebDAV_Server::mkprop(groupdav::DAV,'read-current-user-privilege-set',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'bind',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'unbind',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'schedule-post',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'schedule-post-vevent',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'schedule-respond',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'schedule-respond-vevent',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'schedule-deliver',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'schedule-deliver-vevent',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'write',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'write-properties',''),
+ HTTP_WebDAV_Server::mkprop(groupdav::DAV,'write-content',''),
))));
return $props;
}
@@ -675,42 +675,41 @@ class calendar_groupdav extends groupdav_handler
* Add extra properties for calendar collections
*
* @param array $props=array() regular props by the groupdav handler
+ * @param string $displayname
* @param string $base_uri=null base url of handler
* @return array
*/
- static function extra_properties(array $props=array(), $base_uri=null)
+ static function extra_properties(array $props=array(), $displayname, $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/')));
+ array(HTTP_WebDAV_Server::mkprop(groupdav::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/')));
+ array(HTTP_WebDAV_Server::mkprop(groupdav::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/')));
+ array(HTTP_WebDAV_Server::mkprop(groupdav::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/')));
+ array(HTTP_WebDAV_Server::mkprop(groupdav::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']);
+ $props[] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-user-address-set',array(
+ HTTP_WebDAV_Server::mkprop('href','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')), // 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;
}
diff --git a/calendar/inc/class.calendar_ical.inc.php b/calendar/inc/class.calendar_ical.inc.php
index 8742e6a63d..ad0439960f 100644
--- a/calendar/inc/class.calendar_ical.inc.php
+++ b/calendar/inc/class.calendar_ical.inc.php
@@ -1029,9 +1029,10 @@ class calendar_ical extends calendar_boupdate
* @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
+ * @param int $user=null account_id of owner, default null
* @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, $principalURL='')
+ function importVCal($_vcalData, $cal_id=-1, $etag=null, $merge=false, $recur_date=0, $principalURL='', $user=null)
{
if (!is_array($this->supportedFields)) $this->setSupportedFields();
@@ -1081,7 +1082,7 @@ class calendar_ical extends calendar_boupdate
if ($this->log)
{
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__
- ."($cal_id, $etag, $recur_date, $principalURL)\n"
+ ."($cal_id, $etag, $recur_date, $principalURL, $user)\n"
. array2string($event)."\n",3,$this->logfile);
}
$updated_id = false;
@@ -1204,9 +1205,20 @@ class calendar_ical extends calendar_boupdate
$event['non_blocking'] = 1;
}
+ if (!is_null($user))
+ {
+ if ($this->check_perms(EGW_ACL_ADD, 0, $user))
+ {
+ $event['owner'] = $user;
+ }
+ else
+ {
+ return false; // no permission
+ }
+ }
// check if an owner is set and the current user has add rights
// for that owners calendar; if not set the current user
- if (!isset($event['owner'])
+ elseif (!isset($event['owner'])
|| !$this->check_perms(EGW_ACL_ADD, 0, $event['owner']))
{
$event['owner'] = $this->user;
diff --git a/egw-pear/HTTP/WebDAV/Server.php b/egw-pear/HTTP/WebDAV/Server.php
index 0a98a2bc01..70f1ca7a6a 100644
--- a/egw-pear/HTTP/WebDAV/Server.php
+++ b/egw-pear/HTTP/WebDAV/Server.php
@@ -59,6 +59,18 @@ class HTTP_WebDAV_Server
*/
var $client_require_href_as_url;
+ /**
+ * Set if client requires does not allow namespace redundacy.
+ * The XML Namespace specification does allow both
+ * But some clients can NOT deal with one or the other!
+ *
+ * @var boolean (client_refuses_redundand_namespace_declarations)
+ */
+ var $crrnd = false;
+
+ /**
+
+
/**
* URI path for this request
*
@@ -229,11 +241,18 @@ class HTTP_WebDAV_Server
$this->$wrapper(); // call method by name
} else { // method not found/implemented
if ($this->_SERVER["REQUEST_METHOD"] == "LOCK") {
- $this->http_status("412 Precondition failed");
+ $error = '412 Precondition failed';
+ ;
} else {
- $this->http_status("405 Method not allowed");
+ $error = '405 Method not allowed';
header("Allow: ".join(", ", $this->_allow())); // tell client what's allowed
}
+ $this->http_status($error);
+ echo "
Error $error\n";
+ echo "$error
\n";
+ echo "The requested could not by handled by this server.\n";
+ echo '(URI ' . $this->_SERVER['REQUEST_URI'] . ")
\n
\n";
+ echo "\n";
}
}
@@ -432,7 +451,7 @@ class HTTP_WebDAV_Server
*/
// }}}
- // {{{ LOCK()
+ // {{{ ACL()
/**
* ACL implementation
@@ -585,7 +604,7 @@ class HTTP_WebDAV_Server
$options['other'] = $propinfo->other;
// call user handler
- if (!$this->$handler($options, $files)) {
+ if (!($retval =$this->$handler($options, $files))) {
$files = array("files" => array());
if (method_exists($this, "checkLock")) {
// is locked?
@@ -611,27 +630,43 @@ class HTTP_WebDAV_Server
}
}
- // now we generate the reply header ...
- if ($propinfo->root['name'] == 'principal-search-property-set')
+ // now we generate the reply header ...
+ if ($retval === true)
{
- $this->http_status('200 OK');
+ $this->http_status('207 Multi-Status');
}
else
{
- $this->http_status('207 Multi-Status');
+ $this->http_status($retval);
+ header('Content-Type: text/html');
+ echo "Error $retval\n";
+ echo "$retval
\n";
+ switch (substr($retval, 0 ,3))
+ {
+ case '501': // Not Implemented
+ echo "The requested feature is not (yet) supported by this server.\n";
+ break;
+ default:
+ echo "The request could not be handled by this server.\n";
+ }
+ echo '(URI ' . $this->_SERVER['REQUEST_URI'] . ")
\n
\n";
+ echo "\n";
+ return;
}
+ // dav header
+ $dav = array(1); // assume we are always dav class 1 compliant
+ $allow = false;
+
+ // allow extending class to modify DAV
+ if (method_exists($this,'OPTIONS')) {
+ $this->OPTIONS($this->path,$dav,$allow);
+ }
+ header("DAV: " .join(", ", $dav));
header('Content-Type: text/xml; charset="utf-8"');
// ... and payload
echo "\n";
- if ($propinfo->root['name'] == 'principal-search-property-set')
- {
- echo "\n";
- }
- else
- {
- echo "\n";
- }
+ echo ($this->crrnd?'<':'\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']
@@ -748,7 +783,14 @@ class HTTP_WebDAV_Server
$path = $file['path'];
if (!is_string($path) || $path==="") continue;
- if ($propinfo->root['name'] != 'principal-search-property-set') echo " \n";
+ if ($this->crrnd)
+ {
+ echo " \n";
+ }
+ else
+ {
+ echo " \n";
+ }
/* TODO right now the user implementation has to make sure
collections end in a slash, this should be done in here
@@ -756,15 +798,20 @@ class HTTP_WebDAV_Server
// path needs to be urlencoded (only basic version of this class!)
$href = $this->_urlencode($this->_mergePathes($this->base_uri, $path));
- if ($propinfo->root['name'] != 'principal-search-property-set') echo " $href\n";
+ if ($this->crrnd)
+ {
+ echo " $href\n";
+ }
+ else
+ {
+ echo " $href\n";
+ }
// report all found properties and their values (if any)
if (isset($file["props"]) && is_array($file["props"])) {
- if ($propinfo->root['name'] != 'principal-search-property-set')
- {
- echo " \n";
- echo " \n";
- }
+ echo ' <'.($this->crrnd?'':'D:')."propstat>\n";
+ echo ' <'.($this->crrnd?'':'D:')."prop>\n";
+
foreach ($file["props"] as &$prop) {
if (!is_array($prop)) continue;
@@ -773,7 +820,7 @@ class HTTP_WebDAV_Server
if (!isset($prop["val"]) || $prop["val"] === "" || $prop["val"] === false) {
// empty properties (cannot use empty() for check as "0" is a legal value here)
if ($prop["ns"]=="DAV:") {
- echo " \n";
+ echo ' <'.($this->crrnd?'':'D:')."$prop[name]/>\n";
} else if (!empty($prop["ns"])) {
echo " <".$ns_hash[$prop["ns"]].":$prop[name]/>\n";
} else {
@@ -783,61 +830,34 @@ class HTTP_WebDAV_Server
// some WebDAV properties need special treatment
switch ($prop["name"]) {
case "creationdate":
- echo " "
+ echo ' <'.($this->crrnd?'':'D:')."creationdate ns0:dt=\"dateTime.tz\">"
. gmdate("Y-m-d\\TH:i:s\\Z", $prop['val'])
- . "\n";
+ . ''.($this->crrnd?'':'D:')."creationdate>\n";
break;
case "getlastmodified":
- echo " "
+ echo ' <'.($this->crrnd?'':'D:')."getlastmodified ns0:dt=\"dateTime.rfc1123\">"
. gmdate("D, d M Y H:i:s ", $prop['val'])
- . "GMT\n";
+ . "GMT".($this->crrnd?'':'D:')."getlastmodified>\n";
break;
- /* @Todo: breaks CalDAV - 2010/03/01 jlehrke
- case "resourcetype":
- if (!is_array($prop['val'])) {
- echo ' \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 " $vals\n";
- //error_log("resourcetype: $vals");
- }
- break;
- */
case "supportedlock":
- echo " $prop[val]\n";
+ echo ' <'.($this->crrnd?'':'D:')."supportedlock>$prop[val]".($this->crrnd?'':'D:')."supportedlock>\n";
break;
case "lockdiscovery":
- echo " \n";
+ echo ' <'.($this->crrnd?'':'D:')."lockdiscovery>\n";
echo $prop["val"];
- echo " \n";
+ echo ' '.($this->crrnd?'':'D:')."lockdiscovery>\n";
break;
default:
- echo " ".
- (is_array($prop['val']) ?
- $this->_hierarchical_prop_encode($prop['val']) :
- $this->_prop_encode(htmlspecialchars($prop['val']))).
- "\n";
+ if (is_array($prop['val']))
+ {
+ $val = $this->_hierarchical_prop_encode($prop['val']);
+ } elseif (isset($prop['raw'])) {
+ $val = $this->_prop_encode('');
+ } else {
+ $val = $this->_prop_encode(htmlspecialchars($prop['val']));
+ }
+ echo ' <'.($this->crrnd?'':'D:')."$prop[name]>$val".
+ ''.($this->crrnd?'':'D:')."$prop[name]>\n";
break;
}
} else {
@@ -850,53 +870,75 @@ class HTTP_WebDAV_Server
$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[name]";
- if (is_array($subprop['val'])) // val contains only attributes, no value
- {
- foreach($subprop['val'] as $attr => $val)
- {
- $vals .= ' '.$attr.'="'.htmlspecialchars($val).'"';
- }
- $vals .= '/>';
- }
- else
- {
- $vals .= '>'.htmlspecialchars($subprop['val'])."$ns_name$subprop[name]>";
- }
- }
- echo " <".$ns_hash[$prop['ns']].":$prop[name]$extra_ns>$vals".$ns_hash[$prop['ns']].":$prop[name]>\n";
- }
- else
- // properties from namespaces != "DAV:" or without any namespace
- if ($prop["ns"]) {
- echo " <" . $ns_hash[$prop["ns"]] . ":$prop[name]>"
- . $this->_prop_encode(htmlspecialchars($prop['val']))
- . "" . $ns_hash[$prop["ns"]] . ":$prop[name]>\n";
+ 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[name]";
+ if (is_array($subprop['val'])) // val contains only attributes, no value
+ {
+ foreach($subprop['val'] as $attr => $val)
+ {
+ $vals .= ' '.$attr.'="'.htmlspecialchars($val).'"';
+ }
+ $vals .= '/>';
+ }
+ else
+ {
+ $vals .= '>';
+ if (isset($subprop['raw'])) {
+ $vals .= '';
+ } else {
+ $vals .= htmlspecialchars($subprop['val']);
+ }
+ $vals .= "$ns_name$subprop[name]>";
+ }
+ }
+ echo ' <'.$ns_hash[$prop['ns']].":$prop[name]$extra_ns>$vals".$ns_hash[$prop['ns']].":$prop[name]>\n";
} else {
- echo " <$prop[name] xmlns=\"\">"
- . $this->_prop_encode(htmlspecialchars($prop['val']))
- . "$prop[name]>\n";
+ if ($prop['raw'])
+ {
+ $val = '';
+ } else {
+ $val = htmlspecialchars($prop['val']);
+ }
+ $val = $this->_prop_encode($val);
+ // properties from namespaces != "DAV:" or without any namespace
+ if ($prop['ns']) {
+ if ($this->crrnd) {
+ echo " <$prop[name]> xmlns:".$ns_hash[$prop['ns']]."=".'"'.$prop["ns"].'">'
+ . $val . "$prop[name]>\n";
+ } else {
+ echo " <" . $ns_hash[$prop["ns"]] . ":$prop[name]>"
+ . $val . ''.$ns_hash[$prop['ns']].":$prop[name]>\n";
+ }
+ } else {
+ echo " <$prop[name] xmlns=\"\">$val$prop[name]>\n";
+ }
}
}
}
- if ($propinfo->root['name'] != 'principal-search-property-set')
+
+ if ($this->crrnd)
+ {
+ echo " \n";
+ echo " HTTP/1.1 200 OK\n";
+ echo " \n";
+ }
+ else
{
echo " \n";
echo " HTTP/1.1 200 OK\n";
@@ -906,12 +948,12 @@ class HTTP_WebDAV_Server
// now report all properties requested but not found
if (isset($file["noprops"])) {
- echo " \n";
- echo " \n";
+ echo ' <'.($this->crrnd?'':'D:')."propstat>\n";
+ echo ' <'.($this->crrnd?'':'D:')."prop>\n";
foreach ($file["noprops"] as &$prop) {
if ($prop["ns"] == "DAV:") {
- echo " \n";
+ echo ' <'.($this->crrnd?'':'D:')."$prop[name]/>\n";
} else if ($prop["ns"] == "") {
echo " <$prop[name] xmlns=\"\"/>\n";
} else {
@@ -919,23 +961,24 @@ class HTTP_WebDAV_Server
}
}
- echo " \n";
- echo " HTTP/1.1 404 Not Found\n";
- echo " \n";
+ if ($this->crrnd)
+ {
+ echo " \n";
+ echo " HTTP/1.1 404 Not Found\n";
+ echo " \n";
+ }
+ else
+ {
+ echo " \n";
+ echo " HTTP/1.1 404 Not Found\n";
+ echo " \n";
+ }
}
- if ($propinfo->root['name'] != 'principal-search-property-set') echo " \n";
- }
-
- if ($propinfo->root['name'] == 'principal-search-property-set')
- {
- echo "\n";
- }
- else
- {
- echo "\n";
+ echo ' '.($this->crrnd?'':'D:')."response>\n";
}
+ echo ''.($this->crrnd?'':'D:')."multistatus>\n";
}
@@ -973,24 +1016,24 @@ class HTTP_WebDAV_Server
echo "\n";
echo "\n";
- echo " \n";
- echo " ".$this->_urlencode($this->_mergePathes($this->_SERVER["SCRIPT_NAME"], $this->path))."\n";
+ echo ' <'.($this->crrnd?'':'D:')."response>\n";
+ echo ' <'.($this->crrnd?'':'D:')."href>".$this->_urlencode($this->_mergePathes($this->_SERVER["SCRIPT_NAME"], $this->path)).''.($this->crrnd?'':'D:')."href>\n";
foreach ($options["props"] as $prop) {
- echo " \n";
- echo " <$prop[name] xmlns=\"$prop[ns]\"/>\n";
- echo " HTTP/1.1 $prop[status]\n";
- echo " \n";
+ echo ' <'.($this->crrnd?'':'D:')."propstat>\n";
+ echo ' <'.($this->crrnd?'':'D:')."prop><$prop[name] xmlns=\"$prop[ns]\"/>".($this->crrnd?'':'D:')."prop>\n";
+ echo ' <'.($this->crrnd?'':'D:')."status>HTTP/1.1 $prop[status]".($this->crrnd?'':'D:')."status>\n";
+ echo ' '.($this->crrnd?'':'D:')."propstat>\n";
}
if ($responsedescr) {
- echo " ".
+ echo ' <'.($this->crrnd?'':'D:')."responsedescription>".
$this->_prop_encode(htmlspecialchars($responsedescr)).
- "\n";
+ ''.($this->crrnd?'':'D:')."responsedescription>\n";
}
- echo " \n";
- echo "\n";
+ echo ' '.($this->crrnd?'':'D:')."response>\n";
+ echo ''.($this->crrnd?'':'D:')."multistatus>\n";
} else {
$this->http_status("423 Locked");
}
@@ -1580,17 +1623,17 @@ class HTTP_WebDAV_Server
header("Lock-Token: <$options[locktoken]>");
echo "\n";
echo "\n";
- echo " \n";
- echo " \n";
- echo " \n";
- echo " \n";
- echo " $options[depth]\n";
- echo " $options[owner]\n";
- echo " $timeout\n";
- echo " $options[locktoken]\n";
- echo " \n";
- echo " \n";
- echo "\n\n";
+ echo ' <'.($this->crrnd?'':'D:')."lockdiscovery>\n";
+ echo ' <'.($this->crrnd?'':'D:')."activelock>\n";
+ echo ' <'.($this->crrnd?'':'D:')."lockscope>".($this->crrnd?'':'D:')."lockscope>\n";
+ echo ' <'.($this->crrnd?'':'D:')."locktype>".($this->crrnd?'':'D:')."locktype>\n";
+ echo ' <'.($this->crrnd?'':'D:')."depth>$options[depth]".($this->crrnd?'':'D:')."depth>\n";
+ echo ' <'.($this->crrnd?'':'D:')."owner>$options[owner]".($this->crrnd?'':'D:')."owner>\n";
+ echo ' <'.($this->crrnd?'':'D:')."timeout>$timeout".($this->crrnd?'':'D:')."timeout>\n";
+ echo ' <'.($this->crrnd?'':'D:')."locktoken>$options[locktoken]".($this->crrnd?'':'D:')."locktoken>\n";
+ echo ' '.($this->crrnd?'':'D:')."activelock>\n";
+ echo ' '.($this->crrnd?'':'D:')."lockdiscovery>\n";
+ echo ''.($this->crrnd?'':'D:')."prop>\n\n";
}
}
@@ -1627,9 +1670,9 @@ class HTTP_WebDAV_Server
// }}}
- // {{{ http_UNLOCK()
+ // {{{ http_ACL()
- /**
+ /**
* ACL method handler
*
* @param void
@@ -1660,9 +1703,9 @@ class HTTP_WebDAV_Server
$content .= "\n";
$content .= " \n";
foreach ($options['errors'] as $violation) {
- $content .= "\n";
+ $content .= '<'.($this->crrnd?'':'D:')."$violation/>\n";
}
- $content .= "\n";
+ $content .= ''.($this->crrnd?'':'D:')."error>\n";
}
header("Content-length: ".$this->bytes($content));
if ($content) echo $options['content'];
@@ -1765,20 +1808,27 @@ class HTTP_WebDAV_Server
* @param string XML namespace (optional)
* @param string property name
* @param string property value
+ * @praram boolen property raw-flag
* @return array property array
*/
function mkprop()
{
- $args = func_get_args();
- if (count($args) == 3) {
- return array("ns" => $args[0],
- "name" => $args[1],
- "val" => $args[2]);
- } else {
- return array("ns" => "DAV:",
- "name" => $args[0],
- "val" => $args[1]);
- }
+ $args = func_get_args();
+ switch (count($args)) {
+ case 4:
+ return array('ns' => $args[0],
+ 'name' => $args[1],
+ 'val' => $args[2],
+ 'raw' => true);
+ case 3:
+ return array('ns' => $args[0],
+ 'name' => $args[1],
+ 'val' => $args[2]);
+ default:
+ return array("ns" => "DAV:",
+ "name" => $args[0],
+ "val" => $args[1]);
+ }
}
// {{{ _check_auth
@@ -2125,16 +2175,32 @@ class HTTP_WebDAV_Server
}
// genreate response block
- $activelocks.= "
-
-
-
- $lock[depth]
- $lock[owner]
- $timeout
- $lock[token]
-
- ";
+ if ($this->crrnd)
+ {
+ $activelocks.= "
+
+ <$lock[scope]/>
+ <$lock[type]/>
+ $lock[depth]
+ $lock[owner]
+ $timeout
+ $lock[token]
+
+ ";
+ }
+ else
+ {
+ $activelocks.= "
+
+
+
+ $lock[depth]
+ $lock[owner]
+ $timeout
+ $lock[token]
+
+ ";
+ }
}
// return generated response
diff --git a/egw-pear/HTTP/WebDAV/Server/Filesystem.php b/egw-pear/HTTP/WebDAV/Server/Filesystem.php
index 48c30da8d1..b6b98fd691 100644
--- a/egw-pear/HTTP/WebDAV/Server/Filesystem.php
+++ b/egw-pear/HTTP/WebDAV/Server/Filesystem.php
@@ -186,7 +186,7 @@ class HTTP_WebDAV_Server_Filesystem extends HTTP_WebDAV_Server
// type and size (caller already made sure that path exists)
if (is_dir($fspath)) {
// directory (WebDAV collection)
- $info["props"][] = $this->mkprop("resourcetype", "collection");
+ $info["props"][] = $this->mkprop("resourcetype", array($this->mkprop('collection', '')));
$info["props"][] = $this->mkprop("getcontenttype", "httpd/unix-directory");
} else {
// plain file (WebDAV resource)
diff --git a/infolog/inc/class.infolog_bo.inc.php b/infolog/inc/class.infolog_bo.inc.php
index 097ca0d434..5eb9b1ad72 100644
--- a/infolog/inc/class.infolog_bo.inc.php
+++ b/infolog/inc/class.infolog_bo.inc.php
@@ -420,13 +420,13 @@ class infolog_bo
/**
* Read an infolog entry specified by $info_id
*
- * @param int/array $info_id integer id or array with key 'info_id' of the entry to read
+ * @param int|array $info_id integer id or array with key 'info_id' of the entry to read
* @param boolean $run_link_id2from=true should link_id2from run, default yes,
* need to be set to false if called from link-title to prevent an infinit recursion
* @param string $date_format='ts' date-formats: 'ts'=timestamp, 'server'=timestamp in server-time,
* 'array'=array or string with date-format
*
- * @return array/boolean infolog entry, null if not found or false if no permission to read it
+ * @return array|boolean infolog entry, null if not found or false if no permission to read it
*/
function &read($info_id,$run_link_id2from=true,$date_format='ts')
{
diff --git a/infolog/inc/class.infolog_groupdav.inc.php b/infolog/inc/class.infolog_groupdav.inc.php
index 206bd0acef..ea102d49f7 100644
--- a/infolog/inc/class.infolog_groupdav.inc.php
+++ b/infolog/inc/class.infolog_groupdav.inc.php
@@ -57,7 +57,7 @@ class infolog_groupdav extends groupdav_handler
if (!is_array($info)) $info = $this->bo->read($info);
$name = $info[self::PATH_ATTRIBUTE];
}
- return '/infolog/'.$name.'.ics';
+ return $name.'.ics';
}
/**
@@ -73,6 +73,8 @@ class infolog_groupdav extends groupdav_handler
{
$starttime = microtime(true);
+ $myself = ($user == $GLOBALS['egw_info']['user']['account_id']);
+
if ($options['filters'])
{
@@ -113,14 +115,17 @@ class infolog_groupdav extends groupdav_handler
$filter = array(
'info_type' => 'task',
);
+
+ //if (!$myself) $filter['info_owner'] = $user;
+
if ($id) $filter['info_id'] = $id; // propfind on a single id
// ToDo: add parameter to only return id & etag
if (($tasks =& $this->bo->search($params=array(
'order' => 'info_datemodified',
'sort' => 'DESC',
- 'filter' => 'own', // filter my: entries user is responsible for,
- // filter own: entries the user own or is responsible for
+ 'filter' => ($myself ? 'own' : 'own'), // filter my: entries user is responsible for,
+ // filter own: entries the user own or is responsible for
'date_format' => 'server',
'col_filter' => $filter,
))))
@@ -148,7 +153,7 @@ class infolog_groupdav extends groupdav_handler
$props[] = HTTP_WebDAV_Server::mkprop('getcontentlength', ''); // expensive to calculate and no CalDAV client uses it
}
$files['files'][] = array(
- 'path' => self::get_path($task),
+ 'path' => $path.self::get_path($task),
'props' => $props,
);
}
@@ -193,8 +198,11 @@ class infolog_groupdav extends groupdav_handler
{
return $ok;
}
+
$handler = $this->_get_handler();
- if (!($info_id = $handler->importVTODO($options['content'],is_numeric($id) ? $id : -1)))
+ $vTodo = htmlspecialchars_decode($options['content']);
+
+ if (!($info_id = $handler->importVTODO($vTodo,is_numeric($id) ? $id : -1, false, $user)))
{
if ($this->debug) error_log(__METHOD__."(,$id) import_vtodo($options[content]) returned false");
return '403 Forbidden';
@@ -202,7 +210,8 @@ class infolog_groupdav extends groupdav_handler
header('ETag: '.$this->get_etag($info_id));
if (is_null($ok) || $id != $info_id)
{
- header('Location: '.$this->base_uri.self::get_path($info_id));
+ $path = preg_replace('|(.*)/[^/]*|', '\1/', $options['path']);
+ header('Location: '.$path.self::get_path($info_id));
return '201 Created';
}
return true;
@@ -263,36 +272,38 @@ class infolog_groupdav extends groupdav_handler
{
return false;
}
- return '"'.$info['info_id'].':'.$info['info_datemodified'].'"';
+ return 'EGw-'.$info['info_id'].':'.$info['info_datemodified'].'-wGE';
}
/**
* Add extra properties for calendar collections
*
* @param array $props=array() regular props by the groupdav handler
+ * @param string $displayname
* @param string $base_uri=null base url of handler
* @return array
*/
- static function extra_properties(array $props=array(), $base_uri=null)
+ static function extra_properties(array $props=array(), $displayname, $base_uri=null)
{
// calendar description
$displayname = $GLOBALS['egw']->translation->convert(lang('Tasks of') . ' ' .
- $GLOBALS['egw_info']['user']['account_fullname'],
+ $displayname,
$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']);
+ $props[] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-user-address-set',array(
+ HTTP_WebDAV_Server::mkprop('href','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;
}
diff --git a/infolog/inc/class.infolog_ical.inc.php b/infolog/inc/class.infolog_ical.inc.php
index b169b996d9..97bbf77068 100644
--- a/infolog/inc/class.infolog_ical.inc.php
+++ b/infolog/inc/class.infolog_ical.inc.php
@@ -380,9 +380,10 @@ class infolog_ical extends infolog_bo
* @param string $_vcalData
* @param int $_taskID=-1 info_id, default -1 = new entry
* @param boolean $merge=false merge data with existing entry
+ * @param int $user=null delegate new task to this account_id, default null
* @return int|boolean integer info_id or false on error
*/
- function importVTODO(&$_vcalData, $_taskID=-1, $merge=false)
+ function importVTODO(&$_vcalData, $_taskID=-1, $merge=false, $user=null)
{
if (!($taskData = $this->vtodotoegw($_vcalData,$_taskID))) return false;
@@ -397,6 +398,11 @@ class infolog_ical extends infolog_bo
$taskData['info_datecompleted'] = 0;
}
+ if (!is_null($user))
+ {
+ $taskData['info_responsible'] = array($user);
+ }
+
if ($this->log)
{
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n" .
diff --git a/phpgwapi/inc/class.groupdav.inc.php b/phpgwapi/inc/class.groupdav.inc.php
index 1d0b6e989d..d92a862288 100644
--- a/phpgwapi/inc/class.groupdav.inc.php
+++ b/phpgwapi/inc/class.groupdav.inc.php
@@ -36,6 +36,10 @@ require_once('HTTP/WebDAV/Server.php');
*/
class groupdav extends HTTP_WebDAV_Server
{
+ /**
+ * DAV namespace
+ */
+ const DAV = 'DAV:';
/**
* GroupDAV namespace
*/
@@ -107,6 +111,12 @@ class groupdav extends HTTP_WebDAV_Server
* @var string
*/
var $principalURL;
+ /**
+ * Reference to the accounts class
+ *
+ * @var accounts
+ */
+ var $accounts;
function __construct()
@@ -122,6 +132,8 @@ class groupdav extends HTTP_WebDAV_Server
case 'davkit': // iCal app in OS X 10.6 created wrong request, if full url given
$this->client_require_href_as_url = false;
break;
+ case 'cfnetwork':
+ $this->crrnd = true; // Apple Addressbook.app does not cope with namespace redundancy
}
parent::HTTP_WebDAV_Server();
@@ -136,6 +148,8 @@ class groupdav extends HTTP_WebDAV_Server
$this->principalURL = (@$_SERVER["HTTPS"] === "on" ? "https:" : "http:") .
'//' . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'] . '/';
}
+ $this->principalURL .= 'principals/users/'.$GLOBALS['egw_info']['user']['account_lid'].'/';
+ $this->accounts = $GLOBALS['egw']->accounts;
}
/**
@@ -162,12 +176,24 @@ class groupdav extends HTTP_WebDAV_Server
switch($app)
{
case 'calendar':
- case 'infolog':
+ $dav[] = 2;
+ $dav[] = 'access-control';
$dav[] = 'calendar-access';
+ //$dav[] = 'calendar-schedule';
+ //$dav[] = 'calendar-proxy';
+ //$dav[] = 'calendar-avialibility';
+ //$dav[] = 'calendarserver-private-events';
break;
case 'addressbook':
- $dav[] = 'addressbook';
+ $dav[] = 2;
+ $dav[] = 3;
+ $dav[] = 'access-control';
+ $dav[] = 'addressbook-access';
break;
+ default:
+ $dav[] = 2;
+ $dav[] = 'access-control';
+ $dav[] = 'calendar-access';
}
// not yet implemented: $dav[] = 'access-control';
}
@@ -179,77 +205,101 @@ class groupdav extends HTTP_WebDAV_Server
* @param array return array for file properties
* @return bool true on success
*/
- function PROPFIND(&$options, &$files,$method='PROPFIND')
+ function PROPFIND(&$options, &$files, $method='PROPFIND')
{
if ($this->debug) error_log(__CLASS__."::$method(".array2string($options,true).')');
+
+ if (groupdav_handler::get_agent() == 'cfnetwork' && // Apple Addressbook
+ $options['root']['name'] == 'propfind')
+ {
+ foreach ($options['props'] as $props)
+ {
+ if ($props['name'] == 'current-user-privilege-set')
+ {
+ if ($this->debug > 2) error_log(__CLASS__."::$method: current-user-privilege-set not implemented!");
+ return '501 Not Implemented';
+ }
+ }
+ }
// parse path in form [/account_lid]/app[/more]
if (!self::_parse_path($options['path'],$id,$app,$user,$user_prefix) && $app && !$user)
{
- if ($this->debug > 1) error_log(__CLASS__."::$method: user=$user, app=$app, id=$id: 404 not found!");
+ if ($this->debug > 1) error_log(__CLASS__."::$method: user='$user', app='$app', id='$id': 404 not found!");
return '404 Not Found';
}
- if ($this->debug > 1) error_log(__CLASS__."::$method: user=$user, app='$app', id=$id");
+ if ($this->debug > 1) error_log(__CLASS__."::$method: user='$user', app='$app', id='$id'");
+
+ if ($user)
+ {
+ $account_lid = $this->accounts->id2name($user);
+ }
+ else
+ {
+ $account_lid = $GLOBALS['egw_info']['user']['account_lid'];
+ }
+ $account = $this->accounts->read($account_lid);
+ $displayname = $GLOBALS['egw']->translation->convert($account['account_fullname'],
+ $GLOBALS['egw']->translation->charset(),'utf-8');
$files = array('files' => array());
+ $path = $user_prefix = $this->_slashify($user_prefix);
- if (!$app) // root folder containing apps
+ if (!$app) // user root folder containing apps
{
if (empty($user_prefix))
+ {
+ $user_prefix = '/'.$GLOBALS['egw_info']['user']['account_lid'].'/';
+ }
+ if ($options['depth'])
{
$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(
+ $props = array(
self::mkprop('displayname',$displayname),
- self::mkprop('resourcetype','collection'),
+ self::mkprop('resourcetype',array(self::mkprop('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',array(self::mkprop('href',$this->base_uri.'/calendar/'))),
+ self::mkprop(groupdav::CALDAV,'calendar-home-set',array(
+ self::mkprop('href',$this->base_uri.$user_prefix.'calendar/'))),
+ self::mkprop(groupdav::CARDDAV,'addressbook-home-set',array(
+ self::mkprop('href',$this->base_uri.$user_prefix))),
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(groupdav::CALDAV,'calendar-user-address-set',array(
+ self::mkprop('href','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/'))),
- ),
+ );
+ //$props = self::current_user_privilege_set($props);
+ $files['files'][] = array(
+ 'path' => $path,
+ 'props' => $props,
);
if ($options['depth'])
{
- if (empty($user_prefix))
+ if (strlen($path) == 1) // GroupDAV Root
{
// principals collection
$files['files'][] = array(
'path' => '/principals/',
'props' => array(
self::mkprop('displayname',lang('Accounts')),
- self::mkprop('resourcetype','collection'),
+ self::mkprop('resourcetype',array(self::mkprop('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))),
+ self::mkprop(groupdav::CALDAV,'calendar-home-set',array(
+ self::mkprop('href',$this->base_uri.$user_prefix.'calendar/'))),
+ self::mkprop(groupdav::CARDDAV,'addressbook-home-set',array(
+ self::mkprop('href',$this->base_uri.'/'))),
+ 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->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))),
- ),
- );
}
foreach($this->root as $app => $data)
{
if (!$GLOBALS['egw_info']['user']['apps'][$app]) continue; // no rights for the given app
$files['files'][] = array(
- 'path' => $user_prefix.'/'.$app.'/',
+ 'path' => $path.$app.'/',
'props' => $this->_properties($app,false,$user),
);
}
@@ -266,9 +316,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] = array(
- 'path' => '/'.$app.'/',
+ 'path' => $path.$app.'/',
// KAddressbook doubles the folder, if the self URL contains the GroupDAV/CalDAV resourcetypes
- 'props' => $this->_properties($app,$app=='addressbook'&&strpos($_SERVER['HTTP_USER_AGENT'],'KHTML') !== false),
+ 'props' => $this->_properties($app,$app=='addressbook'&&strpos($_SERVER['HTTP_USER_AGENT'],'KHTML') !== false,$user),
);
}
if (isset($options['depth']) && !$options['depth'] && !$id)
@@ -281,7 +331,7 @@ class groupdav extends HTTP_WebDAV_Server
}
return true; // depth 0 --> show only the self url
}
- return $handler->propfind($options['path'],$options,$files,$user,$id);
+ return $handler->propfind($this->_slashify($options['path']),$options,$files,$user,$id);
}
return '501 Not Implemented';
}
@@ -296,25 +346,52 @@ 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');
+ if ($this->debug) error_log(__CLASS__."::$method: user='$user', app='$app'");
+ if ($user)
+ {
+ $account_lid = $this->accounts->id2name($user);
+ }
+ else
+ {
+ $account_lid = $GLOBALS['egw_info']['user']['account_lid'];
+ }
+ $account = $this->accounts->read($account_lid);
+ $displayname = $GLOBALS['egw']->translation->convert($account['account_fullname'],
+ $GLOBALS['egw']->translation->charset(),'utf-8');
$props = array(
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/'))),
+ self::mkprop('principal-URL',array(self::mkprop('href',$this->principalURL))),
+ self::mkprop('alternate-URI-set',array(
+ self::mkprop('href','MAILTO:'.$GLOBALS['egw_info']['user']['email']))),
+ self::mkprop(groupdav::CALDAV,'calendar-user-address-set',array(
+ self::mkprop('href','MAILTO:'.$GLOBALS['egw_info']['user']['email']))),
+ self::mkprop('principal-collection-set',array(
+ self::mkprop('href',$this->base_uri.'/principals/users/'),
+ self::mkprop('href',$this->base_uri.'/principals/groups/'),
+ )),
);
switch ($app)
{
case 'calendar':
- $props[] = self::mkprop(groupdav::CALDAV,'calendar-home-set',array(self::mkprop('href',$this->base_uri.'/calendar/')));
+ $props[] = self::mkprop(groupdav::CALDAV,'calendar-home-set',array(
+ self::mkprop('href',$this->base_uri.'/'.$account_lid.'/calendar/')));
break;
case 'infolog':
- $props[] = self::mkprop(groupdav::CALDAV,'calendar-home-set',array(self::mkprop('href',$this->base_uri.'/infolog/')));
+ $props[] = self::mkprop(groupdav::CALDAV,'calendar-home-set',array(
+ self::mkprop('href',$this->base_uri.'/'.$account_lid.'/infolog/')));
+ $displayname = $this->translation->convert(lang($app).' '.
+ common::grab_owner_name($user),$this->egw_charset,'utf-8');
+ break;
default:
- $displayname = $this->translation->convert(lang($app).' '.common::grab_owner_name($user),$this->egw_charset,'utf-8');
+ $props[] = self::mkprop(groupdav::CALDAV,'calendar-home-set',array(
+ self::mkprop('href',$this->base_uri.'/'.$account_lid.'/calendar/')));
+ $displayname = $this->translation->convert(lang($app).' '.
+ common::grab_owner_name($user),$this->egw_charset,'utf-8');
}
+ $props[] = self::mkprop(groupdav::CARDDAV,'addressbook-home-set',array(
+ self::mkprop('href',$this->base_uri.'/'.$account_lid.'/')));
$props[] = self::mkprop('displayname',$displayname);
foreach((array)$this->root[$app] as $prop => $values)
@@ -343,7 +420,9 @@ class groupdav extends HTTP_WebDAV_Server
}
if (method_exists($app.'_groupdav','extra_properties'))
{
- $props = ExecMethod2($app.'_groupdav::extra_properties',$props,$this->base_uri);
+ $displayname = $GLOBALS['egw']->translation->convert($account['account_fullname'],
+ $GLOBALS['egw']->translation->charset(),'utf-8');
+ $props = ExecMethod2($app.'_groupdav::extra_properties',$props,$displayname,$this->base_uri);
}
return $props;
}
@@ -448,8 +527,7 @@ class groupdav extends HTTP_WebDAV_Server
$props = $this->props2array($file['props']);
//echo $file['path']; _debug_array($props);
$class = $class == 'row_on' ? 'row_off' : 'row_on';
- $name = $this->_slashify(basename($this->_unslashify($file['path'])));
- /*
+
if (substr($file['path'],-1) == '/')
{
$name = basename(substr($file['path'],0,-1)).'/';
@@ -458,7 +536,7 @@ class groupdav extends HTTP_WebDAV_Server
{
$name = basename($file['path']);
}
- */
+
echo "\t\n\t\t$n | \n\t\t".html::a_href(htmlspecialchars($name),'/groupdav.php'.$file['path'])." | \n";
echo "\t\t".$props['DAV:getcontentlength']." | \n";
echo "\t\t".(!empty($props['DAV:getlastmodified']) ? date('Y-m-d H:i:s',$props['DAV:getlastmodified']) : '')." | \n";
@@ -761,7 +839,7 @@ class groupdav extends HTTP_WebDAV_Server
}
$parts = explode('/', $this->_unslashify($path));
- if ($GLOBALS['egw']->accounts->name2id($parts[0]))
+ if ($this->accounts->name2id($parts[0]))
{
// /$user/$app/...
$user = array_shift($parts);
@@ -772,7 +850,7 @@ class groupdav extends HTTP_WebDAV_Server
if ($user)
{
$user_prefix = '/'.$user;
- $user = $GLOBALS['egw']->accounts->name2id($user,'account_lid',$app != 'addressbook' ? 'u' : null);
+ $user = $this->accounts->name2id($user,'account_lid',$app != 'addressbook' ? 'u' : null);
}
else
{
@@ -785,13 +863,39 @@ class groupdav extends HTTP_WebDAV_Server
list($id) = explode('.',$id); // remove evtl. .ics extension
}
- if (!($ok = $id && in_array($app,array('addressbook','calendar','infolog','principals','groups')) && $user))
+ $ok = $id && $user && in_array($app,array('addressbook','calendar','infolog','principals','groups'));
+ if ($this->debug)
{
- if ($this->debug)
- {
- error_log(__METHOD__."('$path') returning false: id=$id, app='$app', user=$user");
- }
+ error_log(__METHOD__."('$path') returning " . ($ok ? 'true' : 'false') . ": id='$id', app='$app', user='$user', user_prefix='$user_prefix'");
}
return $ok;
}
+ /**
+ * Add the privileges of the current user
+ *
+ * @param array $props=array() regular props by the groupdav handler
+ * @return array
+ */
+ static function current_user_privilege_set(array $props=array())
+ {
+ $props[] = HTTP_WebDAV_Server::mkprop('current-user-privilege-set',
+ array(HTTP_WebDAV_Server::mkprop('privilege',
+ array(//HTTP_WebDAV_Server::mkprop('all',''),
+ HTTP_WebDAV_Server::mkprop('read',''),
+ HTTP_WebDAV_Server::mkprop('read-free-busy',''),
+ //HTTP_WebDAV_Server::mkprop('read-current-user-privilege-set',''),
+ HTTP_WebDAV_Server::mkprop('bind',''),
+ HTTP_WebDAV_Server::mkprop('unbind',''),
+ HTTP_WebDAV_Server::mkprop('schedule-post',''),
+ HTTP_WebDAV_Server::mkprop('schedule-post-vevent',''),
+ HTTP_WebDAV_Server::mkprop('schedule-respond',''),
+ HTTP_WebDAV_Server::mkprop('schedule-respond-vevent',''),
+ HTTP_WebDAV_Server::mkprop('schedule-deliver',''),
+ HTTP_WebDAV_Server::mkprop('schedule-deliver-vevent',''),
+ HTTP_WebDAV_Server::mkprop('write',''),
+ HTTP_WebDAV_Server::mkprop('write-properties',''),
+ HTTP_WebDAV_Server::mkprop('write-content',''),
+ ))));
+ return $props;
+ }
}
diff --git a/phpgwapi/inc/class.groupdav_handler.inc.php b/phpgwapi/inc/class.groupdav_handler.inc.php
index c0c90c505b..4fd0c3400a 100644
--- a/phpgwapi/inc/class.groupdav_handler.inc.php
+++ b/phpgwapi/inc/class.groupdav_handler.inc.php
@@ -37,6 +37,12 @@ abstract class groupdav_handler
* @var translation
*/
var $translation;
+ /**
+ * Reference to the accounts class
+ *
+ * @var accounts
+ */
+ var $accounts;
/**
* Translates method names into ACL bits
*
@@ -88,7 +94,6 @@ abstract class groupdav_handler
*/
function __construct($app,$debug=null,$base_uri=null,$principalURL=null)
{
- //error_log(__METHOD__." called");
$this->app = $app;
if (!is_null($debug)) $this->debug = $debug;
$this->base_uri = is_null($base_uri) ? $base_uri : $_SERVER['SCRIPT_NAME'];
@@ -99,13 +104,15 @@ abstract class groupdav_handler
}
else
{
- $this->principalURL = $principalURL;
+ $this->principalURL = $principalURL.'principals/users/'.
+ $GLOBALS['egw_info']['user']['account_lid'].'/';
}
$this->agent = self::get_agent();
$this->translation =& $GLOBALS['egw']->translation;
$this->egw_charset = $this->translation->charset();
+ $this->accounts = $GLOBALS['egw']->accounts;
}
/**
@@ -122,12 +129,13 @@ abstract class groupdav_handler
/**
* Propfind callback, if interator is used
*
+ * @param string $path
* @param array $filter
* @param array|boolean $start false=return all or array(start,num)
* @param int &$total
* @return array with "files" array with values for keys path and props
*/
- function &propfind_callback(array $filter,$start,&$total) { }
+ function &propfind_callback($path, array $filter,$start,&$total) { }
/**
* Handle get request for an applications entry
@@ -178,10 +186,11 @@ abstract class groupdav_handler
* Add extra properties for collections
*
* @param array $props=array() regular props by the groupdav handler
+ * @param string $displayname
* @param string $base_uri=null base url of handler
* @return array
*/
- static function extra_properties(array $props=array(), $base_uri=null)
+ static function extra_properties(array $props=array(), $displayname, $base_uri=null)
{
return $props;
}
@@ -203,7 +212,7 @@ abstract class groupdav_handler
// error_log(__METHOD__."(".array2string($entry).") Cant create etag!");
return false;
}
- return '"'.$entry['id'].':'.(isset($entry['etag']) ? $entry['etag'] : $entry['modified']).'"';
+ return 'EGw-'.$entry['id'].':'.(isset($entry['etag']) ? $entry['etag'] : $entry['modified']).'-wGE';
}
/**
@@ -214,7 +223,7 @@ abstract class groupdav_handler
*/
static function etag2value($etag)
{
- list(,$val) = explode(':',substr($etag,1,-1),2);
+ list(,$val) = explode(':',substr($etag,4,-4),2);
return $val;
}
@@ -278,6 +287,7 @@ abstract class groupdav_handler
*
* @static
* @param string $app 'calendar', 'addressbook' or 'infolog'
+ * @param int $user=null owner of the collection, default current user
* @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
@@ -297,7 +307,9 @@ abstract class groupdav_handler
$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)");
+
+ if ($debug) error_log(__METHOD__."('$app', '$base_uri', '$principalURL')");
+
return $handler_cache[$app];
}
@@ -317,6 +329,7 @@ abstract class groupdav_handler
$user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
foreach(array(
'davkit' => 'davkit', // Apple iCal
+ 'cfnetwork' => 'cfnetwork', // Apple Addressbook
'bionicmessage.net' => 'funambol', // funambol GroupDAV connector from bionicmessage.net
'zideone' => 'zideone', // zideone outlook plugin
'lightning' => 'lightning', // Lighting (SOGo connector for addressbook)
@@ -356,6 +369,13 @@ abstract class groupdav_handler
*/
class groupdav_propfind_iterator implements Iterator
{
+ /**
+ * current path
+ *
+ * @var string
+ */
+ protected $path;
+
/**
* Handler to call for entries
*
@@ -375,8 +395,16 @@ class groupdav_propfind_iterator implements Iterator
*
* @var array
*/
+ protected $common_files;
+
+ /**
+ * current chunk
+ *
+ * @var array
+ */
protected $files;
+
/**
* Start value for callback
*
@@ -397,6 +425,8 @@ class groupdav_propfind_iterator implements Iterator
*/
public $debug = false;
+ /**
+
/**
* Constructor
*
@@ -404,13 +434,14 @@ class groupdav_propfind_iterator implements Iterator
* @param array $filter filter for propfind call
* @param array $files=null extra files/responses to return too
*/
- public function __construct(groupdav_handler $handler,array $filter,array &$files=null)
+ public function __construct(groupdav_handler $handler, $path, array $filter,array &$files=null)
{
- if ($this->debug) error_log(__METHOD__."(,".array2string($filter).",)");
-
+ if ($this->debug) error_log(__METHOD__."('$path', ".array2string($filter).",)");
+ $this->path = $path;
$this->handler = $handler;
$this->filter = $filter;
$this->files = $files;
+ $this->common_files = $files;
reset($this->files);
}
@@ -422,7 +453,6 @@ class groupdav_propfind_iterator implements Iterator
public function current()
{
if ($this->debug) error_log(__METHOD__."() returning ".array2string(current($this->files)));
-
return current($this->files);
}
@@ -447,21 +477,20 @@ class groupdav_propfind_iterator implements Iterator
if (next($this->files) !== false)
{
if ($this->debug) error_log(__METHOD__."() returning TRUE");
-
return true;
}
- if (is_array($this->files) && count($this->files) < self::CHUNK_SIZE) // less entries then asked --> no further available
+ if (is_array($this->files) && count($this->files) < self::CHUNK_SIZE) // less entries then asked --> no further available
{
if ($this->debug) error_log(__METHOD__."() returning FALSE (no more entries)");
-
return false; // no further entries
}
// try query further files via propfind callback of handler and store result in $this->files
- $this->files = $this->handler->propfind_callback($this->filter,array($this->start,self::CHUNK_SIZE));
+ $this->files = $this->handler->propfind_callback($this->path,$this->filter,array($this->start,self::CHUNK_SIZE));
$this->start += self::CHUNK_SIZE;
reset($this->files);
if ($this->debug) error_log(__METHOD__."() returning ".array2string(current($this->files) !== false));
+
return current($this->files) !== false;
}
@@ -474,7 +503,8 @@ class groupdav_propfind_iterator implements Iterator
// query first set of files via propfind callback of handler and store result in $this->files
$this->start = 0;
- $this->files = $this->handler->propfind_callback($this->filter,array($this->start,self::CHUNK_SIZE));
+ $files = $this->handler->propfind_callback($this->path,$this->filter,array($this->start,self::CHUNK_SIZE));
+ $this->files = $this->common_files + $files;
$this->start += self::CHUNK_SIZE;
reset($this->files);
}
diff --git a/phpgwapi/inc/class.groupdav_principals.inc.php b/phpgwapi/inc/class.groupdav_principals.inc.php
index 61d49e426b..ab767243bc 100644
--- a/phpgwapi/inc/class.groupdav_principals.inc.php
+++ b/phpgwapi/inc/class.groupdav_principals.inc.php
@@ -7,7 +7,7 @@
* @package api
* @subpackage groupdav
* @author Ralf Becker
- * @copyright (c) 2008 by Ralf Becker
+ * @copyright (c) 2008-10 by Ralf Becker
* @version $Id$
*/
@@ -16,12 +16,6 @@
*/
class groupdav_principals extends groupdav_handler
{
- /**
- * Reference to the accounts class
- *
- * @var accounts
- */
- var $accounts;
/**
* Constructor
@@ -34,8 +28,6 @@ class groupdav_principals extends groupdav_handler
function __construct($app,$debug=null,$base_uri=null,$principalURL=null)
{
parent::__construct($app,$debug,$base_uri,$principalURL);
-
- $this->accounts = $GLOBALS['egw']->accounts;
}
/**
@@ -49,10 +41,41 @@ class groupdav_principals extends groupdav_handler
*/
function propfind($path,$options,&$files,$user)
{
- if ($this->debug) error_log(__METHOD__."($path,".array2string($options).",,$user,$id)");
+ list(,$principals,$type,$name,$rest) = explode('/',$path,5);
+ // /principals/users/$name/
+ // /users/$name/calendar-proxy-read/
+ // /users/$name/calendar-proxy-write/
+ // /groups/$name/
+ // /resources/$resource/
+ // /__uids__/$uid/.../
+
+ switch($type)
+ {
+ case 'users':
+ $files['files'] = $this->propfind_users($name,$rest,$options);
+ break;
+ case 'groups':
+ $files['files'] = $this->propfind_groups($name,$rest,$options);
+ break;
+ case 'resources':
+ $files['files'] = $this->propfind_resources($name,$rest,$options);
+ break;
+ case '__uids__':
+ $files['files'] = $this->propfind_uids($name,$rest,$options);
+ break;
+ case '':
+ $files['files'] = $this->propfind_principals($options);
+ break;
+ default:
+ return '404 Not Found';
+ }
+ if (!is_array($files['files']))
+ {
+ return $files['files'];
+ }
+ return true;
list(,,$id) = explode('/',$path);
-
if ($id && !($id = $this->accounts->id2name($id)))
{
return false;
@@ -61,31 +84,18 @@ class groupdav_principals extends groupdav_handler
{
$displayname = $GLOBALS['egw']->translation->convert($account['account_fullname'],
$GLOBALS['egw']->translation->charset(),'utf-8');
- if ($options['root']['name'] == 'principal-search-property-set')
+ $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('principal-URL',$this->base_uri.'/principals/'.$account['account_lid']),
+ HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-home-set',$this->base_uri.$account['account_lid'].'/calendar/'),
+ HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-user-address-set','MAILTO:'.$account['account_email']),
+ );
+ foreach($this->accounts->memberships($account['account_id']) as $gid => $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);
- }
+ $props[] = HTTP_WebDAV_Server::mkprop('group-membership',$this->base_uri.'/groups/'.$group);
}
$files['files'][] = array(
'path' => '/principals/'.$account['account_lid'],
@@ -93,7 +103,250 @@ class groupdav_principals extends groupdav_handler
);
if ($this->debug > 1) error_log(__METHOD__."($path) path=/principals/".$account['account_lid'].', props='.array2string($props));
}
- return true;
+ return files;
+ }
+
+ /**
+ * Do propfind in /pricipals/users
+ *
+ * @param string $name name of account or empty
+ * @param string $rest rest of path behind account-name
+ * @param array $options
+ * @return array|string array with files or HTTP error code
+ */
+ protected function propfind_users($name,$rest,array $options)
+ {
+ //echo "".__METHOD__."($name,$rest,".array2string($options).")
\n";
+ if (empty($name))
+ {
+ $files = array();
+ // add /pricipals/users/ entry
+ $files[] = $this->add_collection('/principals/users/',array(
+ HTTP_WebDAV_Server::mkprop('current-user-principal',array(
+ HTTP_WebDAV_Server::mkprop('href',$this->base_uri.'/principals/'.$GLOBALS['egw_info']['user']['account_lid'].'/'))),
+ ));
+ if ($options['depth'])
+ {
+ // add all users
+ foreach($this->accounts->search(array('type' => 'accounts')) as $account)
+ {
+ $files[] = $this->add_account($account);
+ }
+ }
+ }
+ else
+ {
+ if (!($id = $GLOBALS['egw']->accounts->name2id($name,'account_lid','u')) ||
+ !($account = $GLOBALS['egw']->accounts->read($id)))
+ {
+ return '404 Not Found';
+ }
+ switch((string)$rest)
+ {
+ case '':
+ $files[] = $this->add_account($account);
+ $files[] = $this->add_collection('/principals/users/'.$account['account_lid'].'/calendar-proxy-read');
+ $files[] = $this->add_collection('/principals/users/'.$account['account_lid'].'/calendar-proxy-write');
+ break;
+ case 'calendar-proxy-read':
+ case 'calendar-proxy-write':
+ $files = array();
+ $files[] = $this->add_collection('/principals/users/'.$account['account_lid'].'/'.$rest);
+ // add proxys
+ break;
+ default:
+ return '404 Not Found';
+ }
+ }
+ return $files;
+ }
+
+ /**
+ * Do propfind in /pricipals/groups
+ *
+ * @param string $name name of group or empty
+ * @param string $rest rest of path behind account-name
+ * @param array $options
+ * @return array|string array with files or HTTP error code
+ */
+ protected function propfind_groups($name,$rest,array $options)
+ {
+ //echo "".__METHOD__."($name,$rest,".array2string($options).")
\n";
+ if (empty($name))
+ {
+ $files = array();
+ // add /pricipals/users/ entry
+ $files[] = $this->add_collection('/principals/groups/',array(
+ HTTP_WebDAV_Server::mkprop('current-user-principal',array(
+ HTTP_WebDAV_Server::mkprop('href',$this->base_uri.'/principals/'.$GLOBALS['egw_info']['user']['account_lid'].'/'))),
+ ));
+ if ($options['depth'])
+ {
+ // add all users
+ foreach($this->accounts->search(array('type' => 'groups')) as $account)
+ {
+ $files[] = $this->add_group($account);
+ }
+ }
+ }
+ else
+ {
+ if (!($id = $GLOBALS['egw']->accounts->name2id($name,'account_lid','g')) ||
+ !($account = $GLOBALS['egw']->accounts->read($id)))
+ {
+ return '404 Not Found';
+ }
+ switch((string)$rest)
+ {
+ case '':
+ $files[] = $this->add_group($account);
+ $files[] = $this->add_collection('/principals/groups/'.$account['account_lid'].'/calendar-proxy-read');
+ $files[] = $this->add_collection('/principals/groups/'.$account['account_lid'].'/calendar-proxy-write');
+ break;
+ case 'calendar-proxy-read':
+ case 'calendar-proxy-write':
+ $files = array();
+ $files[] = $this->add_collection('/principals/groups/'.$account['account_lid'].'/'.$rest);
+ // add proxys
+ break;
+ default:
+ return '404 Not Found';
+ }
+ }
+ return $files;
+ }
+
+ /**
+ * Add collection of a single account to a collection
+ *
+ * @param array $account
+ * @return array with values for keys 'path' and 'props'
+ */
+ protected function add_account(array $account)
+ {
+ //echo "".__METHOD__."(".array2string($account).")
\n";
+ $displayname = $GLOBALS['egw']->translation->convert($account['account_fullname'],
+ $GLOBALS['egw']->translation->charset(),'utf-8');
+ $memberships = array();
+ foreach($this->accounts->memberships($account['account_id']) as $gid => $group)
+ {
+ if ($group)
+ {
+ $memberships[] = HTTP_WebDAV_Server::mkprop('href',
+ $this->base_uri.'/principals/groups/'.$group);
+ }
+ }
+ $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',array(
+ HTTP_WebDAV_Server::mkprop('href','MAILTO:'.$account['account_email']))),
+ HTTP_WebDAV_Server::mkprop('principal-URL',$this->base_uri.'/principals/users/'.$account['account_lid'].'/'),
+ 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',array(
+ HTTP_WebDAV_Server::mkprop('href','MAILTO:'.$account['account_email']))),
+ HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'addressbook-home-set',array(
+ HTTP_WebDAV_Server::mkprop('href',$this->base_uri.'/'.$account['account_lid'].'/'))),
+ HTTP_WebDAV_Server::mkprop('group-member-ship', $memberships),
+ HTTP_WebDAV_Server::mkprop('principal-URL',array(self::mkprop('href',$this->principalURL))),
+ );
+ if ($this->debug > 1) error_log(__METHOD__."($path) path=/principals/users/".$account['account_lid'].', props='.array2string($props));
+ return array(
+ 'path' => '/principals/users/'.$account['account_lid'].'/',
+ 'props' => $props,
+ );
+ }
+
+ /**
+ * Add collection of a single group to a collection
+ *
+ * @param array $account
+ * @return array with values for keys 'path' and 'props'
+ */
+ protected function add_group(array $account)
+ {
+ $displayname = $GLOBALS['egw']->translation->convert(lang('Group').' '.$account['account_lid'],
+ $GLOBALS['egw']->translation->charset(),'utf-8');
+ $members = array();
+ foreach($this->accounts->members($account['account_id']) as $gid => $user)
+ {
+ if ($user)
+ {
+ $members[] = HTTP_WebDAV_Server::mkprop('href',
+ $this->base_uri.'/principals/users/'.$user);
+ }
+ }
+ $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(groupdav::CALDAV,'calendar-home-set',array(
+ HTTP_WebDAV_Server::mkprop('href',$this->base_uri.'/'.$account['account_lid'].'/calendar/'))),
+ HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'addressbook-home-set',array(
+ HTTP_WebDAV_Server::mkprop('href',$this->base_uri.'/'.$account['account_lid'].'/'))),
+ HTTP_WebDAV_Server::mkprop('group-member-set', $members),
+ //HTTP_WebDAV_Server::mkprop('principal-URL',array(self::mkprop('href',$this->principalURL))),
+ );
+ $files['files'][] = array(
+ 'path' => '/principals/groups/'.$account['account_lid'].'/',
+ 'props' => $props,
+ );
+ if ($this->debug > 1) error_log(__METHOD__."($path) path=/principals/groups/".$account['account_lid'].', props='.array2string($props));
+ return array(
+ 'path' => '/principals/groups/'.$account['account_lid'].'/',
+ 'props' => $props,
+ );
+ }
+
+ /**
+ * Add a collection
+ *
+ * @param string $path
+ * @param array $props=array() extra properties 'resourcetype' is added anyway
+ * @return array
+ */
+ protected function add_collection($path,$props=array())
+ {
+ //echo "".__METHOD__."($path,".array($props).")
\n";
+ $props[] = HTTP_WebDAV_Server::mkprop('resourcetype',array(
+ HTTP_WebDAV_Server::mkprop('collection',''),
+ HTTP_WebDAV_Server::mkprop('resourcetype','principal'),
+ ));
+ return array(
+ 'path' => $path,
+ 'props' => $props,
+ );
+ }
+
+ /**
+ * Do propfind of /pricipals
+ *
+ * @param string $name name of group or empty
+ * @param string $rest name of rest of path behind group-name
+ * @param array $options
+ * @return array|string array with files or HTTP error code
+ */
+ protected function propfind_principals(array $options)
+ {
+ //echo "".__METHOD__."(".array($options).")
\n";
+ $files = array();
+ $files[] = $this->add_collection('/principals/',array(
+ HTTP_WebDAV_Server::mkprop('current-user-principal',array(
+ HTTP_WebDAV_Server::mkprop('href',$this->base_uri.'/principals/users/'.$GLOBALS['egw_info']['user']['account_lid'].'/'))),
+ ));
+
+ if ($options['depth'])
+ {
+ $options['depth'] = 0;
+ $files = array_merge($files,$this->propfind_users('','',$options));
+ $files = array_merge($files,$this->propfind_groups('','',$options));
+ //$files = array_merge($this->propfind_resources('','',$options));
+ //$files = array_merge($this->propfind_uids('','',$options));
+ }
+ return $files;
}
/**
@@ -109,12 +362,12 @@ class groupdav_principals extends groupdav_handler
{
return $account;
}
- $displayname = $GLOBALS['egw']->translation->convert(
+ $name = $GLOBALS['egw']->translation->convert(
trim($account['account_firstname'].' '.$account['account_lastname']),
$GLOBALS['egw']->translation->charset(),'utf-8');
$options['data'] = 'Principal: '.$account['account_lid'].
"\nURL: ".$this->base_uri.$options['path'].
- "\nName: ".$displayname.
+ "\nName: ".$name.
"\nEmail: ".$account['account_email'].
"\nMemberships: ".implode(', ',$this->accounts->memberships($id))."\n";
$options['mimetype'] = 'text/plain; charset=utf-8';
@@ -156,7 +409,8 @@ class groupdav_principals extends groupdav_handler
*/
function read($id)
{
- return $this->accounts->read($id);
+ return false;
+ //return $this->accounts->read($id);
}
/**
@@ -191,6 +445,6 @@ class groupdav_principals extends groupdav_handler
{
$account = $this->read($account);
}
- return '"'.$account['account_id'].':'.md5(serialize($account)).'"';
+ return 'EGw-'.$account['account_id'].':'.md5(serialize($account)).'-wGE';
}
}
\ No newline at end of file
diff --git a/phpgwapi/inc/class.vfs_webdav_server.inc.php b/phpgwapi/inc/class.vfs_webdav_server.inc.php
index d1b60fa737..12d425b8bc 100644
--- a/phpgwapi/inc/class.vfs_webdav_server.inc.php
+++ b/phpgwapi/inc/class.vfs_webdav_server.inc.php
@@ -263,7 +263,8 @@ class vfs_webdav_server extends HTTP_WebDAV_Server_Filesystem
// type and size (caller already made sure that path exists)
if (is_dir($fspath)) {
// directory (WebDAV collection)
- $info['props'][] = HTTP_WebDAV_Server::mkprop ('resourcetype', 'collection');
+ $info['props'][] = HTTP_WebDAV_Server::mkprop ('resourcetype', array(
+ HTTP_WebDAV_Server::mkprop('collection', '')));
$info['props'][] = HTTP_WebDAV_Server::mkprop ('getcontenttype', 'httpd/unix-directory');
} else {
// plain file (WebDAV resource)