mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-25 16:19:00 +01:00
* CalDAV: store name part of URL from client PUT request, to fully comply with CalDAV spec
This commit is contained in:
parent
3825fecf6d
commit
0bfd238e3f
@ -1,12 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* eGroupWare - Calendar's buisness-object - access only
|
||||
* EGroupware - Calendar's buisness-object - access only
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @package calendar
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @author Joerg Lehrke <jlehrke@noc.de>
|
||||
* @copyright (c) 2004-9 by RalfBecker-At-outdoor-training.de
|
||||
* @copyright (c) 2004-11 by RalfBecker-At-outdoor-training.de
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
@ -1,12 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* eGroupWare - Calendar's buisness-object - access + update
|
||||
* EGroupware - Calendar's buisness-object - access + update
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @package calendar
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @author Joerg Lehrke <jlehrke@noc.de>
|
||||
* @copyright (c) 2005-10 by RalfBecker-At-outdoor-training.de
|
||||
* @copyright (c) 2005-11 by RalfBecker-At-outdoor-training.de
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
@ -1,13 +1,13 @@
|
||||
<?php
|
||||
/**
|
||||
* eGroupWare: GroupDAV access: calendar handler
|
||||
* EGroupware: CalDAV / GroupDAV access: calendar handler
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package calendar
|
||||
* @subpackage groupdav
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2007-9 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2007-11 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
@ -57,9 +57,11 @@ class calendar_groupdav extends groupdav_handler
|
||||
var $client_shared_uid_exceptions = true;
|
||||
|
||||
/**
|
||||
* Are we using id or uid for the path/url
|
||||
* Are we using id, uid or caldav_name for the path/url
|
||||
*
|
||||
* Get's set in constructor to 'caldav_name' and groupdav_handler::$path_extension = ''!
|
||||
*/
|
||||
const PATH_ATTRIBUTE = 'id';
|
||||
static $path_attr = 'id';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@ -75,6 +77,13 @@ class calendar_groupdav extends groupdav_handler
|
||||
|
||||
$this->bo = new calendar_boupdate();
|
||||
$this->vCalendar = new Horde_iCalendar;
|
||||
|
||||
// since 1.9.003 we allow clients to specify the URL when creating a new event, as specified by CalDAV
|
||||
if (version_compare($GLOBALS['egw_info']['apps']['calendar']['version'], '1.9.003', '>='))
|
||||
{
|
||||
self::$path_attr = 'caldav_name';
|
||||
groupdav_handler::$path_extension = '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -85,16 +94,18 @@ class calendar_groupdav extends groupdav_handler
|
||||
*/
|
||||
function get_path($event)
|
||||
{
|
||||
if (is_numeric($event) && self::PATH_ATTRIBUTE == 'id')
|
||||
if (is_numeric($event) && self::$path_attr == 'id')
|
||||
{
|
||||
$name = $event;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!is_array($event)) $event = $this->bo->read($event);
|
||||
$name = $event[self::PATH_ATTRIBUTE];
|
||||
$name = $event[self::$path_attr];
|
||||
}
|
||||
return $name.'.ics';
|
||||
$name .= groupdav_handler::$path_extension;
|
||||
//error_log(__METHOD__.'('.array2string($event).") path_attr='".self::$path_attr."', path_extension='".groupdav_handler::$path_extension."' returning ".array2string($name));
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -332,15 +343,8 @@ class calendar_groupdav extends groupdav_handler
|
||||
|
||||
if ($id)
|
||||
{
|
||||
if (is_numeric($id))
|
||||
{
|
||||
$ids[] = (int)$id;
|
||||
}
|
||||
else
|
||||
{
|
||||
$cal_filters['query']['cal_uid'] = basename($id,'.ics');
|
||||
}
|
||||
|
||||
$cal_filters['query'][self::$path_attr] = groupdav_handler::$path_extension ?
|
||||
basename($id,groupdav_handler::$path_extension) : $id;
|
||||
}
|
||||
else // fetch all given url's
|
||||
{
|
||||
@ -349,23 +353,14 @@ class calendar_groupdav extends groupdav_handler
|
||||
if ($option['name'] == 'href')
|
||||
{
|
||||
$parts = explode('/',$option['data']);
|
||||
if (!($id = basename(array_pop($parts),'.ics'))) continue;
|
||||
|
||||
if (is_numeric($id))
|
||||
if (($id = array_pop($parts)))
|
||||
{
|
||||
$ids[] = $id;
|
||||
}
|
||||
else // eg. lightning uses multiget after a PUT on the PUT url, which is the uid
|
||||
{
|
||||
$cal_filters['query']['cal_uid'][] = $id;
|
||||
$cal_filters['query'][self::$path_attr][] = groupdav_handler::$path_extension ?
|
||||
basename($id,groupdav_handler::$path_extension) : $id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($ids)
|
||||
{
|
||||
$cal_filters['query'][] = 'egw_cal.cal_id IN ('.implode(',',array_map(create_function('$n','return (int)$n;'),$ids)).')';
|
||||
}
|
||||
|
||||
if ($this->debug > 1) error_log(__FILE__ . __METHOD__ ."($options[path],...,$id) calendar-multiget: ids=".implode(',',$ids).', cal_filters='.array2string($cal_filters));
|
||||
}
|
||||
@ -573,32 +568,13 @@ class calendar_groupdav extends groupdav_handler
|
||||
}
|
||||
else
|
||||
{
|
||||
// new entry?
|
||||
if (($foundEvents = $handler->search($vCalendar, null, false, $charset)))
|
||||
{
|
||||
if (($eventId = array_shift($foundEvents)) &&
|
||||
(list($eventId) = explode(':', $eventId)) &&
|
||||
($oldEvent = $this->bo->read($eventId)))
|
||||
{
|
||||
$retval = '301 Moved Permanently';
|
||||
}
|
||||
else
|
||||
{
|
||||
// to be safe
|
||||
$eventId = -1;
|
||||
$retval = '201 Created';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// new entry
|
||||
$eventId = -1;
|
||||
$retval = '201 Created';
|
||||
}
|
||||
// new entry
|
||||
$eventId = -1;
|
||||
$retval = '201 Created';
|
||||
}
|
||||
|
||||
if (!($cal_id = $handler->importVCal($vCalendar, $eventId,
|
||||
self::etag2value($this->http_if_match), false, 0, $this->principalURL, $user, $charset)))
|
||||
self::etag2value($this->http_if_match), false, 0, $this->principalURL, $user, $charset, $id)))
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."(,$id) eventId=$eventId: importVCal('$options[content]') returned false");
|
||||
if ($eventId && $cal_id === false)
|
||||
@ -614,14 +590,15 @@ class calendar_groupdav extends groupdav_handler
|
||||
}
|
||||
|
||||
header('ETag: '.$this->get_etag($cal_id));
|
||||
if ($retval !== true)
|
||||
|
||||
// send GroupDAV Location header only if we dont use caldav_name as path-attribute
|
||||
if ($retval !== true && self::$path_attr != 'caldav_name')
|
||||
{
|
||||
$path = preg_replace('|(.*)/[^/]*|', '\1/', $options['path']);
|
||||
if ($this->debug) error_log(__METHOD__."(,$id,$user) cal_id=$cal_id: $retval");
|
||||
header('Location: '.$this->base_uri.$path.$this->get_path($cal_id));
|
||||
return $retval;
|
||||
}
|
||||
return true;
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -773,18 +750,22 @@ class calendar_groupdav extends groupdav_handler
|
||||
}
|
||||
return $event;
|
||||
}
|
||||
return $this->bo->delete($id);
|
||||
return $this->bo->delete($event['id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an entry
|
||||
*
|
||||
* @param string/id $id
|
||||
* @return array/boolean array with entry, false if no read rights, null if $id does not exist
|
||||
* @param string|id $id
|
||||
* @return array|boolean array with entry, false if no read rights, null if $id does not exist
|
||||
*/
|
||||
function read($id)
|
||||
{
|
||||
$event = $this->bo->read($id, null, true, 'server');
|
||||
if (strpos($column=self::$path_attr,'_') === false) $column = 'cal_'.$column;
|
||||
|
||||
$event = $this->bo->read(array($column => $id), null, true, 'server');
|
||||
if ($event) $event = array_shift($event); // read with array as 1. param, returns an array of events!
|
||||
|
||||
if (!($retval = $this->bo->check_perms(EGW_ACL_FREEBUSY,$event, 0, 'server')))
|
||||
{
|
||||
if ($this->debug > 0) error_log(__METHOD__."($id) no READ or FREEBUSY rights returning ".array2string($retval));
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* iCal import and export via Horde iCalendar classes
|
||||
* EGroupware - Calendar iCal import and export via Horde iCalendar classes
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Lars Kneschke <lkneschke@egroupware.org>
|
||||
@ -1078,10 +1078,12 @@ class calendar_ical extends calendar_boupdate
|
||||
* @param int $user=null account_id of owner, default null
|
||||
* @param string $charset The encoding charset for $text. Defaults to
|
||||
* utf-8 for new format, iso-8859-1 for old format.
|
||||
* @param string $caldav_name=null name from CalDAV client or null (to use default)
|
||||
* @return int|boolean cal_id > 0 on success, false on failure or 0 for a failed etag|permission denied
|
||||
*/
|
||||
function importVCal($_vcalData, $cal_id=-1, $etag=null, $merge=false, $recur_date=0, $principalURL='', $user=null, $charset=null)
|
||||
function importVCal($_vcalData, $cal_id=-1, $etag=null, $merge=false, $recur_date=0, $principalURL='', $user=null, $charset=null, $caldav_name=null)
|
||||
{
|
||||
//error_log(__METHOD__."(, $cal_id, $etag, $merge, $recur_date, $principalURL, $user, $charset, $caldav_name)");
|
||||
$this->events_imported = 0;
|
||||
$replace = $delete_exceptions= false;
|
||||
|
||||
@ -1336,10 +1338,12 @@ class calendar_ical extends calendar_boupdate
|
||||
// avoid that iCal changes the organizer, which is not allowed
|
||||
$event['owner'] = $event_info['stored_event']['owner'];
|
||||
}
|
||||
$event['caldav_name'] = $event_info['stored_event']['caldav_name'];
|
||||
}
|
||||
else // common adjustments for new events
|
||||
{
|
||||
unset($event['id']);
|
||||
if ($caldav_name) $event['caldav_name'] = $caldav_name;
|
||||
// set non blocking all day depending on the user setting
|
||||
if (!empty($event['whole_day']) && $this->nonBlockingAllday)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* eGroupWare - Calendar's storage-object
|
||||
* EGroupware - Calendar's storage-object
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @package calendar
|
||||
@ -121,7 +121,7 @@ class calendar_so
|
||||
*
|
||||
* @param int|array|string $ids id or array of id's of the entries to read, or string with a single uid
|
||||
* @param int $recur_date=0 if set read the next recurrence at or after the timestamp, default 0 = read the initital one
|
||||
* @return array|boolean array with id => data pairs or false if entry not found
|
||||
* @return array|boolean array with cal_id => event array pairs or false if entry not found
|
||||
*/
|
||||
function read($ids,$recur_date=0)
|
||||
{
|
||||
@ -142,23 +142,28 @@ class calendar_so
|
||||
$group_by_cols .= ','.$this->repeats_table.'.'.implode(','.$this->repeats_table.'.',array_keys($table_def['fd']));
|
||||
|
||||
$where = array();
|
||||
if (is_array($ids))
|
||||
{
|
||||
array_walk($ids,create_function('&$val,$key','$val = (int) $val;'));
|
||||
|
||||
$where[] = $this->cal_table.'.cal_id IN ('.implode(',',$ids).')';
|
||||
}
|
||||
elseif (is_numeric($ids))
|
||||
{
|
||||
$where[] = $this->cal_table.'.cal_id = '.(int) $ids;
|
||||
}
|
||||
else
|
||||
if (is_scalar($ids) && !is_numeric($ids)) // a single uid
|
||||
{
|
||||
// We want only the parents to match
|
||||
$where['cal_uid'] = $ids;
|
||||
$where['cal_reference'] = 0;
|
||||
$where['cal_recurrence'] = 0;
|
||||
}
|
||||
elseif(is_array($ids) && isset($ids[count($ids)-1]) || is_scalar($ids)) // one or more cal_id's
|
||||
{
|
||||
$where['cal_id'] = $ids;
|
||||
}
|
||||
else // array with column => value pairs
|
||||
{
|
||||
$where = $ids;
|
||||
}
|
||||
if (isset($where['cal_id'])) // prevent non-unique column-name cal_id
|
||||
{
|
||||
$where[] = $this->db->expression($this->cal_table, $this->cal_table.'.',array(
|
||||
'cal_id' => $where['cal_id'],
|
||||
));
|
||||
unset($where['cal_id']);
|
||||
}
|
||||
if ((int) $recur_date)
|
||||
{
|
||||
$where[] = 'cal_start >= '.(int)$recur_date;
|
||||
@ -920,7 +925,7 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
// add colum prefix 'cal_' if there's not already a 'recur_' prefix
|
||||
foreach($event as $col => $val)
|
||||
{
|
||||
if ($col[0] != '#' && substr($col,0,6) != 'recur_' && $col != 'alarm' && $col != 'tz_id')
|
||||
if ($col[0] != '#' && substr($col,0,6) != 'recur_' && $col != 'alarm' && $col != 'tz_id' && $col != 'caldav_name')
|
||||
{
|
||||
$event['cal_'.$col] = $val;
|
||||
unset($event[$col]);
|
||||
@ -975,12 +980,20 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
}
|
||||
$etag = 0;
|
||||
}
|
||||
$update = array();
|
||||
// event without uid or not strong enough uid
|
||||
if (!isset($event['cal_uid']) || strlen($event['cal_uid']) < $minimum_uid_length)
|
||||
{
|
||||
// event (without uid), not strong enough uid
|
||||
$event['cal_uid'] = $GLOBALS['egw']->common->generate_uid('calendar',$cal_id);
|
||||
$this->db->update($this->cal_table, array('cal_uid' => $event['cal_uid']),
|
||||
array('cal_id' => $cal_id),__LINE__,__FILE__,'calendar');
|
||||
$update['cal_uid'] = $event['cal_uid'] = $GLOBALS['egw']->common->generate_uid('calendar',$cal_id);
|
||||
}
|
||||
// set caldav_name, if not given by caller
|
||||
if (empty($event['caldav_name']) && version_compare($GLOBALS['egw_info']['apps']['calendar']['version'], '1.9.003', '>='))
|
||||
{
|
||||
$update['caldav_name'] = $event['caldav_name'] = $cal_id.'.ics';
|
||||
}
|
||||
if ($update)
|
||||
{
|
||||
$this->db->update($this->cal_table, $update, array('cal_id' => $cal_id),__LINE__,__FILE__,'calendar');
|
||||
}
|
||||
|
||||
if ($event['recur_type'] == MCAL_RECUR_NONE)
|
||||
|
@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
$setup_info['calendar']['name'] = 'calendar';
|
||||
$setup_info['calendar']['version'] = '1.9.002';
|
||||
$setup_info['calendar']['version'] = '1.9.003';
|
||||
$setup_info['calendar']['app_order'] = 3;
|
||||
$setup_info['calendar']['enable'] = 1;
|
||||
$setup_info['calendar']['index'] = 'calendar.calendar_uiviews.index';
|
||||
@ -66,6 +66,3 @@ $setup_info['calendar']['check_install'] = array(
|
||||
'from' => 'Calendar',
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
@ -31,11 +31,12 @@ $phpgw_baseline = array(
|
||||
'cal_created' => array('type' => 'int','precision' => '8','nullable' => False,'comment' => 'creation time of event'),
|
||||
'cal_recurrence' => array('type' => 'int','precision' => '8','nullable' => False,'default' => '0','comment' => 'cal_start of original recurrence for exception'),
|
||||
'tz_id' => array('type' => 'int','precision' => '4','comment' => 'key into egw_cal_timezones'),
|
||||
'cal_deleted' => array('type' => 'int','precision' => '8','comment' => 'ts when event was deleted')
|
||||
'cal_deleted' => array('type' => 'int','precision' => '8','comment' => 'ts when event was deleted'),
|
||||
'caldav_name' => array('type' => 'varchar','precision' => '64','comment' => 'name part of CalDAV URL, if specified by client')
|
||||
),
|
||||
'pk' => array('cal_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array('cal_uid','cal_owner','cal_deleted'),
|
||||
'ix' => array('cal_uid','cal_owner','cal_deleted','caldav_name'),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_cal_holidays' => array(
|
||||
|
@ -2094,7 +2094,7 @@ function calendar_upgrade1_7_011()
|
||||
{
|
||||
return $GLOBALS['setup_info']['calendar']['currentver'] = '1.9.001';
|
||||
}
|
||||
|
||||
|
||||
function calendar_upgrade1_8()
|
||||
{
|
||||
calendar_upgrade1_7_010();
|
||||
@ -2104,7 +2104,7 @@ function calendar_upgrade1_8()
|
||||
|
||||
/**
|
||||
* Convert bool column cal_deleted with egw_api_content_history table to a unix timestamp
|
||||
*
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function calendar_upgrade1_9_001()
|
||||
@ -2152,3 +2152,23 @@ function calendar_upgrade1_9_001()
|
||||
return $GLOBALS['setup_info']['calendar']['currentver'] = '1.9.002';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add column to store CalDAV name given by client
|
||||
*/
|
||||
function calendar_upgrade1_9_002()
|
||||
{
|
||||
$GLOBALS['egw_setup']->oProc->AddColumn('egw_cal','caldav_name',array(
|
||||
'type' => 'varchar',
|
||||
'precision' => '64',
|
||||
'comment' => 'name part of CalDAV URL, if specified by client'
|
||||
));
|
||||
$GLOBALS['egw_setup']->db->query($sql='UPDATE egw_cal SET caldav_name='.
|
||||
$GLOBALS['egw_setup']->db->concat(
|
||||
$GLOBALS['egw_setup']->db->to_varchar('cal_id'),"'.ics'"),__LINE__,__FILE__);
|
||||
|
||||
$GLOBALS['egw_setup']->oProc->CreateIndex('egw_cal','caldav_name');
|
||||
|
||||
return $GLOBALS['setup_info']['calendar']['currentver'] = '1.9.003';
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user