mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-26 16:48:49 +01:00
pricipals and groups collection for WebDAV Acl, to improve support for Apple iCal, you can now use http://domain.com/egroupware/groupdav.php/pricipals/username as account-url in iCal
This commit is contained in:
parent
ce59f97204
commit
0afb2d0324
@ -137,14 +137,31 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
|
||||
if (!$app) // root folder containing apps
|
||||
{
|
||||
// self url
|
||||
$files['files'][] = array(
|
||||
'path' => '/',
|
||||
'props' => array(
|
||||
self::mkprop('displayname','eGroupWare'),
|
||||
self::mkprop('resourcetype','collection'),
|
||||
// adding the calendar extra property (calendar-home-set, etc.) here, allows apple iCal to "autodetect" the URL
|
||||
'path' => '/',
|
||||
'props' => array(
|
||||
self::mkprop('displayname','eGroupWare'),
|
||||
self::mkprop('resourcetype','collection'),
|
||||
// adding the calendar extra property (calendar-home-set, etc.) here, allows apple iCal to "autodetect" the URL
|
||||
self::mkprop(groupdav::CALDAV,'calendar-home-set',$_SERVER['SCRIPT_NAME'].'/calendar/'),
|
||||
),
|
||||
);
|
||||
// principals collection
|
||||
$files['files'][] = array(
|
||||
'path' => '/principals/',
|
||||
'props' => array(
|
||||
self::mkprop('displayname',lang('Accounts')),
|
||||
self::mkprop('resourcetype','collection'),
|
||||
),
|
||||
);
|
||||
// groups collection
|
||||
$files['files'][] = array(
|
||||
'path' => '/groups/',
|
||||
'props' => array(
|
||||
self::mkprop('displayname',lang('Groups')),
|
||||
self::mkprop('resourcetype','collection'),
|
||||
),
|
||||
);
|
||||
|
||||
foreach($this->root as $app => $data)
|
||||
@ -155,7 +172,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
|
||||
$files['files'][] = array(
|
||||
'path' => '/'.$app.'/',
|
||||
'props' => call_user_func('groupdav_'.$app.'::extra_properties',array(
|
||||
'props' => call_user_func($app.'_groupdav::extra_properties',array(
|
||||
self::mkprop('displayname',$this->translation->convert(lang($app),$this->egw_charset,'utf-8')),
|
||||
self::mkprop('resourcetype',$this->_resourcetype($app)),
|
||||
)),
|
||||
@ -163,9 +180,9 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!$GLOBALS['egw_info']['user']['apps'][$app])
|
||||
if (!in_array($app,array('principals','groups')) && !$GLOBALS['egw_info']['user']['apps'][$app])
|
||||
{
|
||||
error_log(__CLASS__."::$method(path=$options[path]) 403 Forbidden: no app rights");
|
||||
error_log(__CLASS__."::$method(path=$options[path]) 403 Forbidden: no app rights for '$app'");
|
||||
return '403 Forbidden'; // no rights for the given app
|
||||
}
|
||||
if (($handler = groupdav_handler::app_handler($app,$this->debug)))
|
||||
@ -198,7 +215,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
$resourcetype = array(
|
||||
self::mkprop('collection','collection'),
|
||||
);
|
||||
if (!$no_extra_types)
|
||||
if (!$no_extra_types && isset($this->root[$app]))
|
||||
{
|
||||
foreach($this->root[$app] as $ns => $type)
|
||||
{
|
||||
@ -426,6 +443,13 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
{
|
||||
$parts = explode('/',$path);
|
||||
|
||||
if (in_array($parts[1],array('principals','groups')))
|
||||
{
|
||||
$user = $GLOBALS['egw_info']['user']['account_id'];
|
||||
list(,$app,$id) = $parts;
|
||||
return true;
|
||||
}
|
||||
|
||||
list($id) = explode('.',array_pop($parts)); // remove evtl. .ics extension
|
||||
|
||||
$app = array_pop($parts);
|
||||
@ -438,7 +462,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
{
|
||||
$user = $GLOBALS['egw_info']['user']['account_id'];
|
||||
}
|
||||
if (!($ok = $id && in_array($app,array('addressbook','calendar','infolog')) && $user))
|
||||
if (!($ok = $id && in_array($app,array('addressbook','calendar','infolog','principals','groups')) && $user))
|
||||
{
|
||||
error_log(__METHOD__."('$path') returning false: id=$id, app='$app', user=$user");
|
||||
}
|
||||
|
168
phpgwapi/inc/class.groupdav_groups.inc.php
Normal file
168
phpgwapi/inc/class.groupdav_groups.inc.php
Normal file
@ -0,0 +1,168 @@
|
||||
<?php
|
||||
/**
|
||||
* eGroupWare: GroupDAV access: groupdav/caldav/carddav groups handlers
|
||||
*
|
||||
* @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) 2008 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* eGroupWare: GroupDAV access: groupdav/caldav/carddav groups handlers
|
||||
*/
|
||||
class groupdav_groups extends groupdav_handler
|
||||
{
|
||||
/**
|
||||
* Reference to the accounts class
|
||||
*
|
||||
* @var accounts
|
||||
*/
|
||||
var $accounts;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $app
|
||||
* @param int $debug=null
|
||||
*/
|
||||
function __construct($app,$debug=null)
|
||||
{
|
||||
parent::__construct($app,$debug);
|
||||
|
||||
$this->accounts = $GLOBALS['egw']->accounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle propfind request for an application folder
|
||||
*
|
||||
* @param string $path
|
||||
* @param array $options
|
||||
* @param array &$files
|
||||
* @param int $user account_id
|
||||
* @return mixed boolean true on success, false on failure or string with http status (eg. '404 Not Found')
|
||||
*/
|
||||
function propfind($path,$options,&$files,$user)
|
||||
{
|
||||
list(,,$user) = explode('/',$path);
|
||||
foreach($user ? array($this->accounts->read($user)) : $this->accounts->search(array('type' => 'groups')) as $account)
|
||||
{
|
||||
$props = array(
|
||||
HTTP_WebDAV_Server::mkprop('displayname',lang('Group').' '.$account['account_lid']),
|
||||
HTTP_WebDAV_Server::mkprop('getetag',$this->get_etag($account)),
|
||||
HTTP_WebDAV_Server::mkprop('resourcetype','principal'),
|
||||
HTTP_WebDAV_Server::mkprop('alternate-URI-set',''),
|
||||
HTTP_WebDAV_Server::mkprop('principal-URL',$_SERVER['SCRIPT_NAME'].'/groups/'.$account['account_lid']),
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-home-set',$_SERVER['SCRIPT_NAME'].'/calendar/'),
|
||||
);
|
||||
foreach($this->accounts->members($account['account_id']) as $uid => $user)
|
||||
{
|
||||
$props[] = HTTP_WebDAV_Server::mkprop('group-membership',$_SERVER['SCRIPT_NAME'].'/principals/'.$user);
|
||||
}
|
||||
$files['files'][] = array(
|
||||
'path' => '/groups/'.$account['account_lid'],
|
||||
'props' => $props,
|
||||
);
|
||||
}
|
||||
//error_log(__METHOD__."($path,,,$user) files=".array2string($files['files']));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle get request for an applications entry
|
||||
*
|
||||
* @param array &$options
|
||||
* @param int $id
|
||||
* @return mixed boolean true on success, false on failure or string with http status (eg. '404 Not Found')
|
||||
*/
|
||||
function get(&$options,$id)
|
||||
{
|
||||
if (!is_array($account = $this->_common_get_put_delete('GET',$options,$id)))
|
||||
{
|
||||
return $account;
|
||||
}
|
||||
$options['data'] = 'Principal: '.$account['account_lid'].
|
||||
"\nURL: ".$_SERVER['SCRIPT_NAME'].$options['path'].
|
||||
"\nName: ".lang('Group').' '.$account['account_lid'].
|
||||
($account['account_email'] ? "\nEmail: ".$account['account_email'] : '').
|
||||
"\nMembers: ".implode(', ',$this->accounts->members($id))."\n";
|
||||
$options['mimetype'] = 'text/plain; charset=utf-8';
|
||||
header('Content-Encoding: identity');
|
||||
header('ETag: '.$this->get_etag($account));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle get request for an applications entry
|
||||
*
|
||||
* @param array &$options
|
||||
* @param int $id
|
||||
* @param int $user=null account_id of owner, default null
|
||||
* @return mixed boolean true on success, false on failure or string with http status (eg. '404 Not Found')
|
||||
*/
|
||||
function put(&$options,$id,$user=null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle get request for an applications entry
|
||||
*
|
||||
* @param array &$options
|
||||
* @param int $id
|
||||
* @return mixed boolean true on success, false on failure or string with http status (eg. '404 Not Found')
|
||||
*/
|
||||
function delete(&$options,$id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an entry
|
||||
*
|
||||
* @param string/int $id
|
||||
* @return array/boolean array with entry, false if no read rights, null if $id does not exist
|
||||
*/
|
||||
function read($id)
|
||||
{
|
||||
return $this->accounts->read($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has the neccessary rights on an entry
|
||||
*
|
||||
* @param int $acl EGW_ACL_READ, EGW_ACL_EDIT or EGW_ACL_DELETE
|
||||
* @param array/int $entry entry-array or id
|
||||
* @return boolean null if entry does not exist, false if no access, true if access permitted
|
||||
*/
|
||||
function check_access($acl,$entry)
|
||||
{
|
||||
if ($acl != EGW_ACL_READ)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!is_array($entry) && !$this->accounts->name2id($entry,'account_lid','g'))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the etag for an entry, can be reimplemented for other algorithm or field names
|
||||
*
|
||||
* @param array/int $event array with event or cal_id
|
||||
* @return string/boolean string with etag or false
|
||||
*/
|
||||
function get_etag($account)
|
||||
{
|
||||
if (!is_array($account))
|
||||
{
|
||||
$account = $this->read($account);
|
||||
}
|
||||
return '"'.$account['account_id'].':'.md5(serialize($account)).'"';
|
||||
}
|
||||
}
|
@ -60,6 +60,12 @@ abstract class groupdav_handler
|
||||
*/
|
||||
var $http_if_match;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $app
|
||||
* @param int $debug=null
|
||||
*/
|
||||
function __construct($app,$debug=null)
|
||||
{
|
||||
$this->app = $app;
|
||||
@ -181,10 +187,10 @@ abstract class groupdav_handler
|
||||
*/
|
||||
function _common_get_put_delete($method,&$options,$id)
|
||||
{
|
||||
if (!$GLOBALS['egw_info']['user']['apps'][$this->app])
|
||||
if (!in_array($this->app,array('principals','groups')) && !$GLOBALS['egw_info']['user']['apps'][$this->app])
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."($method,,$id) 403 Forbidden: no app rights");
|
||||
return '403 Forbidden'; // no calendar rights
|
||||
if ($this->debug) error_log(__METHOD__."($method,,$id) 403 Forbidden: no app rights for '$this->app'");
|
||||
return '403 Forbidden'; // no app rights
|
||||
}
|
||||
$extra_acl = $this->method2acl[$method];
|
||||
if (!($entry = $this->read($id)) && ($method != 'PUT' || $event === false) ||
|
||||
@ -228,7 +234,7 @@ abstract class groupdav_handler
|
||||
if (!array_key_exists($app,$handler_cache))
|
||||
{
|
||||
$class = $app.'_groupdav';
|
||||
if (!class_exists($class)) return null;
|
||||
if (!class_exists($class) && !class_exists($class = 'groupdav_'.$app)) return null;
|
||||
|
||||
$handler_cache[$app] = new $class($app);
|
||||
}
|
||||
|
174
phpgwapi/inc/class.groupdav_principals.inc.php
Normal file
174
phpgwapi/inc/class.groupdav_principals.inc.php
Normal file
@ -0,0 +1,174 @@
|
||||
<?php
|
||||
/**
|
||||
* eGroupWare: GroupDAV access: groupdav/caldav/carddav principals handlers
|
||||
*
|
||||
* @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) 2008 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* eGroupWare: GroupDAV access: groupdav/caldav/carddav principals handlers
|
||||
*/
|
||||
class groupdav_principals extends groupdav_handler
|
||||
{
|
||||
/**
|
||||
* Reference to the accounts class
|
||||
*
|
||||
* @var accounts
|
||||
*/
|
||||
var $accounts;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $app
|
||||
* @param int $debug=null
|
||||
*/
|
||||
function __construct($app,$debug=null)
|
||||
{
|
||||
parent::__construct($app,$debug);
|
||||
|
||||
$this->accounts = $GLOBALS['egw']->accounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle propfind request for an application folder
|
||||
*
|
||||
* @param string $path
|
||||
* @param array $options
|
||||
* @param array &$files
|
||||
* @param int $user account_id
|
||||
* @return mixed boolean true on success, false on failure or string with http status (eg. '404 Not Found')
|
||||
*/
|
||||
function propfind($path,$options,&$files,$user)
|
||||
{
|
||||
list(,,$id) = explode('/',$path);
|
||||
if ($id && !($id = $this->accounts->id2name($id)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
foreach($id ? array($this->accounts->read($id)) : $this->accounts->search(array('type' => 'accounts')) as $account)
|
||||
{
|
||||
$props = array(
|
||||
HTTP_WebDAV_Server::mkprop('displayname',trim($account['account_firstname'].' '.$account['account_lastname'])),
|
||||
HTTP_WebDAV_Server::mkprop('getetag',$this->get_etag($account)),
|
||||
HTTP_WebDAV_Server::mkprop('resourcetype','principal'),
|
||||
HTTP_WebDAV_Server::mkprop('alternate-URI-set',''),
|
||||
HTTP_WebDAV_Server::mkprop('principal-URL',$_SERVER['SCRIPT_NAME'].'/principals/'.$account['account_lid']),
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-home-set',$_SERVER['SCRIPT_NAME'].'/'),
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-user-address-set','MAILTO:'.$account['account_email']),
|
||||
);
|
||||
foreach($this->accounts->memberships($account['account_id']) as $gid => $group)
|
||||
{
|
||||
$props[] = HTTP_WebDAV_Server::mkprop('group-membership',$_SERVER['SCRIPT_NAME'].'/groups/'.$group);
|
||||
}
|
||||
$files['files'][] = array(
|
||||
'path' => '/principals/'.$account['account_lid'],
|
||||
'props' => $props,
|
||||
);
|
||||
error_log(__METHOD__."($path) path=/principals/".$account['account_lid'].', props='.array2string($props));
|
||||
}
|
||||
//error_log(__METHOD__."($path,,,$user) files=".array2string($files['files']));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle get request for an applications entry
|
||||
*
|
||||
* @param array &$options
|
||||
* @param int $id
|
||||
* @return mixed boolean true on success, false on failure or string with http status (eg. '404 Not Found')
|
||||
*/
|
||||
function get(&$options,$id)
|
||||
{
|
||||
if (!is_array($account = $this->_common_get_put_delete('GET',$options,$id)))
|
||||
{
|
||||
return $account;
|
||||
}
|
||||
$options['data'] = 'Principal: '.$account['account_lid'].
|
||||
"\nURL: ".$_SERVER['SCRIPT_NAME'].$options['path'].
|
||||
"\nName: ".$account['account_firstname'].' '.$account['account_lastname'].
|
||||
"\nEmail: ".$account['account_email'].
|
||||
"\nMemberships: ".implode(', ',$this->accounts->memberships($id))."\n";
|
||||
$options['mimetype'] = 'text/plain; charset=utf-8';
|
||||
header('Content-Encoding: identity');
|
||||
header('ETag: '.$this->get_etag($account));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle get request for an applications entry
|
||||
*
|
||||
* @param array &$options
|
||||
* @param int $id
|
||||
* @param int $user=null account_id of owner, default null
|
||||
* @return mixed boolean true on success, false on failure or string with http status (eg. '404 Not Found')
|
||||
*/
|
||||
function put(&$options,$id,$user=null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle get request for an applications entry
|
||||
*
|
||||
* @param array &$options
|
||||
* @param int $id
|
||||
* @return mixed boolean true on success, false on failure or string with http status (eg. '404 Not Found')
|
||||
*/
|
||||
function delete(&$options,$id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an entry
|
||||
*
|
||||
* @param string/int $id
|
||||
* @return array/boolean array with entry, false if no read rights, null if $id does not exist
|
||||
*/
|
||||
function read($id)
|
||||
{
|
||||
return $this->accounts->read($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has the neccessary rights on an entry
|
||||
*
|
||||
* @param int $acl EGW_ACL_READ, EGW_ACL_EDIT or EGW_ACL_DELETE
|
||||
* @param array/int $entry entry-array or id
|
||||
* @return boolean null if entry does not exist, false if no access, true if access permitted
|
||||
*/
|
||||
function check_access($acl,$entry)
|
||||
{
|
||||
if ($acl != EGW_ACL_READ)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!is_array($entry) && !$this->accounts->name2id($entry,'account_lid','u'))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the etag for an entry, can be reimplemented for other algorithm or field names
|
||||
*
|
||||
* @param array/int $event array with event or cal_id
|
||||
* @return string/boolean string with etag or false
|
||||
*/
|
||||
function get_etag($account)
|
||||
{
|
||||
if (!is_array($account))
|
||||
{
|
||||
$account = $this->read($account);
|
||||
}
|
||||
return '"'.$account['account_id'].':'.md5(serialize($account)).'"';
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user