mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-01-22 22:08:45 +01:00
* CardDAV pref which addressbooks to sync and many fixes for iPhone OS 4.0, 4.1, 4.2beta and Mac iCal and contact app
Merge of following commits from Trunk: r32609: * GroupDAV preference for addressbook-home-set (requires to register hooks) r32610: missing groupdav hooks r32611: fixed missing "users" of principal url in calendar-user-address-set r32615: as the pricipal of current user is influenced by GroupDAV prefs, we have to include them in the etag r32619: loop over existing addressbooks, to make sure each ab is only once in addressbook-home-set, even when selected multiple times in the prefs because of symbolic ab like "primary group" r32620: urlencode and decode account_lid in url to cope with group-names with space in it, which stall iPhone OS 4.2 devices r32621: fixed bug: GroupDAV/CardDAV PUT request to /addressbook/ changes owner, also checking now required ACL for moving contacts between addressbooks r32622: returning "403 Forbidden" if addressbook_bo->save() fails, happens when writing new entries in ABs without ADD rights r32623: * iCal on iPhone detects URL now correct reverted calendar-home-set to report only users calendar, as reporting multiple break propfind r32624: we need a real redirect, not just a proxy r32631: fixed working in GroupDAV prefs and translation
This commit is contained in:
commit
fa58c2adc4
@ -299,9 +299,10 @@ class addressbook_groupdav extends groupdav_handler
|
||||
* @param array &$options
|
||||
* @param int $id
|
||||
* @param int $user=null account_id of owner, default null
|
||||
* @param string $prefix=null user prefix from path (eg. /ralf from /ralf/addressbook)
|
||||
* @return mixed boolean true on success, false on failure or string with http status (eg. '404 Not Found')
|
||||
*/
|
||||
function put(&$options,$id,$user=null)
|
||||
function put(&$options,$id,$user=null,$prefix=null)
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__.'('.array2string($options).",$id,$user)");
|
||||
|
||||
@ -383,12 +384,21 @@ class addressbook_groupdav extends groupdav_handler
|
||||
$contact['id'] = $oldContact['id'];
|
||||
// dont allow the client to overwrite certain values
|
||||
$contact['uid'] = $oldContact['uid'];
|
||||
//$contact['owner'] = $oldContact['owner'];
|
||||
$contact['owner'] = $oldContact['owner'];
|
||||
$contact['private'] = $oldContact['private'];
|
||||
}
|
||||
|
||||
$contact['owner'] = $user;
|
||||
|
||||
// only set owner, if user is explicitly specified in URL (check via prefix, NOT for /addressbook/ !)
|
||||
if ($prefix)
|
||||
{
|
||||
// check for modified owners, if user has an add right for the new addressbook and
|
||||
// delete rights for the old addressbook (_common_get_put_delete checks for PUT only EGW_ACL_EDIT)
|
||||
if ($oldContact && $user != $oldContact['owner'] && !($this->bo->grants[$user] & EGW_ACL_ADD) &&
|
||||
(!$this->bo->grants[$oldContact['owner']] & EGW_ACL_DELETE))
|
||||
{
|
||||
return '403 Forbidden';
|
||||
}
|
||||
$contact['owner'] = $user;
|
||||
}
|
||||
if ($this->http_if_match) $contact['etag'] = self::etag2value($this->http_if_match);
|
||||
|
||||
if (!($save_ok = $this->bo->save($contact)))
|
||||
@ -398,7 +408,7 @@ class addressbook_groupdav extends groupdav_handler
|
||||
{
|
||||
return '412 Precondition Failed';
|
||||
}
|
||||
return false;
|
||||
return '403 Forbidden'; // happens when writing new entries in AB's without ADD rights
|
||||
}
|
||||
|
||||
if (!isset($contact['etag']))
|
||||
|
@ -25,4 +25,4 @@ RewriteBase /
|
||||
|
||||
RewriteRule ^.well-known/(caldav|carddav)$ /egroupware/groupdav.php/ [R]
|
||||
RewriteCond %{REQUEST_METHOD} ^(PROPFIND|OPTIONS)$
|
||||
RewriteRule ^/$ /egroupware/groupdav.php/
|
||||
RewriteRule ^/$ /egroupware/groupdav.php/ [R]
|
||||
|
@ -32,6 +32,7 @@ require_once('HTTP/WebDAV/Server.php');
|
||||
* Calling one of the above collections with a GET request / regular browser generates an automatic index
|
||||
* from the data of a allprop PROPFIND, allow to browse CalDAV/CardDAV/GroupDAV tree with a regular browser.
|
||||
*
|
||||
* @todo All principal urls should either contain no account_lid (eg. base64 of it) or use urlencode($account_lid)
|
||||
* @link http://www.groupdav.org GroupDAV spec
|
||||
*/
|
||||
class groupdav extends HTTP_WebDAV_Server
|
||||
@ -81,6 +82,9 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
'resourcetype' => array(self::GROUPDAV => 'vtodo-collection', self::CALDAV => 'calendar'),
|
||||
'component-set' => array(self::GROUPDAV => 'VTODO'),
|
||||
),
|
||||
'principals' => array(
|
||||
'resourcetype' => array(self::DAV => 'principal'),
|
||||
)
|
||||
);
|
||||
/**
|
||||
* Debug level: 0 = nothing, 1 = function calls, 2 = more info, 3 = complete $_SERVER array
|
||||
@ -134,12 +138,14 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
break;
|
||||
case 'davkit': // iCal app in OS X 10.6 created wrong request, if full url given
|
||||
$this->client_require_href_as_url = false;
|
||||
$this->cnrnd = true;
|
||||
break;
|
||||
case 'cfnetwork_old':
|
||||
$this->crrnd = true; // Older Apple Addressbook.app does not cope with namespace redundancy
|
||||
break;
|
||||
case 'neon':
|
||||
$this->cnrnd = true; // neon clients like cadaver
|
||||
break;
|
||||
}
|
||||
// adding EGroupware version to X-Dav-Powered-By header eg. "EGroupware 1.8.001 CalDAV/CardDAV/GroupDAV server"
|
||||
$this->dav_powered_by = str_replace('EGroupware','EGroupware '.$GLOBALS['egw_info']['server']['versions']['phpgwapi'],
|
||||
@ -252,8 +258,8 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
$user_prefix = '/'; //.$GLOBALS['egw_info']['user']['account_lid'].'/';
|
||||
}
|
||||
$calendar_user_address_set = array(
|
||||
self::mkprop('href',$this->base_uri.'/principals/'.$principalType.'/'.$account['account_lid'].'/'),
|
||||
self::mkprop('href','urn:uuid:'.$account['account_lid']));
|
||||
self::mkprop('href','urn:uuid:'.$account['account_lid']),
|
||||
);
|
||||
if ($user < 0)
|
||||
{
|
||||
$principalType = 'groups';
|
||||
@ -265,6 +271,8 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
$displayname = $account['account_fullname'];
|
||||
$calendar_user_address_set[] = self::mkprop('href','MAILTO:'.$account['account_email']);
|
||||
}
|
||||
$calendar_user_address_set[] = self::mkprop('href',$this->base_uri.'/principals/'.$principalType.'/'.$account['account_lid'].'/');
|
||||
|
||||
if ($options['depth'] && $user_prefix == '/')
|
||||
{
|
||||
$displayname = 'EGroupware (Cal|Card|Group)DAV server';
|
||||
@ -334,7 +342,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!in_array($app,array('principals','groups')) && !$GLOBALS['egw_info']['user']['apps'][$app])
|
||||
if ($app != 'principals' && !$GLOBALS['egw_info']['user']['apps'][$app])
|
||||
{
|
||||
if ($this->debug) error_log(__CLASS__."::$method(path=$options[path]) 403 Forbidden: no app rights for '$app'");
|
||||
return "403 Forbidden: no app rights for '$app'"; // no rights for the given app
|
||||
@ -729,13 +737,13 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
|
||||
if ($this->debug) error_log(__METHOD__.'('.array2string($options).')');
|
||||
|
||||
if (!$this->_parse_path($options['path'],$id,$app,$user))
|
||||
if (!$this->_parse_path($options['path'],$id,$app,$user,$prefix))
|
||||
{
|
||||
return '404 Not Found';
|
||||
}
|
||||
if (($handler = self::app_handler($app)))
|
||||
{
|
||||
$status = $handler->put($options,$id,$user);
|
||||
$status = $handler->put($options,$id,$user,$prefix);
|
||||
// set default stati: true --> 204 No Content, false --> should be already handled
|
||||
if (is_bool($status)) $status = $status ? '204 No Content' : '400 Something went wrong';
|
||||
return $status;
|
||||
@ -918,7 +926,8 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
}
|
||||
$parts = explode('/', $this->_unslashify($path));
|
||||
|
||||
if (($account_id = $this->accounts->name2id($parts[0], 'account_lid')))
|
||||
if (($account_id = $this->accounts->name2id($parts[0], 'account_lid')) ||
|
||||
($account_id = $this->accounts->name2id($parts[0]=urldecode($parts[0]))))
|
||||
{
|
||||
// /$user/$app/...
|
||||
$user = array_shift($parts);
|
||||
@ -942,7 +951,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
list($id) = explode('.',$id); // remove evtl. .ics extension
|
||||
}
|
||||
|
||||
$ok = $id && $user && in_array($app,array('addressbook','calendar','infolog','principals','groups'));
|
||||
$ok = $id && $user && in_array($app,array('addressbook','calendar','infolog','principals'));
|
||||
if ($this->debug)
|
||||
{
|
||||
error_log(__METHOD__."('$path') returning " . ($ok ? 'true' : 'false') . ": id='$id', app='$app', user='$user', user_prefix='$user_prefix'");
|
||||
|
@ -235,7 +235,7 @@ abstract class groupdav_handler
|
||||
*/
|
||||
function _common_get_put_delete($method,&$options,$id,&$return_no_access=false)
|
||||
{
|
||||
if (!in_array($this->app,array('principals','groups')) && !$GLOBALS['egw_info']['user']['apps'][$this->app])
|
||||
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'");
|
||||
return '403 Forbidden'; // no app rights
|
||||
|
97
phpgwapi/inc/class.groupdav_hooks.inc.php
Normal file
97
phpgwapi/inc/class.groupdav_hooks.inc.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware: GroupDAV hooks: eg. preferences
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage groupdav
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2010 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* GroupDAV hooks: eg. preferences
|
||||
*/
|
||||
class groupdav_hooks
|
||||
{
|
||||
/**
|
||||
* Show GroupDAV preferences link in preferences
|
||||
*
|
||||
* @param string|array $args
|
||||
*/
|
||||
public static function menus($args)
|
||||
{
|
||||
$appname = 'groupdav';
|
||||
$location = is_array($args) ? $args['location'] : $args;
|
||||
|
||||
if ($location == 'preferences')
|
||||
{
|
||||
$file = array(
|
||||
'Preferences' => egw::link('/index.php','menuaction=preferences.uisettings.index&appname='.$appname),
|
||||
);
|
||||
if ($location == 'preferences')
|
||||
{
|
||||
display_section($appname,$file);
|
||||
}
|
||||
else
|
||||
{
|
||||
display_sidebox($appname,lang('Preferences'),$file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* populates $settings for the preferences
|
||||
*
|
||||
* @param array|string $hook_data
|
||||
* @return array
|
||||
*/
|
||||
static function settings($hook_data)
|
||||
{
|
||||
$settings = array();
|
||||
|
||||
if ($hook_data['setup'])
|
||||
{
|
||||
$addressbooks = array();
|
||||
}
|
||||
else
|
||||
{
|
||||
$user = $GLOBALS['egw_info']['user']['account_id'];
|
||||
$addressbook_bo = new addressbook_bo();
|
||||
$addressbooks = $addressbook_bo->get_addressbooks(EGW_ACL_READ);
|
||||
unset($addressbooks[$user]); // Use P for personal addressbook
|
||||
unset($addressbooks[$user.'p']);// ignore (optional) private addressbook for now
|
||||
}
|
||||
$addressbooks = array(
|
||||
'P' => lang('Personal'),
|
||||
'G' => lang('Primary Group'),
|
||||
//'U' => lang('Accounts'), // not yet working
|
||||
'O' => lang('All in one'),
|
||||
'A' => lang('All'),
|
||||
) + $addressbooks;
|
||||
|
||||
// rewriting owner=0 to 'U', as 0 get's always selected by prefs
|
||||
if (!isset($addressbooks[0]))
|
||||
{
|
||||
unset($addressbooks['U']);
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($addressbooks[0]);
|
||||
}
|
||||
|
||||
$settings['add_default'] = array(
|
||||
'type' => 'multiselect',
|
||||
'label' => 'Addressbooks to sync with Apple clients',
|
||||
'name' => 'addressbook-home-set',
|
||||
'help' => 'Addressbooks for CardDAV attribute "addressbook-home-set".',
|
||||
'values' => $addressbooks,
|
||||
'xmlrpc' => True,
|
||||
'admin' => False,
|
||||
'default' => 'P',
|
||||
);
|
||||
return $settings;
|
||||
}
|
||||
}
|
@ -13,6 +13,8 @@
|
||||
|
||||
/**
|
||||
* EGroupware: GroupDAV access: groupdav/caldav/carddav principals handlers
|
||||
*
|
||||
* @todo All principal urls should either contain no account_lid (eg. base64 of it) or use urlencode($account_lid)
|
||||
*/
|
||||
class groupdav_principals extends groupdav_handler
|
||||
{
|
||||
@ -251,20 +253,41 @@ class groupdav_principals extends groupdav_handler
|
||||
$this->base_uri.'/principals/groups/'.$group);
|
||||
}
|
||||
}
|
||||
$addressbooks = array();
|
||||
$calendars = array();
|
||||
$addressbooks = $calendars = array();
|
||||
if ($account['account_id'] == $GLOBALS['egw_info']['user']['account_id'])
|
||||
{
|
||||
$addr_bo = new addressbook_bo();
|
||||
foreach ($addr_bo->get_addressbooks() as $id => $label)
|
||||
$prefs = $GLOBALS['egw_info']['user']['preferences']['groupdav'];
|
||||
$addressbook_home_set = $prefs['addressbook-home-set'];
|
||||
if (empty($addressbook_home_set)) $addressbook_home_set = 'P'; // personal addressbook
|
||||
$addressbook_home_set = explode(',',$addressbook_home_set);
|
||||
// replace symbolic id's with real nummeric id's
|
||||
foreach(array(
|
||||
'P' => $GLOBALS['egw_info']['user']['account_id'],
|
||||
'G' => $GLOBALS['egw_info']['user']['account_primary_group'],
|
||||
'U' => '0',
|
||||
) as $sym => $id)
|
||||
{
|
||||
if ($id && is_numeric($id))
|
||||
if (($key = array_search($sym, $addressbook_home_set)) !== false)
|
||||
{
|
||||
$owner = $GLOBALS['egw']->accounts->id2name($id);
|
||||
$addressbooks[] = HTTP_WebDAV_Server::mkprop('href',
|
||||
$this->base_uri.'/'.$owner.'/');
|
||||
$addressbook_home_set[$key] = $id;
|
||||
}
|
||||
}
|
||||
if (in_array('O',$addressbook_home_set)) // "all in one" from groupdav.php/addressbook/
|
||||
{
|
||||
$addressbooks[] = HTTP_WebDAV_Server::mkprop('href',$this->base_uri.'/');
|
||||
}
|
||||
foreach(ExecMethod('addressbook.addressbook_bo.get_addressbooks',EGW_ACL_READ) as $id => $label)
|
||||
{
|
||||
if ((in_array('A',$addressbook_home_set) || in_array((string)$id,$addressbook_home_set)) &&
|
||||
is_numeric($id) && ($owner = $GLOBALS['egw']->accounts->id2name($id)))
|
||||
{
|
||||
$addressbooks[] = HTTP_WebDAV_Server::mkprop('href',$this->base_uri.'/'.urlencode($owner).'/');
|
||||
}
|
||||
}
|
||||
$calendars[] = HTTP_WebDAV_Server::mkprop('href',
|
||||
$this->base_uri.'/'.$account['account_lid'].'/');
|
||||
|
||||
/* iCal send propfind to wrong url (concatinated href's), if we return multiple href in calendar-home-set
|
||||
$cal_bo = new calendar_bo();
|
||||
foreach ($cal_bo->list_cals() as $label => $entry)
|
||||
{
|
||||
@ -273,11 +296,12 @@ class groupdav_principals extends groupdav_handler
|
||||
$calendars[] = HTTP_WebDAV_Server::mkprop('href',
|
||||
$this->base_uri.'/'.$owner.'/');
|
||||
}
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
$addressbooks[] = HTTP_WebDAV_Server::mkprop('href',
|
||||
$this->base_uri.'/'.$account['account_lid'].'/');
|
||||
$this->base_uri.'/'.$account['account_lid'].'/');
|
||||
$calendars[] = HTTP_WebDAV_Server::mkprop('href',
|
||||
$this->base_uri.'/'.$account['account_lid'].'/');
|
||||
}
|
||||
@ -507,6 +531,9 @@ class groupdav_principals extends groupdav_handler
|
||||
{
|
||||
$account = $this->read($account);
|
||||
}
|
||||
return 'EGw-'.$account['account_id'].':'.md5(serialize($account)).'-wGE';
|
||||
return 'EGw-'.$account['account_id'].':'.md5(serialize($account)).
|
||||
// as the pricipal of current user is influenced by GroupDAV prefs, we have to include them in the etag
|
||||
($account['account_id'] == $GLOBALS['egw_info']['user']['account_id'] ?
|
||||
':'.md5(serialize($GLOBALS['egw_info']['user']['preferences']['groupdav'])) : '').'-wGE';
|
||||
}
|
||||
}
|
@ -268,10 +268,12 @@ class hooks
|
||||
foreach($GLOBALS['egw_info']['apps'] as $appname => $app)
|
||||
{
|
||||
$f = EGW_SERVER_ROOT . $SEP . $appname . $SEP . 'setup' . $SEP . 'setup.inc.php';
|
||||
if(@file_exists($f))
|
||||
$setup_info = array($appname => array());
|
||||
if(@file_exists($f)) include($f);
|
||||
// some apps have setup_info for more then themselfs (eg. phpgwapi for groupdav)
|
||||
foreach($setup_info as $appname => $data)
|
||||
{
|
||||
include($f);
|
||||
$this->register_hooks($appname,$setup_info[$appname]['hooks']);
|
||||
if ($data['hooks']) $this->register_hooks($appname,$data['hooks']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,8 @@ add category common de Kategorie hinzufügen
|
||||
add shortcut common de Abkürzung hinzufügen
|
||||
add sub common de Untergeordnete hinzufügen
|
||||
addressbook common de Adressbuch
|
||||
addressbooks for carddav attribute "addressbook-home-set". common de Adressbücher für CardDAV Attribut "addressbook-home-set".
|
||||
addressbooks to sync with apple clients common de Adressbücher zum Synchronisieren mit Apple Programmen
|
||||
admin common de Admin
|
||||
administration common de Administration
|
||||
afghanistan common de AFGHANISTAN
|
||||
@ -291,6 +293,7 @@ group has been deleted common de Gruppe wurde gelöscht
|
||||
group has been updated common de Gruppe wurde aktualisiert
|
||||
group name common de Gruppenname
|
||||
group public common de Group Public
|
||||
groupdav common de CalDAV, CardDAV und GroupDAV Server
|
||||
groups common de Gruppen
|
||||
groups with permission for %1 common de Gruppen mit Berechtigung für %1
|
||||
groups without permission for %1 common de Gruppen ohne Berechtigung für %1
|
||||
|
@ -40,6 +40,8 @@ add category common en Add category
|
||||
add shortcut common en Add Shortcut
|
||||
add sub common en Add sub
|
||||
addressbook common en Addressbook
|
||||
addressbooks for carddav attribute "addressbook-home-set". common en Addressbooks for CardDAV attribute "addressbook-home-set".
|
||||
addressbooks to sync with apple clients common en Addressbooks to sync with Apple clients
|
||||
admin common en Admin
|
||||
administration common en Administration
|
||||
afghanistan common en AFGHANISTAN
|
||||
@ -291,6 +293,7 @@ group has been deleted common en Group has been deleted
|
||||
group has been updated common en Group has been updated
|
||||
group name common en group name
|
||||
group public common en Group Public
|
||||
groupdav common en CalDAV, CardDAV and GroupDAV server
|
||||
groups common en Groups
|
||||
groups with permission for %1 common en Groups with permission for %1
|
||||
groups without permission for %1 common en Groups without permission for %1
|
||||
|
@ -75,5 +75,5 @@ $setup_info['groupdav']['author'] = $setup_info['groupdav']['maintainer'] = arra
|
||||
'email' => 'RalfBecker@outdoor-training.de'
|
||||
);
|
||||
$setup_info['groupdav']['license'] = 'GPL';
|
||||
|
||||
|
||||
$setup_info['groupdav']['hooks']['preferences'] = 'groupdav_hooks::menus';
|
||||
$setup_info['groupdav']['hooks']['settings'] = 'groupdav_hooks::settings';
|
||||
|
Loading…
Reference in New Issue
Block a user