mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-26 01:43:47 +01:00
* CardDAV: store name part of URL from client PUT request, to fully comply with CardDAV spec
This commit is contained in:
parent
ca7dfd3370
commit
87ee0f0088
@ -7,7 +7,7 @@
|
||||
* @package addressbook
|
||||
* @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$
|
||||
*/
|
||||
|
||||
@ -77,9 +77,11 @@ class addressbook_groupdav extends groupdav_handler
|
||||
var $charset = 'utf-8';
|
||||
|
||||
/**
|
||||
* What attribute is used to construct the path, default id, can be uid too
|
||||
* Which attribute to use to contruct name part of url/path
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const PATH_ATTRIBUTE = 'id';
|
||||
static $path_attr = 'id';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@ -94,6 +96,18 @@ class addressbook_groupdav extends groupdav_handler
|
||||
parent::__construct($app,$debug,$base_uri,$principalURL);
|
||||
|
||||
$this->bo = new addressbook_bo();
|
||||
|
||||
// since 1.9.007 we allow clients to specify the URL when creating a new contact, as specified by CardDAV
|
||||
if ($this->bo->account_repository != 'ldap' &&
|
||||
version_compare($GLOBALS['egw_info']['apps']['phpgwapi']['version'], '1.9.007', '>='))
|
||||
{
|
||||
self::$path_attr = 'carddav_name';
|
||||
groupdav_handler::$path_extension = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
groupdav_handler::$path_extension = '.vcf';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -104,7 +118,7 @@ class addressbook_groupdav extends groupdav_handler
|
||||
*/
|
||||
static function get_path($contact)
|
||||
{
|
||||
return $contact[self::PATH_ATTRIBUTE].'.vcf';
|
||||
return $contact[self::$path_attr].groupdav_handler::$path_extension;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,7 +183,9 @@ class addressbook_groupdav extends groupdav_handler
|
||||
unset($filter['address_data']);
|
||||
$files = array();
|
||||
// we query etag and modified, as LDAP does not have the strong sql etag
|
||||
if (($contacts =& $this->bo->search(array(),array('id','uid','etag','modified'),'egw_addressbook.contact_id','','',False,'AND',$start,$filter)))
|
||||
$cols = array('id','uid','etag','modified');
|
||||
if (!in_array(self::$path_attr,$cols)) $cols[] = self::$path_attr;
|
||||
if (($contacts =& $this->bo->search(array(),$cols,'egw_addressbook.contact_id','','',False,'AND',$start,$filter)))
|
||||
{
|
||||
foreach($contacts as &$contact)
|
||||
{
|
||||
@ -258,15 +274,18 @@ class addressbook_groupdav extends groupdav_handler
|
||||
if ($option['name'] == 'href')
|
||||
{
|
||||
$parts = explode('/',$option['data']);
|
||||
if (($id = array_pop($parts))) $ids[] = basename($id,'.vcf');
|
||||
if (($id = array_pop($parts)))
|
||||
{
|
||||
$ids[] = groupdav_handler::$path_extension ? basename($id,groupdav_handler::$path_extension) : $id;
|
||||
}
|
||||
}
|
||||
if ($ids) $filters[self::PATH_ATTRIBUTE] = $ids;
|
||||
}
|
||||
if ($ids) $filters[self::$path_attr] = $ids;
|
||||
if ($this->debug) error_log(__METHOD__."($path,,,$user) addressbook-multiget: ids=".implode(',',$ids));
|
||||
}
|
||||
elseif ($id)
|
||||
{
|
||||
$filters[self::PATH_ATTRIBUTE] = basename($id,'.vcf');
|
||||
$filters[self::$path_attr] = groupdav_handler::$path_extension ? basename($id,groupdav_handler::$path_extension) : $id;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -337,37 +356,19 @@ class addressbook_groupdav extends groupdav_handler
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($oldContact))
|
||||
$contact = $handler->vcardtoegw($vCard, $charset);
|
||||
|
||||
if (is_array($oldContact) || ($oldContact = $this->bo->read(array('contact_uid' => $contact['uid']))))
|
||||
{
|
||||
$contactId = $oldContact['id'];
|
||||
$retval = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// new entry?
|
||||
if (($foundContacts = $handler->search($vCard, null, false, $charset)))
|
||||
{
|
||||
if (($contactId = array_shift($foundContacts)) &&
|
||||
($oldContact = $this->bo->read($contactId)))
|
||||
{
|
||||
$retval = '301 Moved Permanently';
|
||||
}
|
||||
else
|
||||
{
|
||||
// to be safe
|
||||
$contactId = -1;
|
||||
$retval = '201 Created';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// new entry
|
||||
$contactId = -1;
|
||||
$retval = '201 Created';
|
||||
}
|
||||
}
|
||||
|
||||
$contact = $handler->vcardtoegw($vCard, $charset);
|
||||
|
||||
if (is_array($contact['cat_id']))
|
||||
{
|
||||
@ -384,6 +385,11 @@ class addressbook_groupdav extends groupdav_handler
|
||||
$contact['uid'] = $oldContact['uid'];
|
||||
$contact['owner'] = $oldContact['owner'];
|
||||
$contact['private'] = $oldContact['private'];
|
||||
$contact['carddav_name'] = $oldContact['carddav_name'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$contact['carddav_name'] = $id;
|
||||
}
|
||||
// only set owner, if user is explicitly specified in URL (check via prefix, NOT for /addressbook/ !)
|
||||
if ($prefix)
|
||||
@ -415,14 +421,15 @@ class addressbook_groupdav extends groupdav_handler
|
||||
}
|
||||
|
||||
header('ETag: '.$this->get_etag($contact));
|
||||
if ($retval !== true)
|
||||
|
||||
// send GroupDAV Location header only if we dont use carddav_name as path-attribute
|
||||
if ($retval !== true && self::$path_attr == 'id')
|
||||
{
|
||||
$path = preg_replace('|(.*)/[^/]*|', '\1/', $options['path']);
|
||||
header($h='Location: '.$this->base_uri.$path.self::get_path($contact));
|
||||
if ($this->debug) error_log(__METHOD__."($method,,$id) header('$h'): $retval");
|
||||
return $retval;
|
||||
}
|
||||
return true;
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -547,18 +554,18 @@ class addressbook_groupdav extends groupdav_handler
|
||||
{
|
||||
return '412 Precondition Failed';
|
||||
}
|
||||
//return $ok;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a contact
|
||||
*
|
||||
* @param string/id $id
|
||||
* @param string|id $id
|
||||
* @return array/boolean array with entry, false if no read rights, null if $id does not exist
|
||||
*/
|
||||
function read($id)
|
||||
{
|
||||
return $this->bo->read(self::PATH_ATTRIBUTE == 'id' ? $id : array(self::PATH_ATTRIBUTE => $id));
|
||||
return $this->bo->read(array(self::$path_attr => $id));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -632,12 +632,22 @@ class addressbook_sql extends so_sql_cf
|
||||
}
|
||||
}
|
||||
|
||||
$update = array();
|
||||
// enforce a minium uid strength
|
||||
if (!$err && (!isset($this->data['uid'])
|
||||
|| strlen($this->data['uid']) < $minimum_uid_length)) {
|
||||
parent::update(array('uid' => common::generate_uid('addressbook',$this->data['id'])));
|
||||
if (!isset($this->data['uid']) || strlen($this->data['uid']) < $minimum_uid_length)
|
||||
{
|
||||
$update['uid'] = common::generate_uid('addressbook',$this->data['id']);
|
||||
//echo "<p>set uid={$this->data['uid']}, etag={$this->data['etag']}</p>";
|
||||
}
|
||||
// set carddav_name, if not given by caller
|
||||
if (empty($this->data['carddav_name']) && version_compare($GLOBALS['egw_info']['apps']['phpgwapi']['version'], '1.9.007', '>='))
|
||||
{
|
||||
$update['carddav_name'] = $this->data['id'].'.vcf';
|
||||
}
|
||||
if (!$err && $update)
|
||||
{
|
||||
parent::update($update);
|
||||
}
|
||||
return $err;
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* @package api
|
||||
* @subpackage groupdav
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2007-10 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2007-11 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
@ -122,7 +122,6 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
*/
|
||||
var $accounts;
|
||||
|
||||
|
||||
function __construct()
|
||||
{
|
||||
if (!$this->debug) $this->debug = (int)$GLOBALS['egw_info']['user']['preferences']['groupdav']['debug_level'];
|
||||
@ -966,10 +965,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
$user = $GLOBALS['egw_info']['user']['account_id'];
|
||||
}
|
||||
|
||||
if (($id = array_pop($parts)))
|
||||
{
|
||||
list($id) = explode('.',$id); // remove evtl. .ics extension
|
||||
}
|
||||
$id = array_pop($parts);
|
||||
|
||||
$ok = $id && $user && in_array($app,array('addressbook','calendar','infolog','principals'));
|
||||
if ($this->debug)
|
||||
|
@ -7,7 +7,7 @@
|
||||
* @package api
|
||||
* @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$
|
||||
*/
|
||||
|
||||
@ -78,6 +78,13 @@ abstract class groupdav_handler
|
||||
*/
|
||||
var $agent;
|
||||
|
||||
/**
|
||||
* Extension to append to url/path
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
static $path_extension = '.ics';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@ -105,7 +112,6 @@ abstract class groupdav_handler
|
||||
$this->agent = self::get_agent();
|
||||
|
||||
$this->egw_charset = translation::charset();
|
||||
$this->accounts = $GLOBALS['egw']->accounts;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -230,12 +236,14 @@ abstract class groupdav_handler
|
||||
*
|
||||
* @param string $method GET, PUT, DELETE
|
||||
* @param array &$options
|
||||
* @param int $id
|
||||
* @param int|string &$id on return self::$path_extension got removed
|
||||
* @param boolean &$return_no_access=false if set to true on call, instead of '403 Forbidden' the entry is returned and $return_no_access===false
|
||||
* @return array|string entry on success, string with http-error-code on failure, null for PUT on an unknown id
|
||||
*/
|
||||
function _common_get_put_delete($method,&$options,$id,&$return_no_access=false)
|
||||
function _common_get_put_delete($method,&$options,&$id,&$return_no_access=false)
|
||||
{
|
||||
if (self::$path_extension) $id = basename($id,self::$path_extension);
|
||||
|
||||
if ($this->app != 'principals' && !$GLOBALS['egw_info']['user']['apps'][$this->app])
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."($method,,$id) 403 Forbidden: no app rights for '$this->app'");
|
||||
@ -535,6 +543,7 @@ class groupdav_propfind_iterator implements Iterator
|
||||
|
||||
$this->start = 0;
|
||||
$this->files = $this->common_files;
|
||||
if (!$this->files) $this->next(); // otherwise valid will return false and nothing get returned
|
||||
reset($this->files);
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* @package api
|
||||
* @subpackage groupdav
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2008-10 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2008-11 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
@ -18,6 +18,12 @@
|
||||
*/
|
||||
class groupdav_principals extends groupdav_handler
|
||||
{
|
||||
/**
|
||||
* Reference to the accounts class
|
||||
*
|
||||
* @var accounts
|
||||
*/
|
||||
var $accounts;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@ -30,6 +36,8 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -12,7 +12,7 @@
|
||||
/* Basic information about this app */
|
||||
$setup_info['phpgwapi']['name'] = 'phpgwapi';
|
||||
$setup_info['phpgwapi']['title'] = 'eGroupWare API';
|
||||
$setup_info['phpgwapi']['version'] = '1.9.006';
|
||||
$setup_info['phpgwapi']['version'] = '1.9.007';
|
||||
$setup_info['phpgwapi']['versions']['current_header'] = '1.29';
|
||||
$setup_info['phpgwapi']['enable'] = 3;
|
||||
$setup_info['phpgwapi']['app_order'] = 1;
|
||||
@ -74,4 +74,3 @@ $setup_info['groupdav']['author'] = $setup_info['groupdav']['maintainer'] = arra
|
||||
$setup_info['groupdav']['license'] = 'GPL';
|
||||
$setup_info['groupdav']['hooks']['preferences'] = 'groupdav_hooks::menus';
|
||||
$setup_info['groupdav']['hooks']['settings'] = 'groupdav_hooks::settings';
|
||||
|
||||
|
@ -336,11 +336,12 @@ $phpgw_baseline = array(
|
||||
'contact_etag' => array('type' => 'int','precision' => '4','default' => '0'),
|
||||
'contact_uid' => array('type' => 'varchar','precision' => '255'),
|
||||
'adr_one_countrycode' => array('type' => 'varchar','precision' => '2'),
|
||||
'adr_two_countrycode' => array('type' => 'varchar','precision' => '2')
|
||||
'adr_two_countrycode' => array('type' => 'varchar','precision' => '2'),
|
||||
'carddav_name' => array('type' => 'varchar','precision' => '64','comment' => 'name part of CardDAV URL, if specified by client')
|
||||
),
|
||||
'pk' => array('contact_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array('contact_owner','cat_id','n_fileas','contact_uid',array('n_family','n_given'),array('n_given','n_family'),array('org_name','n_family','n_given')),
|
||||
'ix' => array('contact_owner','cat_id','n_fileas','contact_uid','caldav_name',array('n_family','n_given'),array('n_given','n_family'),array('org_name','n_family','n_given')),
|
||||
'uc' => array('account_id')
|
||||
),
|
||||
'egw_addressbook_extra' => array(
|
||||
|
@ -154,3 +154,22 @@ function phpgwapi_upgrade1_9_005()
|
||||
return $GLOBALS['setup_info']['phpgwapi']['currentver'] = '1.9.006';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add column to store CalDAV name given by client
|
||||
*/
|
||||
function phpgwapi_upgrade1_9_006()
|
||||
{
|
||||
$GLOBALS['egw_setup']->oProc->AddColumn('egw_addressbook','carddav_name',array(
|
||||
'type' => 'varchar',
|
||||
'precision' => '64',
|
||||
'comment' => 'name part of CardDAV URL, if specified by client'
|
||||
));
|
||||
$GLOBALS['egw_setup']->db->query($sql='UPDATE egw_addressbook SET carddav_name='.
|
||||
$GLOBALS['egw_setup']->db->concat(
|
||||
$GLOBALS['egw_setup']->db->to_varchar('contact_id'),"'.vcf'"),__LINE__,__FILE__);
|
||||
|
||||
$GLOBALS['egw_setup']->oProc->CreateIndex('egw_addressbook','carddav_name');
|
||||
|
||||
return $GLOBALS['setup_info']['phpgwapi']['currentver'] = '1.9.007';
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user