mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-21 23:43:17 +01:00
move CalDAV/CardDAV server to api
This commit is contained in:
parent
25a1bf6360
commit
682fd42a26
@ -5,7 +5,7 @@
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package addressbook
|
||||
* @subpackage groupdav
|
||||
* @subpackage carddav
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2007-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
@ -14,20 +14,20 @@
|
||||
use EGroupware\Api;
|
||||
|
||||
/**
|
||||
* EGroupware: GroupDAV access: addressbook handler
|
||||
* CalDAV/CardDAV/GroupDAV access: Addressbook handler
|
||||
*
|
||||
* Propfind now uses a groupdav_propfind_iterator with a callback to query huge addressbooks in chunk,
|
||||
* Propfind now uses a Api\CalDAV\PropfindIterator with a callback to query huge addressbooks in chunk,
|
||||
* without getting into problems with memory_limit.
|
||||
*
|
||||
* Permanent error_log() calls should use $this->groupdav->log($str) instead, to be send to PHP error_log()
|
||||
* Permanent error_log() calls should use $this->caldav->log($str) instead, to be send to PHP error_log()
|
||||
* and our request-log (prefixed with "### " after request and response, like exceptions).
|
||||
*/
|
||||
class addressbook_groupdav extends groupdav_handler
|
||||
class addressbook_groupdav extends Api\CalDAV\Handler
|
||||
{
|
||||
/**
|
||||
* bo class of the application
|
||||
*
|
||||
* @var addressbook_bo
|
||||
* @var Api\Contacts
|
||||
*/
|
||||
var $bo;
|
||||
|
||||
@ -63,13 +63,13 @@ class addressbook_groupdav extends groupdav_handler
|
||||
* Constructor
|
||||
*
|
||||
* @param string $app 'calendar', 'addressbook' or 'infolog'
|
||||
* @param groupdav $groupdav calling class
|
||||
* @param Api\CalDAV $caldav calling class
|
||||
*/
|
||||
function __construct($app, groupdav $groupdav)
|
||||
function __construct($app, Api\CalDAV $caldav)
|
||||
{
|
||||
parent::__construct($app, $groupdav);
|
||||
parent::__construct($app, $caldav);
|
||||
|
||||
$this->bo = new addressbook_bo();
|
||||
$this->bo = new Api\Contacts();
|
||||
|
||||
// since 1.9.007 we allow clients to specify the URL when creating a new contact, as specified by CardDAV
|
||||
// LDAP does NOT have a carddav_name attribute --> stick with id mapped to LDAP attribute uid
|
||||
@ -77,12 +77,12 @@ class addressbook_groupdav extends groupdav_handler
|
||||
$this->bo->contact_repository != 'sql' ||
|
||||
$this->bo->account_repository != 'sql' && strpos($_SERVER['REQUEST_URI'].'/','/addressbook-accounts/') !== false)
|
||||
{
|
||||
groupdav_handler::$path_extension = '.vcf';
|
||||
self::$path_extension = '.vcf';
|
||||
}
|
||||
else
|
||||
{
|
||||
groupdav_handler::$path_attr = 'carddav_name';
|
||||
groupdav_handler::$path_extension = '';
|
||||
self::$path_attr = 'carddav_name';
|
||||
self::$path_extension = '';
|
||||
}
|
||||
if ($this->debug) error_log(__METHOD__."() contact_repository={$this->bo->contact_repository}, account_repository={$this->bo->account_repository}, REQUEST_URI=$_SERVER[REQUEST_URI] --> path_attr=".self::$path_attr.", path_extension=".self::$path_extension);
|
||||
|
||||
@ -136,7 +136,7 @@ class addressbook_groupdav extends groupdav_handler
|
||||
|
||||
// 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']))
|
||||
$options['root']['ns'] == Api\CalDAV::CARDDAV) && is_array($options['props']))
|
||||
{
|
||||
foreach($options['props'] as $prop)
|
||||
{
|
||||
@ -177,13 +177,13 @@ class addressbook_groupdav extends groupdav_handler
|
||||
else
|
||||
{
|
||||
// return iterator, calling ourself to return result in chunks
|
||||
$files['files'] = new groupdav_propfind_iterator($this,$path,$filter,$files['files']);
|
||||
$files['files'] = new Api\CalDAV\PropfindIterator($this,$path,$filter,$files['files']);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for profind interator
|
||||
* Callback for profind iterator
|
||||
*
|
||||
* @param string $path
|
||||
* @param array& $filter
|
||||
@ -243,7 +243,7 @@ class addressbook_groupdav extends groupdav_handler
|
||||
continue;
|
||||
}
|
||||
$props = array(
|
||||
'getcontenttype' => HTTP_WebDAV_Server::mkprop('getcontenttype', 'text/vcard'),
|
||||
'getcontenttype' => Api\CalDAV::mkprop('getcontenttype', 'text/vcard'),
|
||||
'getlastmodified' => $contact['modified'],
|
||||
'displayname' => $contact['n_fn'],
|
||||
);
|
||||
@ -251,7 +251,7 @@ class addressbook_groupdav extends groupdav_handler
|
||||
{
|
||||
$content = $handler->getVCard($contact['id'],$this->charset,false);
|
||||
$props['getcontentlength'] = bytes($content);
|
||||
$props[] = HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'address-data',$content,true);
|
||||
$props[] = Api\CalDAV::mkprop(Api\CalDAV::CARDDAV,'address-data',$content,true);
|
||||
}
|
||||
$files[] = $this->add_resource($path, $contact, $props);
|
||||
}
|
||||
@ -271,11 +271,11 @@ class addressbook_groupdav extends groupdav_handler
|
||||
$accounts_filter = $filter_in;
|
||||
$accounts_filter['owner'] = '0';
|
||||
if ($sync_collection_report) $token_was = $this->sync_collection_token;
|
||||
groupdav_handler::$path_attr = 'id';
|
||||
groupdav_handler::$path_extension = '.vcf';
|
||||
self::$path_attr = 'id';
|
||||
self::$path_extension = '.vcf';
|
||||
$files = array_merge($files, $this->propfind_callback($path, $accounts_filter, false, false));
|
||||
groupdav_handler::$path_attr = 'carddav_name';
|
||||
groupdav_handler::$path_extension = '';
|
||||
self::$path_attr = 'carddav_name';
|
||||
self::$path_extension = '';
|
||||
if ($sync_collection_report && $token_was > $this->sync_collection_token)
|
||||
{
|
||||
$this->sync_collection_token = $token_was;
|
||||
@ -310,7 +310,7 @@ class addressbook_groupdav extends groupdav_handler
|
||||
$etag .= ':'.implode('-',$filter['owner']);
|
||||
}
|
||||
$props = array(
|
||||
'getcontenttype' => HTTP_WebDAV_Server::mkprop('getcontenttype', 'text/vcard'),
|
||||
'getcontenttype' => Api\CalDAV::mkprop('getcontenttype', 'text/vcard'),
|
||||
'getlastmodified' => egw_time::to($list['list_modified'],'ts'),
|
||||
'displayname' => $list['list_name'],
|
||||
'getetag' => '"'.$etag.'"',
|
||||
@ -319,7 +319,7 @@ class addressbook_groupdav extends groupdav_handler
|
||||
{
|
||||
$content = $handler->getGroupVCard($list);
|
||||
$props['getcontentlength'] = bytes($content);
|
||||
$props[] = HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'address-data',$content,true);
|
||||
$props[] = Api\CalDAV::mkprop(Api\CalDAV::CARDDAV,'address-data',$content,true);
|
||||
}
|
||||
$files[] = $this->add_resource($path, $list, $props);
|
||||
|
||||
@ -391,7 +391,7 @@ class addressbook_groupdav extends groupdav_handler
|
||||
switch((string)$filter['name'])
|
||||
{
|
||||
case 'param-filter':
|
||||
$this->groupdav->log(__METHOD__."(...) param-filter='{$filter['attrs']['name']}' not (yet) implemented!");
|
||||
$this->caldav->log(__METHOD__."(...) param-filter='{$filter['attrs']['name']}' not (yet) implemented!");
|
||||
break;
|
||||
case 'prop-filter': // can be multiple prop-filter, see example
|
||||
if ($matches) $prop_filters[] = implode($prop_test=='allof'?' AND ':' OR ',$matches);
|
||||
@ -456,7 +456,7 @@ class addressbook_groupdav extends groupdav_handler
|
||||
}
|
||||
// fall through
|
||||
default:
|
||||
$this->groupdav->log(__METHOD__."(".array2string($options).",,$id) unknown filter=".array2string($filter).' --> ignored');
|
||||
$this->caldav->log(__METHOD__."(".array2string($options).",,$id) unknown filter=".array2string($filter).' --> ignored');
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -498,11 +498,11 @@ class addressbook_groupdav extends groupdav_handler
|
||||
case 'sync-level':
|
||||
if ($option['data'] != '1')
|
||||
{
|
||||
$this->groupdav->log(__METHOD__."(...) only sync-level {$option['data']} requested, but only 1 supported! options[other]=".array2string($options['other']));
|
||||
$this->caldav->log(__METHOD__."(...) only sync-level {$option['data']} requested, but only 1 supported! options[other]=".array2string($options['other']));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$this->groupdav->log(__METHOD__."(...) unknown xml tag '{$option['name']}': options[other]=".array2string($options['other']));
|
||||
$this->caldav->log(__METHOD__."(...) unknown xml tag '{$option['name']}': options[other]=".array2string($options['other']));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -517,7 +517,7 @@ class addressbook_groupdav extends groupdav_handler
|
||||
$parts = explode('/',$option['data']);
|
||||
if (($id = urldecode(array_pop($parts))))
|
||||
{
|
||||
$ids[] = groupdav_handler::$path_extension ? basename($id,groupdav_handler::$path_extension) : $id;
|
||||
$ids[] = self::$path_extension ? basename($id,self::$path_extension) : $id;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -526,7 +526,7 @@ class addressbook_groupdav extends groupdav_handler
|
||||
}
|
||||
elseif ($id)
|
||||
{
|
||||
$filters[self::$path_attr] = groupdav_handler::$path_extension ? basename($id,groupdav_handler::$path_extension) : $id;
|
||||
$filters[self::$path_attr] = self::$path_extension ? basename($id,self::$path_extension) : $id;
|
||||
}
|
||||
//error_log(__METHOD__."() options[other]=".array2string($options['other'])." --> filters=".array2string($filters));
|
||||
return true;
|
||||
@ -848,27 +848,27 @@ class addressbook_groupdav extends groupdav_handler
|
||||
if (!isset($props['addressbook-description']))
|
||||
{
|
||||
// default addressbook description: can be overwritten via PROPPATCH, in which case it's already set
|
||||
$props['addressbook-description'] = HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'addressbook-description',$props['displayname']);
|
||||
$props['addressbook-description'] = Api\CalDAV::mkprop(Api\CalDAV::CARDDAV,'addressbook-description',$props['displayname']);
|
||||
}
|
||||
// setting an max image size, so iOS scales the images before transmitting them
|
||||
// we currently scale down to width of 240px, which tests shown to be ~20k
|
||||
$props['max-image-size'] = HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'max-image-size',24*1024);
|
||||
$props['max-image-size'] = Api\CalDAV::mkprop(Api\CalDAV::CARDDAV,'max-image-size',24*1024);
|
||||
|
||||
// supported reports (required property for CardDAV)
|
||||
$props['supported-report-set'] = array(
|
||||
'addressbook-query' => HTTP_WebDAV_Server::mkprop('supported-report',array(
|
||||
HTTP_WebDAV_Server::mkprop('report',array(
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'addressbook-query',''))))),
|
||||
'addressbook-multiget' => HTTP_WebDAV_Server::mkprop('supported-report',array(
|
||||
HTTP_WebDAV_Server::mkprop('report',array(
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'addressbook-multiget',''))))),
|
||||
'addressbook-query' => Api\CalDAV::mkprop('supported-report',array(
|
||||
Api\CalDAV::mkprop('report',array(
|
||||
Api\CalDAV::mkprop(Api\CalDAV::CARDDAV,'addressbook-query',''))))),
|
||||
'addressbook-multiget' => Api\CalDAV::mkprop('supported-report',array(
|
||||
Api\CalDAV::mkprop('report',array(
|
||||
Api\CalDAV::mkprop(Api\CalDAV::CARDDAV,'addressbook-multiget',''))))),
|
||||
);
|
||||
// only advertice rfc 6578 sync-collection report, if "delete-prevention" is switched on (deleted entries get marked deleted but not actualy deleted
|
||||
if ($GLOBALS['egw_info']['server']['history'])
|
||||
{
|
||||
$props['supported-report-set']['sync-collection'] = HTTP_WebDAV_Server::mkprop('supported-report',array(
|
||||
HTTP_WebDAV_Server::mkprop('report',array(
|
||||
HTTP_WebDAV_Server::mkprop('sync-collection','')))));
|
||||
$props['supported-report-set']['sync-collection'] = Api\CalDAV::mkprop('supported-report',array(
|
||||
Api\CalDAV::mkprop('report',array(
|
||||
Api\CalDAV::mkprop('sync-collection','')))));
|
||||
}
|
||||
return $props;
|
||||
}
|
||||
|
@ -5,13 +5,21 @@
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage groupdav
|
||||
* @subpackage caldav
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2007-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
require_once(EGW_INCLUDE_ROOT.'/api/src/WebDAV/Server.php');
|
||||
namespace EGroupware\Api;
|
||||
|
||||
use EGroupware\Api\CalDAV\Handler;
|
||||
use EGroupware\Api\CalDAV\Principals;
|
||||
|
||||
// explicit import non-namespaced classes
|
||||
require_once(__DIR__.'/WebDAV/Server.php');
|
||||
use HTTP_WebDAV_Server;
|
||||
use calendar_hooks;
|
||||
|
||||
/**
|
||||
* EGroupware: GroupDAV access
|
||||
@ -54,7 +62,7 @@ require_once(EGW_INCLUDE_ROOT.'/api/src/WebDAV/Server.php');
|
||||
* @link http://carddav.calconnect.org/ CardDAV resources
|
||||
* @link http://calendarserver.org/ Apple calendar and contacts server
|
||||
*/
|
||||
class groupdav extends HTTP_WebDAV_Server
|
||||
class CalDAV extends HTTP_WebDAV_Server
|
||||
{
|
||||
/**
|
||||
* DAV namespace
|
||||
@ -141,7 +149,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
/**
|
||||
* Instance of our application specific handler
|
||||
*
|
||||
* @var groupdav_handler
|
||||
* @var Handler
|
||||
*/
|
||||
var $handler;
|
||||
/**
|
||||
@ -228,7 +236,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
$this->crrnd = false;
|
||||
|
||||
// identify clients, which do NOT support path AND full url in <D:href> of PROPFIND request
|
||||
switch(($agent = groupdav_handler::get_agent()))
|
||||
switch(($agent = Handler::get_agent()))
|
||||
{
|
||||
case 'kde': // KAddressbook (at least in 3.5 can NOT subscribe / does NOT find addressbook)
|
||||
$this->client_require_href_as_url = true;
|
||||
@ -262,7 +270,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
}*/
|
||||
//error_log($_SERVER['REQUEST_URI']." --> ".$this->_SERVER['REQUEST_URI']);
|
||||
|
||||
$this->egw_charset = translation::charset();
|
||||
$this->egw_charset = Translation::charset();
|
||||
if (strpos($this->base_uri, 'http') === 0)
|
||||
{
|
||||
$this->current_user_principal = $this->_slashify($this->base_uri);
|
||||
@ -288,13 +296,13 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
* get the handler for $app
|
||||
*
|
||||
* @param string $app
|
||||
* @return groupdav_handler
|
||||
* @return Handler
|
||||
*/
|
||||
function app_handler($app)
|
||||
{
|
||||
if (isset($this->root[$app]['app'])) $app = $this->root[$app]['app'];
|
||||
|
||||
return groupdav_handler::app_handler($app,$this);
|
||||
return Handler::app_handler($app,$this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -632,7 +640,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
$displayname = 'EGroupware (Cal|Card|Group)DAV server';
|
||||
}
|
||||
|
||||
$displayname = translation::convert($displayname, translation::charset(),'utf-8');
|
||||
$displayname = Translation::convert($displayname, Translation::charset(),'utf-8');
|
||||
// self url
|
||||
$props = array(
|
||||
'displayname' => $displayname,
|
||||
@ -710,12 +718,12 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
}
|
||||
if ($depth)
|
||||
{
|
||||
foreach(groupdav_principals::get_resources() as $resource)
|
||||
foreach(Principals::get_resources() as $resource)
|
||||
{
|
||||
if ($is_location == groupdav_principals::resource_is_location($resource))
|
||||
if ($is_location == Principals::resource_is_location($resource))
|
||||
{
|
||||
$files['files'][] = $this->add_app('calendar', false, 'r'.$resource['res_id'],
|
||||
'/'.groupdav_principals::resource2name($resource, $is_location).'/');
|
||||
'/'.Principals::resource2name($resource, $is_location).'/');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -800,11 +808,11 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."(app='$app', no_extra_types=$no_extra_types, user='$user', path='$path')");
|
||||
$user_preferences = $GLOBALS['egw_info']['user']['preferences'];
|
||||
if (is_string($user) && $user[0] == 'r' && ($resource = groupdav_principals::read_resource(substr($user, 1))))
|
||||
if (is_string($user) && $user[0] == 'r' && ($resource = Principals::read_resource(substr($user, 1))))
|
||||
{
|
||||
$is_location = groupdav_principals::resource_is_location($resource);
|
||||
$is_location = Principals::resource_is_location($resource);
|
||||
$displayname = null;
|
||||
list($principalType, $account_lid) = explode('/', groupdav_principals::resource2name($resource, $is_location, $displayname));
|
||||
list($principalType, $account_lid) = explode('/', Principals::resource2name($resource, $is_location, $displayname));
|
||||
}
|
||||
elseif ($user)
|
||||
{
|
||||
@ -850,7 +858,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
}
|
||||
// fall through
|
||||
default:
|
||||
$props['displayname'] = translation::convert(lang($app).' '.$displayname, $this->egw_charset, 'utf-8');
|
||||
$props['displayname'] = Translation::convert(lang($app).' '.$displayname, $this->egw_charset, 'utf-8');
|
||||
}
|
||||
|
||||
// rfc 5995 (Use POST to add members to WebDAV collections): we use collection path with add-member query param
|
||||
@ -926,7 +934,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
if (method_exists($handler,'getctag') && $this->prop_requested('getctag') === true)
|
||||
{
|
||||
$props['getctag'] = self::mkprop(
|
||||
groupdav::CALENDARSERVER,'getctag',$handler->getctag($path,$user));
|
||||
self::CALENDARSERVER,'getctag',$handler->getctag($path,$user));
|
||||
}
|
||||
// add sync-token url if handler supports sync-collection report
|
||||
if (isset($props['supported-report-set']['sync-collection']) && $this->prop_requested('sync-token') === true)
|
||||
@ -1006,7 +1014,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
{
|
||||
return $ret; // no collection
|
||||
}
|
||||
header('Content-type: text/html; charset='.translation::charset());
|
||||
header('Content-type: text/html; charset='.Translation::charset());
|
||||
echo "<html>\n<head>\n\t<title>".'EGroupware (Cal|Card|Group)DAV server '.htmlspecialchars($options['path'])."</title>\n";
|
||||
echo "\t<meta http-equiv='content-type' content='text/html; charset=utf-8' />\n";
|
||||
echo "\t<style type='text/css'>\n.th { background-color: #e0e0e0; }\n.row_on { background-color: #F1F1F1; vertical-align: top; }\n".
|
||||
@ -1018,7 +1026,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
foreach(explode('/',$this->_unslashify($options['path'])) as $n => $name)
|
||||
{
|
||||
$path .= ($n != 1 ? '/' : '').$name;
|
||||
echo html::a_href(htmlspecialchars($name.'/'),$path);
|
||||
echo Html::a_href(htmlspecialchars($name.'/'),$path);
|
||||
}
|
||||
echo "</h1>\n";
|
||||
|
||||
@ -1069,7 +1077,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
}
|
||||
|
||||
echo "\t<tr class='$class'>\n\t\t<td>$n</td>\n\t\t<td>".
|
||||
html::a_href(htmlspecialchars($name),'/groupdav.php'.strtr($file['path'], array(
|
||||
Html::a_href(htmlspecialchars($name),'/groupdav.php'.strtr($file['path'], array(
|
||||
'%' => '%25',
|
||||
'#' => '%23',
|
||||
'?' => '%3F',
|
||||
@ -1107,7 +1115,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
|
||||
echo "</body>\n</html>\n";
|
||||
|
||||
common::egw_exit();
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1206,7 +1214,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
{
|
||||
// for some reason OS X Addressbook (CFNetwork user-agent) uses now (DAV:add-member given with collection URL+"?add-member")
|
||||
// POST to the collection URL plus a UID like name component (like for regular PUT) to create new entrys
|
||||
if (isset($_GET['add-member']) || groupdav_handler::get_agent() == 'cfnetwork')
|
||||
if (isset($_GET['add-member']) || Handler::get_agent() == 'cfnetwork')
|
||||
{
|
||||
$_GET['add-member'] = ''; // otherwise we give no Location header
|
||||
return $this->PUT($options);
|
||||
@ -1251,7 +1259,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
*
|
||||
* @param array &$options
|
||||
* @param string|int $id
|
||||
* @param groupdav_handler $handler
|
||||
* @param Handler $handler
|
||||
* @param string $action 'attachment-add', 'attachment-update', 'attachment-remove'
|
||||
* @return string http status
|
||||
*
|
||||
@ -1259,7 +1267,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
* @todo managed-id does NOT change on update
|
||||
* @todo updates of attachments through vfs need to call $handler->update_tags($id) too
|
||||
*/
|
||||
protected function managed_attachements(&$options, $id, groupdav_handler $handler, $action)
|
||||
protected function managed_attachements(&$options, $id, Handler $handler, $action)
|
||||
{
|
||||
error_log(__METHOD__."(path=$options[path], id=$id, ..., action=$action) _GET=".array2string($_GET));
|
||||
$entry = $handler->_common_get_put_delete('GET', $options, $id);
|
||||
@ -1269,7 +1277,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
return $entry ? $entry : "404 Not found";
|
||||
}
|
||||
|
||||
if (!egw_link::file_access($handler->app, $entry['id'], EGW_ACL_EDIT))
|
||||
if (!Link::file_access($handler->app, $entry['id'], EGW_ACL_EDIT))
|
||||
{
|
||||
return '403 Forbidden';
|
||||
}
|
||||
@ -1282,7 +1290,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
substr($this->_SERVER['HTTP_CONTENT_DISPOSITION'], 0, 10) === 'attachment' &&
|
||||
preg_match('/filename="?([^";]+)/', $this->_SERVER['HTTP_CONTENT_DISPOSITION'], $matches))
|
||||
{
|
||||
$filename = egw_vfs::basename($matches[1]);
|
||||
$filename = Vfs::basename($matches[1]);
|
||||
}
|
||||
$path = null;
|
||||
if (!($to = self::fopen_attachment($handler->app, $handler->get_id($entry), $filename, $this->_SERVER['CONTENT_TYPE'], $path)) ||
|
||||
@ -1307,7 +1315,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
}
|
||||
if ($action == 'attachment-remove')
|
||||
{
|
||||
if (!egw_vfs::unlink($path))
|
||||
if (!Vfs::unlink($path))
|
||||
{
|
||||
self::xml_error(self::mkprop(self::CALDAV, 'valid-managed-id-parameter', ''));
|
||||
return '403 Forbidden';
|
||||
@ -1320,16 +1328,16 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
if (isset($this->_SERVER['HTTP_CONTENT_DISPOSITION']) &&
|
||||
substr($this->_SERVER['HTTP_CONTENT_DISPOSITION'], 0, 10) === 'attachment' &&
|
||||
preg_match('/filename="?([^";]+)/', $this->_SERVER['HTTP_CONTENT_DISPOSITION'], $matches) &&
|
||||
($filename = egw_vfs::basename($matches[1])) != egw_vfs::basename($path))
|
||||
($filename = Vfs::basename($matches[1])) != Vfs::basename($path))
|
||||
{
|
||||
$old_path = $path;
|
||||
if (!egw_vfs::rename($old_path, $path = egw_vfs::concat(egw_vfs::dirname($path), $filename)))
|
||||
if (!Vfs::rename($old_path, $path = Vfs::concat(Vfs::dirname($path), $filename)))
|
||||
{
|
||||
self::xml_error(self::mkprop(self::CALDAV, 'valid-managed-id-parameter', ''));
|
||||
return '403 Forbidden';
|
||||
}
|
||||
}
|
||||
if (!($to = egw_vfs::fopen($path, 'w')) ||
|
||||
if (!($to = Vfs::fopen($path, 'w')) ||
|
||||
isset($options['stream']) && ($copied=stream_copy_to_stream($options['stream'], $to)) === false ||
|
||||
isset($options['content']) && ($copied=fwrite($to, $options['content'])) === false)
|
||||
{
|
||||
@ -1377,7 +1385,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
{
|
||||
error_log(__METHOD__."('$app', $id, attach=".array2string($attach).", delete_via_put=".array2string($delete_via_put).')');
|
||||
|
||||
if (!egw_link::file_access($app, $id, EGW_ACL_EDIT))
|
||||
if (!Link::file_access($app, $id, EGW_ACL_EDIT))
|
||||
{
|
||||
error_log(__METHOD__."('$app', $id, ...) no rights to update attachments");
|
||||
return; // no rights --> nothing to do
|
||||
@ -1386,7 +1394,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
|
||||
if ($delete_via_put)
|
||||
{
|
||||
foreach(egw_vfs::find(egw_link::vfs_path($app, $id, '', true), array('type' => 'F')) as $path)
|
||||
foreach(Vfs::find(Link::vfs_path($app, $id, '', true), array('type' => 'F')) as $path)
|
||||
{
|
||||
$found = false;
|
||||
foreach($attach as $key => $attr)
|
||||
@ -1400,8 +1408,8 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
}
|
||||
if (!$found)
|
||||
{
|
||||
$ok = egw_vfs::unlink($path);
|
||||
error_log(__METHOD__."('$app', $id, ...) egw_vfs::unlink('$path') returned ".array2string($ok));
|
||||
$ok = Vfs::unlink($path);
|
||||
error_log(__METHOD__."('$app', $id, ...) Vfs::unlink('$path') returned ".array2string($ok));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1413,24 +1421,24 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
if (isset($attr['params']['MANAGED-ID']))
|
||||
{
|
||||
// invalid managed-id
|
||||
if (!($path = self::managed_id2path($attr['params']['MANAGED-ID'])) || !egw_vfs::is_readable($path))
|
||||
if (!($path = self::managed_id2path($attr['params']['MANAGED-ID'])) || !Vfs::is_readable($path))
|
||||
{
|
||||
error_log(__METHOD__."('$app', $id, ...) invalid MANAGED-ID ".array2string($attr));
|
||||
self::xml_error(self::mkprop(self::CALDAV, 'valid-managed-id', ''));
|
||||
return false;
|
||||
}
|
||||
if($path == ($link = egw_link::vfs_path($app, $id, egw_vfs::basename($path))))
|
||||
if($path == ($link = Link::vfs_path($app, $id, Vfs::basename($path))))
|
||||
{
|
||||
error_log(__METHOD__."('$app', $id, ...) trying to modify existing MANAGED-ID --> ignored! ".array2string($attr));
|
||||
continue;
|
||||
}
|
||||
// reuse valid managed-id --> symlink attachment
|
||||
if (egw_vfs::file_exists($link))
|
||||
if (Vfs::file_exists($link))
|
||||
{
|
||||
if (egw_vfs::readlink($link) === $path) continue; // no need to recreate identical link
|
||||
egw_vfs::unlink($link); // symlink will fail, if $link exists
|
||||
if (Vfs::readlink($link) === $path) continue; // no need to recreate identical link
|
||||
Vfs::unlink($link); // symlink will fail, if $link exists
|
||||
}
|
||||
if (!egw_vfs::symlink($path, $link))
|
||||
if (!Vfs::symlink($path, $link))
|
||||
{
|
||||
error_log(__METHOD__."('$app', $id, ...) failed to symlink($path, $link) --> ignored!");
|
||||
}
|
||||
@ -1465,15 +1473,15 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
*/
|
||||
protected static function fopen_attachment($app, $id, $_filename, $mime=null, &$path=null)
|
||||
{
|
||||
$filename = empty($_filename) ? 'attachment' : egw_vfs::basename($_filename);
|
||||
$filename = empty($_filename) ? 'attachment' : Vfs::basename($_filename);
|
||||
|
||||
if (strpos($mime, ';')) list($mime) = explode(';', $mime); // in case it contains eg. charset info
|
||||
|
||||
$ext = !empty($mime) ? mime_magic::mime2ext($mime) : '';
|
||||
$ext = !empty($mime) ? MimeMagic::mime2ext($mime) : '';
|
||||
|
||||
$matches = null;
|
||||
if (!$ext || substr($filename, -strlen($ext)-1) == '.'.$ext ||
|
||||
preg_match('/\.([^.]+)$/', $filename, $matches) && mime_magic::ext2mime($matches[1]) == $mime)
|
||||
preg_match('/\.([^.]+)$/', $filename, $matches) && MimeMagic::ext2mime($matches[1]) == $mime)
|
||||
{
|
||||
$parts = explode('.', $filename);
|
||||
$ext = '.'.array_pop($parts);
|
||||
@ -1485,18 +1493,18 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
}
|
||||
for($i = 1; $i < 100; ++$i)
|
||||
{
|
||||
$path = egw_link::vfs_path($app, $id, $filename.($i > 1 ? '-'.$i : '').$ext, true);
|
||||
if (!egw_vfs::stat($path)) break;
|
||||
$path = Link::vfs_path($app, $id, $filename.($i > 1 ? '-'.$i : '').$ext, true);
|
||||
if (!Vfs::stat($path)) break;
|
||||
}
|
||||
if ($i >= 100) return null;
|
||||
|
||||
if (!egw_vfs::file_exists($dir = egw_vfs::dirname($path)) && !egw_vfs::mkdir($dir, 0777, STREAM_MKDIR_RECURSIVE))
|
||||
if (!Vfs::file_exists($dir = Vfs::dirname($path)) && !Vfs::mkdir($dir, 0777, STREAM_MKDIR_RECURSIVE))
|
||||
{
|
||||
error_log(__METHOD__."('$app', $id, ...) failed to create entry dir $dir!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return egw_vfs::fopen($path, 'w');
|
||||
return Vfs::fopen($path, 'w');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1516,7 +1524,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
$url_prefix = ($_SERVER['HTTPS'] ? 'https' : 'http').'://'.$_SERVER['HTTP_HOST'];
|
||||
}
|
||||
}
|
||||
return $url_prefix.egw::link(egw_vfs::download_url($path));
|
||||
return $url_prefix.egw::link(Vfs::download_url($path));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1529,15 +1537,15 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
*/
|
||||
public static function add_attach($app, $id, array &$attributes, array &$parameters)
|
||||
{
|
||||
foreach(egw_vfs::find(egw_link::vfs_path($app, $id, '', true), array(
|
||||
foreach(Vfs::find(Link::vfs_path($app, $id, '', true), array(
|
||||
'type' => 'F',
|
||||
'need_mime' => true,
|
||||
), true) as $path => $stat)
|
||||
{
|
||||
// handle symlinks --> return target size and mime-type
|
||||
if (($target = egw_vfs::readlink($path)))
|
||||
if (($target = Vfs::readlink($path)))
|
||||
{
|
||||
if (!($stat = egw_vfs::stat($target))) continue; // broken or inaccessible symlink
|
||||
if (!($stat = Vfs::stat($target))) continue; // broken or inaccessible symlink
|
||||
|
||||
// check if target is in /apps, probably reused MANAGED-ID --> return it
|
||||
if (substr($target, 0, 6) == '/apps/')
|
||||
@ -1547,10 +1555,10 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
}
|
||||
$attributes['ATTACH'][] = self::path2location($path);
|
||||
$parameters['ATTACH'][] = array(
|
||||
'MANAGED-ID' => groupdav::path2managed_id($path),
|
||||
'MANAGED-ID' => self::path2managed_id($path),
|
||||
'FMTTYPE' => $stat['mime'],
|
||||
'SIZE' => (string)$stat['size'], // Horde_Icalendar renders int as empty string
|
||||
'FILENAME' => egw_vfs::basename($path),
|
||||
'FILENAME' => Vfs::basename($path),
|
||||
);
|
||||
// if we have attachments, set X-attribute to enable deleting them by put
|
||||
// (works around events synced before without ATTACH attributes)
|
||||
@ -1581,7 +1589,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
{
|
||||
$path = base64_decode($managed_id);
|
||||
|
||||
if (!$path || substr($path, 0, 6) != '/apps/' || !egw_vfs::stat($path))
|
||||
if (!$path || substr($path, 0, 6) != '/apps/' || !Vfs::stat($path))
|
||||
{
|
||||
$path = false;
|
||||
}
|
||||
@ -1684,6 +1692,8 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
{
|
||||
$GLOBALS['egw_info']['user']['preferences'] = $GLOBALS['egw']->preferences->save_repository();
|
||||
// call calendar-hook, if default-alarms are changed, to sync them to calendar prefs
|
||||
if (class_exists('calendar_hooks'))
|
||||
{
|
||||
foreach($need_save as $name)
|
||||
{
|
||||
list($name) = explode(':', $name);
|
||||
@ -1695,6 +1705,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT method handler
|
||||
@ -1801,7 +1812,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
*/
|
||||
function COPY($options, $del=false)
|
||||
{
|
||||
if ($this->debug) error_log('groupdav::'.($del ? 'MOVE' : 'COPY').'('.array2string($options).')');
|
||||
if ($this->debug) error_log('self::'.($del ? 'MOVE' : 'COPY').'('.array2string($options).')');
|
||||
|
||||
return '501 Not Implemented';
|
||||
}
|
||||
@ -1816,7 +1827,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
{
|
||||
$id = $app = $user = null;
|
||||
self::_parse_path($options['path'],$id,$app,$user);
|
||||
$path = egw_vfs::app_entry_lock_path($app,$id);
|
||||
$path = Vfs::app_entry_lock_path($app,$id);
|
||||
|
||||
if ($this->debug) error_log(__METHOD__.'('.array2string($options).") path=$path");
|
||||
|
||||
@ -1832,7 +1843,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
|
||||
// dont know why, but HTTP_WebDAV_Server passes the owner in D:href tags, which get's passed unchanged to checkLock/PROPFIND
|
||||
// that's wrong according to the standard and cadaver does not show it on discover --> strip_tags removes eventual tags
|
||||
if (($ret = egw_vfs::lock($path,$options['locktoken'],$options['timeout'],strip_tags($options['owner']),
|
||||
if (($ret = Vfs::lock($path,$options['locktoken'],$options['timeout'],strip_tags($options['owner']),
|
||||
$options['scope'],$options['type'],isset($options['update']),false)) && !isset($options['update'])) // false = no ACL check
|
||||
{
|
||||
return $ret ? '200 OK' : '409 Conflict';
|
||||
@ -1850,10 +1861,10 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
{
|
||||
$id = $app = $user = null;
|
||||
self::_parse_path($options['path'],$id,$app,$user);
|
||||
$path = egw_vfs::app_entry_lock_path($app,$id);
|
||||
$path = Vfs::app_entry_lock_path($app,$id);
|
||||
|
||||
if ($this->debug) error_log(__METHOD__.'('.array2string($options).") path=$path");
|
||||
return egw_vfs::unlock($path,$options['token']) ? '204 No Content' : '409 Conflict';
|
||||
return Vfs::unlock($path,$options['token']) ? '204 No Content' : '409 Conflict';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1867,7 +1878,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
$id = $app = $user = null;
|
||||
self::_parse_path($path,$id,$app,$user);
|
||||
|
||||
return egw_vfs::checkLock(egw_vfs::app_entry_lock_path($app, $id));
|
||||
return Vfs::checkLock(Vfs::app_entry_lock_path($app, $id));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1929,7 +1940,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
$user = $parts[0].'/'.$parts[1];
|
||||
array_shift($parts);
|
||||
$res_id = (int)array_shift($parts);
|
||||
if (!groupdav_principals::read_resource($res_id))
|
||||
if (!Principals::read_resource($res_id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -1964,7 +1975,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
}
|
||||
elseif($app == 'resource' || $app == 'location')
|
||||
{
|
||||
if (!groupdav_principals::read_resource($res_id = (int)$username))
|
||||
if (!Principals::read_resource($res_id = (int)$username))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -2127,7 +2138,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
{
|
||||
header('Content-type: application/xml; charset=utf-8');
|
||||
|
||||
$xml = new XMLWriter;
|
||||
$xml = new \XMLWriter;
|
||||
$xml->openMemory();
|
||||
$xml->setIndent(true);
|
||||
$xml->startDocument('1.0', 'utf-8');
|
||||
@ -2148,10 +2159,10 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
/**
|
||||
* Recursivly add properties to XMLWriter object
|
||||
*
|
||||
* @param XMLWriter $xml
|
||||
* @param \XMLWriter $xml
|
||||
* @param string|array $props string with name for empty element in DAV NS or array with props
|
||||
*/
|
||||
protected static function add_prop(XMLWriter $xml, $props)
|
||||
protected static function add_prop(\XMLWriter $xml, $props)
|
||||
{
|
||||
if (is_string($props)) $props = self::mkprop($props, '');
|
||||
if (isset($props['name'])) $props = array($props);
|
||||
@ -2202,9 +2213,9 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
*
|
||||
* Does NOT return and get installed in constructor.
|
||||
*
|
||||
* @param Exception $e
|
||||
* @param \Exception $e
|
||||
*/
|
||||
public static function exception_handler(Exception $e)
|
||||
public static function exception_handler(\Exception $e)
|
||||
{
|
||||
// logging exception as regular egw_execption_hander does
|
||||
$headline = null;
|
||||
@ -2229,10 +2240,20 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
self::$instance->log_request();
|
||||
}
|
||||
}
|
||||
if (is_object($GLOBALS['egw']))
|
||||
{
|
||||
common::egw_exit();
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique id, which can be used for syncronisation
|
||||
*
|
||||
* @param string $_appName the appname
|
||||
* @param string $_eventID the id of the content
|
||||
* @return string the unique id
|
||||
*/
|
||||
static function generate_uid($_appName, $_eventID)
|
||||
{
|
||||
if(empty($_appName) || empty($_eventID)) return false;
|
||||
|
||||
return $_appName.'-'.$_eventID.'-'.$GLOBALS['egw_info']['server']['install_id'];
|
||||
}
|
||||
}
|
@ -5,21 +5,25 @@
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage groupdav
|
||||
* @subpackage caldav
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2007-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\CalDAV;
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
/**
|
||||
* EGroupware: GroupDAV access: abstract baseclass for groupdav/caldav/carddav handlers
|
||||
*
|
||||
* Permanent error_log() calls should use $this->groupdav->log($str) instead, to be send to PHP error_log()
|
||||
* Permanent error_log() calls should use $this->caldav->log($str) instead, to be send to PHP error_log()
|
||||
* and our request-log (prefixed with "### " after request and response, like exceptions).
|
||||
*
|
||||
* @ToDo: If precondition for PUT, see https://tools.ietf.org/html/rfc6578#section-5
|
||||
*/
|
||||
abstract class groupdav_handler
|
||||
abstract class Handler
|
||||
{
|
||||
/**
|
||||
* Debug level: 0 = nothing, 1 = function calls, 2 = more info, eg. complete $_SERVER array
|
||||
@ -39,13 +43,13 @@ abstract class groupdav_handler
|
||||
/**
|
||||
* Reference to the accounts class
|
||||
*
|
||||
* @var accounts
|
||||
* @var Api\Accounts
|
||||
*/
|
||||
var $accounts;
|
||||
/**
|
||||
* Reference to the ACL class
|
||||
*
|
||||
* @var acl
|
||||
* @var Api\Acl
|
||||
*/
|
||||
var $acl;
|
||||
/**
|
||||
@ -65,13 +69,13 @@ abstract class groupdav_handler
|
||||
*/
|
||||
var $app;
|
||||
/**
|
||||
* Calling groupdav object
|
||||
* Calling CalDAV object
|
||||
*
|
||||
* @var groupdav
|
||||
* @var Api\CalDAV
|
||||
*/
|
||||
var $groupdav;
|
||||
var $caldav;
|
||||
/**
|
||||
* Base url of handler, need to prefix all pathes not automatic handled by HTTP_WebDAV_Server
|
||||
* Base url of handler, need to prefix all pathes not automatic handled by Api\CalDAV
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
@ -114,18 +118,18 @@ abstract class groupdav_handler
|
||||
* Constructor
|
||||
*
|
||||
* @param string $app 'calendar', 'addressbook' or 'infolog'
|
||||
* @param groupdav $groupdav calling class
|
||||
* @param Api\CalDAV $caldav calling class
|
||||
*/
|
||||
function __construct($app, groupdav $groupdav)
|
||||
function __construct($app, Api\CalDAV $caldav)
|
||||
{
|
||||
$this->app = $app;
|
||||
if (!is_null($groupdav->debug)) $this->debug = $groupdav->debug;
|
||||
$this->base_uri = $groupdav->base_uri;
|
||||
$this->groupdav = $groupdav;
|
||||
if (!is_null($caldav->debug)) $this->debug = $caldav->debug;
|
||||
$this->base_uri = $caldav->base_uri;
|
||||
$this->caldav = $caldav;
|
||||
|
||||
$this->agent = self::get_agent();
|
||||
|
||||
$this->egw_charset = translation::charset();
|
||||
$this->egw_charset = Api\Translation::charset();
|
||||
|
||||
$this->accounts = $GLOBALS['egw']->accounts;
|
||||
$this->acl = $GLOBALS['egw']->acl;
|
||||
@ -358,7 +362,7 @@ abstract class groupdav_handler
|
||||
{
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST')
|
||||
{
|
||||
$location = $this->groupdav->base_uri.$options['path'];
|
||||
$location = $this->caldav->base_uri.$options['path'];
|
||||
if ($location[0] == '/')
|
||||
{
|
||||
$location = (@$_SERVER['HTTPS'] === 'on' ? 'https' : 'http').'://'.$_SERVER['HTTP_HOST'].$location;
|
||||
@ -372,7 +376,7 @@ abstract class groupdav_handler
|
||||
|
||||
if (($ret = $this->get($options, $id ? $id : $this->new_id, $user)) && !empty($options['data']))
|
||||
{
|
||||
if (!$this->groupdav->use_compression()) header('Content-Length: '.$this->groupdav->bytes($options['data']));
|
||||
if (!$this->caldav->use_compression()) header('Content-Length: '.$this->caldav->bytes($options['data']));
|
||||
header('Content-Type: '.$options['mimetype']);
|
||||
echo $options['data'];
|
||||
}
|
||||
@ -398,17 +402,17 @@ abstract class groupdav_handler
|
||||
*
|
||||
* @static
|
||||
* @param string $app 'calendar', 'addressbook' or 'infolog'
|
||||
* @param groupdav $groupdav calling class
|
||||
* @param Api\CalDAV $groupdav calling class
|
||||
* @return groupdav_handler
|
||||
*/
|
||||
static function app_handler($app, $groupdav)
|
||||
static function app_handler($app, Api\CalDAV $groupdav)
|
||||
{
|
||||
static $handler_cache = array();
|
||||
|
||||
if (!array_key_exists($app,$handler_cache))
|
||||
{
|
||||
$class = $app.'_groupdav';
|
||||
if (!class_exists($class) && !class_exists($class = 'groupdav_'.$app)) return null;
|
||||
if (!class_exists($class) && !class_exists($class = __NAMESPACE__.'\\'.ucfirst($app))) return null;
|
||||
|
||||
$handler_cache[$app] = new $class($app, $groupdav);
|
||||
}
|
||||
@ -639,21 +643,21 @@ abstract class groupdav_handler
|
||||
}
|
||||
// if requested add privileges
|
||||
$privileges = array('read', 'read-current-user-privilege-set');
|
||||
if ($this->groupdav->prop_requested('current-user-privilege-set') === true && !isset($props['current-user-privilege-set']))
|
||||
if ($this->caldav->prop_requested('current-user-privilege-set') === true && !isset($props['current-user-privilege-set']))
|
||||
{
|
||||
if ($this->check_access(EGW_ACL_EDIT, $entry))
|
||||
{
|
||||
$privileges[] = 'write-content';
|
||||
}
|
||||
}
|
||||
if ($this->groupdav->prop_requested('owner') === true && !isset($props['owner']) &&
|
||||
if ($this->caldav->prop_requested('owner') === true && !isset($props['owner']) &&
|
||||
($account_lid = $this->accounts->id2name($entry['owner'])))
|
||||
{
|
||||
$type = $this->accounts->get_type($entry['owner']) == 'u' ? 'users' : 'groups';
|
||||
$props['owner'] = HTTP_WebDAV_Server::mkprop('href', $this->base_uri.'/principals/'.$type.'/'.$account_lid.'/');
|
||||
$props['owner'] = Api\CalDAV::mkprop('href', $this->base_uri.'/principals/'.$type.'/'.$account_lid.'/');
|
||||
}
|
||||
// we urldecode here, as HTTP_WebDAV_Server uses a minimal (#?%) urlencoding for incomming pathes and urlencodes pathes in propfind
|
||||
return $this->groupdav->add_resource($path.urldecode($this->get_path($entry)), $props, $privileges);
|
||||
// we urldecode here, as Api\CalDAV uses a minimal (#?%) urlencoding for incomming pathes and urlencodes pathes in propfind
|
||||
return $this->caldav->add_resource($path.urldecode($this->get_path($entry)), $props, $privileges);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -671,7 +675,7 @@ abstract class groupdav_handler
|
||||
|
||||
if (!isset($uri))
|
||||
{
|
||||
$uri = $path = $this->groupdav->base_uri;
|
||||
$uri = $path = $this->caldav->base_uri;
|
||||
if ($uri[0] == '/')
|
||||
{
|
||||
$uri = ($_SERVER["HTTPS"] === "on" ? "https:" : "http:") .'//' . $_SERVER['HTTP_HOST'] . $uri;
|
||||
@ -705,12 +709,12 @@ abstract class groupdav_handler
|
||||
{
|
||||
$error =
|
||||
' <D:response>
|
||||
<D:href>'.htmlspecialchars($this->groupdav->base_uri.$this->groupdav->path).'</D:href>
|
||||
<D:href>'.htmlspecialchars($this->caldav->base_uri.$this->caldav->path).'</D:href>
|
||||
<D:status>HTTP/1.1 507 Insufficient Storage</D:status>
|
||||
<D:error><D:number-of-matches-within-limits/></D:error>
|
||||
</D:response>
|
||||
';
|
||||
if ($this->groupdav->crrnd)
|
||||
if ($this->caldav->crrnd)
|
||||
{
|
||||
$error = str_replace(array('<D:', '</D:'), array('<', '</'), $error);
|
||||
}
|
||||
@ -747,175 +751,3 @@ abstract class groupdav_handler
|
||||
return $this->base_uri().$path.$token;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator for propfinds using propfind callback of a groupdav_handler to query results in chunks
|
||||
*
|
||||
* The propfind method just computes a filter and then returns an instance of this iterator instead of the files:
|
||||
*
|
||||
* function propfind($path,$options,&$files,$user,$id='')
|
||||
* {
|
||||
* $filter = array();
|
||||
* // compute filter from path, options, ...
|
||||
*
|
||||
* $files['files'] = new groupdav_propfind_iterator($this,$filter,$files['files']);
|
||||
*
|
||||
* return true;
|
||||
* }
|
||||
*/
|
||||
class groupdav_propfind_iterator implements Iterator
|
||||
{
|
||||
/**
|
||||
* current path
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $path;
|
||||
|
||||
/**
|
||||
* Handler to call for entries
|
||||
*
|
||||
* @var groupdav_handler
|
||||
*/
|
||||
protected $handler;
|
||||
|
||||
/**
|
||||
* Filter of propfind call
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $filter;
|
||||
|
||||
/**
|
||||
* Extra responses to return too
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $common_files;
|
||||
|
||||
/**
|
||||
* current chunk
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $files;
|
||||
|
||||
|
||||
/**
|
||||
* Start value for callback
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $start=0;
|
||||
|
||||
/**
|
||||
* Number of entries queried from callback in one call
|
||||
*
|
||||
*/
|
||||
const CHUNK_SIZE = 500;
|
||||
|
||||
/**
|
||||
* Log calls via error_log()
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $debug = false;
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param groupdav_handler $handler
|
||||
* @param array $filter filter for propfind call
|
||||
* @param array $files =array() extra files/responses to return too
|
||||
*/
|
||||
public function __construct(groupdav_handler $handler, $path, array $filter,array &$files=array())
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."('$path', ".array2string($filter).",)");
|
||||
$this->path = $path;
|
||||
$this->handler = $handler;
|
||||
$this->filter = $filter;
|
||||
$this->files = $this->common_files = $files;
|
||||
reset($this->files);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current element
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."() returning ".array2string(current($this->files)));
|
||||
return current($this->files);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the key of the current element
|
||||
*
|
||||
* @return int|string
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
$current = current($this->files);
|
||||
|
||||
if ($this->debug) error_log(__METHOD__."() returning ".array2string($current['path']));
|
||||
return $current['path']; // we return path as key
|
||||
}
|
||||
|
||||
/**
|
||||
* Move forward to next element (called after each foreach loop)
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
if (next($this->files) !== false)
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."() returning TRUE");
|
||||
return true;
|
||||
}
|
||||
// check if previous query gave less then CHUNK_SIZE entries --> we're done
|
||||
if ($this->start && count($this->files) < self::CHUNK_SIZE)
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."() returning FALSE (no more entries)");
|
||||
return false;
|
||||
}
|
||||
// try query further files via propfind callback of handler and store result in $this->files
|
||||
$this->files = $this->handler->propfind_callback($this->path,$this->filter,array($this->start,self::CHUNK_SIZE));
|
||||
if (!is_array($this->files) || !($entries = count($this->files)))
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."() returning FALSE (no more entries)");
|
||||
return false; // no further entries
|
||||
}
|
||||
$this->start += self::CHUNK_SIZE;
|
||||
reset($this->files);
|
||||
|
||||
if ($this->debug) error_log(__METHOD__."() this->start=$this->start, entries=$entries, count(this->files)=".count($this->files)." returning ".array2string(current($this->files) !== false));
|
||||
|
||||
return current($this->files) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewind the Iterator to the first element (called at beginning of foreach loop)
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."()");
|
||||
|
||||
$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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if current position is valid
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function valid ()
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."() returning ".array2string(current($this->files) !== false));
|
||||
return current($this->files) !== false;
|
||||
}
|
||||
}
|
@ -11,10 +11,17 @@
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\CalDAV;
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicit import old non-namespaced api classes
|
||||
use egw; // link
|
||||
|
||||
/**
|
||||
* GroupDAV hooks: eg. preferences
|
||||
*/
|
||||
class groupdav_hooks
|
||||
class Hooks
|
||||
{
|
||||
public $public_functions = array(
|
||||
'log' => true,
|
||||
@ -33,7 +40,7 @@ class groupdav_hooks
|
||||
if ($location == 'preferences')
|
||||
{
|
||||
$file = array(
|
||||
'Preferences' => egw::link('/index.php','menuaction=preferences.uisettings.index&appname='.$appname),
|
||||
'Preferences' => egw::link('/index.php','menuaction=preferences.preference_settings.index&appname='.$appname),
|
||||
);
|
||||
if ($location == 'preferences')
|
||||
{
|
||||
@ -109,13 +116,13 @@ class groupdav_hooks
|
||||
if (substr($log,0,$account_lid_len+1) == $GLOBALS['egw_info']['user']['account_lid'].'-' &&
|
||||
substr($log,-4) == '.log')
|
||||
{
|
||||
$logs['groupdav/'.$log] = egw_time::to(filemtime($log_dir.'/'.$log)).': '.
|
||||
$logs['groupdav/'.$log] = Api\DateTime::to(filemtime($log_dir.'/'.$log)).': '.
|
||||
str_replace('!','/',substr($log,$account_lid_len+1,-4));
|
||||
}
|
||||
}
|
||||
}
|
||||
$link = egw::link('/index.php',array(
|
||||
'menuaction' => 'groupdav.groupdav_hooks.log',
|
||||
'menuaction' => 'api.'.__CLASS__.'.log',
|
||||
'filename' => '',
|
||||
));
|
||||
$onchange = "egw_openWindowCentered('$link'+encodeURIComponent(this.value), '_blank', 1000, 500); this.value=''";
|
||||
@ -144,21 +151,21 @@ class groupdav_hooks
|
||||
*
|
||||
* $_GET['filename'] has to be in groupdav sub-dir of files_dir and start with account_lid of current user
|
||||
*
|
||||
* @throws egw_exception_wrong_parameter
|
||||
* @throws Api\Exception\WrongParameter
|
||||
*/
|
||||
public function log()
|
||||
public static function log()
|
||||
{
|
||||
$filename = $_GET['filename'];
|
||||
if (!preg_match('|^groupdav/'.preg_quote($GLOBALS['egw_info']['user']['account_lid'],'|').'-[^/]+\.log$|',$filename))
|
||||
{
|
||||
throw new egw_exception_wrong_parameter("Access denied to file '$filename'!");
|
||||
throw new Api\Exception\WrongParameter("Access denied to file '$filename'!");
|
||||
}
|
||||
$GLOBALS['egw_info']['flags']['css'] = '
|
||||
body { background-color: #e0e0e0; overflow: hidden; }
|
||||
pre.tail { background-color: white; padding-left: 5px; margin-left: 5px; }
|
||||
';
|
||||
$header = str_replace('!','/',substr($filename,10+strlen($GLOBALS['egw_info']['user']['account_lid']),-4));
|
||||
$tail = new egw_tail($filename);
|
||||
$tail = new Api\Json\Tail($filename);
|
||||
$GLOBALS['egw']->framework->render($tail->show($header),false,false);
|
||||
}
|
||||
}
|
@ -5,24 +5,32 @@
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage groupdav
|
||||
* @subpackage caldav
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2008-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\CalDAV;
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicit import classes without namespace
|
||||
use resources_bo;
|
||||
use calendar_bo;
|
||||
|
||||
/**
|
||||
* EGroupware: GroupDAV access: groupdav/caldav/carddav principals handlers
|
||||
*
|
||||
* First-level properties used in this class should have the property name as their key,
|
||||
* to allow to check if required properties are set!
|
||||
* groupdav_principals::add_principal() converts simple associative props (name => value pairs)
|
||||
* to name => HTTP_WebDAV_Server(name, value) pairs.
|
||||
* Principals::add_principal() converts simple associative props (name => value pairs)
|
||||
* to name => Api\CalDAV(name, value) pairs.
|
||||
*
|
||||
* Permanent error_log() calls should use $this->groupdav->log($str) instead, to be send to PHP error_log()
|
||||
* Permanent error_log() calls should use $this->caldav->log($str) instead, to be send to PHP error_log()
|
||||
* and our request-log (prefixed with "### " after request and response, like exceptions).
|
||||
*/
|
||||
class groupdav_principals extends groupdav_handler
|
||||
class Principals extends Handler
|
||||
{
|
||||
/**
|
||||
* Instance of resources_bo
|
||||
@ -35,11 +43,11 @@ class groupdav_principals extends groupdav_handler
|
||||
* Constructor
|
||||
*
|
||||
* @param string $app 'calendar', 'addressbook' or 'infolog'
|
||||
* @param groupdav $groupdav calling class
|
||||
* @param Api\CalDAV $caldav calling class
|
||||
*/
|
||||
function __construct($app, groupdav $groupdav)
|
||||
function __construct($app, Api\CalDAV $caldav)
|
||||
{
|
||||
parent::__construct($app, $groupdav);
|
||||
parent::__construct($app, $caldav);
|
||||
|
||||
if (!isset(self::$resources)) self::$resources = new resources_bo();
|
||||
}
|
||||
@ -67,7 +75,7 @@ class groupdav_principals extends groupdav_handler
|
||||
),
|
||||
/* seems only be used 'til OS X 10.6, no longer in 10.7
|
||||
'addressbook-findshared' => array(
|
||||
'ns' => groupdav::ADDRESSBOOKSERVER,
|
||||
'ns' => Api\CalDAV::ADDRESSBOOKSERVER,
|
||||
'method' => 'addressbook_findshared_report',
|
||||
),*/
|
||||
);
|
||||
@ -79,7 +87,7 @@ class groupdav_principals extends groupdav_handler
|
||||
*
|
||||
* @param string $path eg. '/principals/'
|
||||
* @param array $reports =null
|
||||
* @return array HTTP_WebDAV_Server::mkprop('supported-report-set', ...)
|
||||
* @return array Api\CalDAV::mkprop('supported-report-set', ...)
|
||||
*/
|
||||
protected function supported_report_set($path, array $reports=null)
|
||||
{
|
||||
@ -90,10 +98,10 @@ class groupdav_principals extends groupdav_handler
|
||||
$supported = array();
|
||||
foreach($reports as $name => $data)
|
||||
{
|
||||
$supported[$name] = HTTP_WebDAV_Server::mkprop('supported-report',array(
|
||||
HTTP_WebDAV_Server::mkprop('report',array(
|
||||
!$data['ns'] ? HTTP_WebDAV_Server::mkprop($name, '') :
|
||||
HTTP_WebDAV_Server::mkprop($data['ns'], $name, '')))));
|
||||
$supported[$name] = Api\CalDAV::mkprop('supported-report',array(
|
||||
Api\CalDAV::mkprop('report',array(
|
||||
!$data['ns'] ? Api\CalDAV::mkprop($name, '') :
|
||||
Api\CalDAV::mkprop($data['ns'], $name, '')))));
|
||||
}
|
||||
return $supported;
|
||||
}
|
||||
@ -116,7 +124,7 @@ class groupdav_principals extends groupdav_handler
|
||||
{
|
||||
return $this->$method($path, $options, $files, $user);
|
||||
}
|
||||
$this->groupdav->log(__METHOD__."('$path', ".array2string($options).",, $user) not implemented report, returning 501 Not Implemented");
|
||||
$this->caldav->log(__METHOD__."('$path', ".array2string($options).",, $user) not implemented report, returning 501 Not Implemented");
|
||||
return '501 Not Implemented';
|
||||
}
|
||||
list(,,$type,$name,$rest) = explode('/',$path,5);
|
||||
@ -178,7 +186,7 @@ class groupdav_principals extends groupdav_handler
|
||||
foreach($this->get_shared_addressbooks() as $path)
|
||||
{
|
||||
$files['files'][] = $f = $this->add_collection($path.'addressbook/', array(
|
||||
'resourcetype' => array(HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'addressbook','')),
|
||||
'resourcetype' => array(Api\CalDAV::mkprop(Api\CalDAV::CARDDAV,'addressbook','')),
|
||||
));
|
||||
error_log(__METHOD__."() ".array2string($f));
|
||||
}
|
||||
@ -268,14 +276,14 @@ class groupdav_principals extends groupdav_handler
|
||||
case 'calendar-proxy-write-for':
|
||||
$prop_path = $path . substr($prop_name, 0, -4).'/';
|
||||
$prop_name = 'group-member-set';
|
||||
$prop_ns = groupdav::DAV;
|
||||
$prop_ns = Api\CalDAV::DAV;
|
||||
break;
|
||||
|
||||
case 'expanded-group-member-set':
|
||||
case 'expanded-group-membership':
|
||||
// remove 'expanded-' prefix
|
||||
$prop_name = substr($prop_name, 9);
|
||||
$prop_ns = groupdav::DAV;
|
||||
$prop_ns = Api\CalDAV::DAV;
|
||||
break;
|
||||
}
|
||||
// run regular propfind for requested property
|
||||
@ -286,10 +294,10 @@ class groupdav_principals extends groupdav_handler
|
||||
'xmlns' => $prop_ns,
|
||||
));
|
||||
$prop_files = array();
|
||||
$this->groupdav->options = $options; // also modify global variable
|
||||
$this->caldav->options = $options; // also modify global variable
|
||||
if (empty($prop_name) || $this->propfind($prop_path, $options, $prop_files, $user) !== true)
|
||||
{
|
||||
$this->groupdav->log('### NO expand-property report for '.$requested_prop['attrs']['name']);
|
||||
$this->caldav->log('### NO expand-property report for '.$requested_prop['attrs']['name']);
|
||||
continue;
|
||||
}
|
||||
// find prop to expand
|
||||
@ -300,7 +308,7 @@ class groupdav_principals extends groupdav_handler
|
||||
if ($expand_prop['name'] !== $prop_name || !is_array($expand_prop['val']) ||
|
||||
$expand_prop['val'] && $expand_prop['val'][0]['name'] !== 'href')
|
||||
{
|
||||
$this->groupdav->log('### NO expand-property report for '.$requested_prop['attrs']['name'].' ('.$prop_name.')');
|
||||
$this->caldav->log('### NO expand-property report for '.$requested_prop['attrs']['name'].' ('.$prop_name.')');
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -323,12 +331,12 @@ class groupdav_principals extends groupdav_handler
|
||||
}
|
||||
// put back evtl. read top-level property
|
||||
if ($prop && $prop['depth'] == 1) array_unshift($requested_props, $prop);
|
||||
$this->groupdav->options = $options2; // also modify global variable
|
||||
$this->caldav->options = $options2; // also modify global variable
|
||||
|
||||
// run regular profind to get requested 2.-level properties for each href
|
||||
foreach($expand_prop['val'] as $key => &$prop_val)
|
||||
{
|
||||
list(,$expand_path) = explode($this->groupdav->base_uri, $prop_val['val']);
|
||||
list(,$expand_path) = explode($this->caldav->base_uri, $prop_val['val']);
|
||||
//error_log(__METHOD__."('$path', ..., $user) calling propfind('$expand_path', ".array2string($options2).', '.array2string($prop_val).", $user)");
|
||||
if ($this->propfind($expand_path, $options2, $prop_val, $user) !== true || !isset($prop_val['files'][0]))
|
||||
{
|
||||
@ -341,7 +349,7 @@ class groupdav_principals extends groupdav_handler
|
||||
// setting top-level name and namespace
|
||||
$expand_prop['ns'] = $requested_prop['attrs']['namespace'];
|
||||
$expand_prop['name'] = $requested_prop['attrs']['name'];
|
||||
// setting 2.-level props, so HTTP_WebDAV_Server can filter unwanted ones out or mark missing ones
|
||||
// setting 2.-level props, so Api\CalDAV can filter unwanted ones out or mark missing ones
|
||||
$expand_prop['props'] = $options2['props'];
|
||||
// add top-level path and property
|
||||
$files['files'][0]['path'] = $path;
|
||||
@ -463,13 +471,13 @@ class groupdav_principals extends groupdav_handler
|
||||
}
|
||||
if (!isset($property_search) || !$search_props || !isset($search_props[$property_search]['match']))
|
||||
{
|
||||
$this->groupdav->log(__METHOD__."('$path',...) Could not parse options[other]=".array2string($options['other']));
|
||||
$this->caldav->log(__METHOD__."('$path',...) Could not parse options[other]=".array2string($options['other']));
|
||||
return '400 Bad Request';
|
||||
}
|
||||
// make sure search property is included in toplevel props (can be missing and defaults to property-search/prop's)
|
||||
foreach($search_props as $prop)
|
||||
{
|
||||
if (!$this->groupdav->prop_requested($prop['name'], $prop['xmlns']))
|
||||
if (!$this->caldav->prop_requested($prop['name'], $prop['xmlns']))
|
||||
{
|
||||
$options['props'][] = array(
|
||||
'name' => $prop['name'],
|
||||
@ -483,7 +491,7 @@ class groupdav_principals extends groupdav_handler
|
||||
substr($search_props[0]['match'],-13) == '/groupdav.php')
|
||||
{
|
||||
$path = '/principals/users/'.$GLOBALS['egw_info']['user']['account_lid'].'/';
|
||||
$this->groupdav->log('Enabling hack for Lightning prior 1.1.1 for searching calendar-home-set matching "/groupdav.php": limiting search to '.$path);
|
||||
$this->caldav->log('Enabling hack for Lightning prior 1.1.1 for searching calendar-home-set matching "/groupdav.php": limiting search to '.$path);
|
||||
}
|
||||
}
|
||||
// check type attribute to limit search on a certain tree
|
||||
@ -645,18 +653,18 @@ class groupdav_principals extends groupdav_handler
|
||||
static $search_props = array(
|
||||
// from iOS iCal
|
||||
'displayname' => 'Display Name',
|
||||
'email-address-set' => array('description' => 'Email Addresses', 'ns' => groupdav::CALENDARSERVER),
|
||||
'last-name' => array('description' => 'Last Name', 'ns' => groupdav::CALENDARSERVER),
|
||||
'calendar-user-type' => array('description' => 'Calendar User Type', 'ns' => groupdav::CALDAV),
|
||||
'first-name' => array('description' => 'First Name', 'ns' => groupdav::CALENDARSERVER),
|
||||
'calendar-user-address-set' => array('description' => 'Calendar User Address Set', 'ns' => groupdav::CALDAV),
|
||||
'email-address-set' => array('description' => 'Email Addresses', 'ns' => Api\CalDAV::CALENDARSERVER),
|
||||
'last-name' => array('description' => 'Last Name', 'ns' => Api\CalDAV::CALENDARSERVER),
|
||||
'calendar-user-type' => array('description' => 'Calendar User Type', 'ns' => Api\CalDAV::CALDAV),
|
||||
'first-name' => array('description' => 'First Name', 'ns' => Api\CalDAV::CALENDARSERVER),
|
||||
'calendar-user-address-set' => array('description' => 'Calendar User Address Set', 'ns' => Api\CalDAV::CALDAV),
|
||||
// Lightning
|
||||
'calendar-home-set' => array('description' => 'Calendar Home Set', 'ns' => groupdav::CALENDARSERVER),
|
||||
'calendar-home-set' => array('description' => 'Calendar Home Set', 'ns' => Api\CalDAV::CALENDARSERVER),
|
||||
// others, we generally support all properties of the principal
|
||||
);
|
||||
header('Content-type: text/xml; charset=UTF-8');
|
||||
|
||||
$xml = new XMLWriter;
|
||||
$xml = new \XMLWriter;
|
||||
$xml->openMemory();
|
||||
$xml->setIndent(true);
|
||||
$xml->startDocument('1.0', 'UTF-8');
|
||||
@ -687,7 +695,7 @@ class groupdav_principals extends groupdav_handler
|
||||
$xml->endDocument();
|
||||
echo $xml->outputMemory();
|
||||
|
||||
common::egw_exit();
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -791,7 +799,7 @@ class groupdav_principals extends groupdav_handler
|
||||
!($account = $this->accounts->read($id)) ||
|
||||
!$this->accounts->visible($name))
|
||||
{
|
||||
$this->groupdav->log(__METHOD__."('$name', ...) account '$name' NOT found OR not visible to you (check account-selection preference)!");
|
||||
$this->caldav->log(__METHOD__."('$name', ...) account '$name' NOT found OR not visible to you (check account-selection preference)!");
|
||||
return '404 Not Found';
|
||||
}
|
||||
while (substr($rest,-1) == '/')
|
||||
@ -913,7 +921,7 @@ class groupdav_principals extends groupdav_handler
|
||||
{
|
||||
$addressbooks[] = '/';
|
||||
}
|
||||
foreach(array_keys(ExecMethod('addressbook.addressbook_bo.get_addressbooks',EGW_ACL_READ)) as $id)
|
||||
foreach(array_keys($GLOBALS['egw']->contacts->get_addressbooks(EGW_ACL_READ)) as $id)
|
||||
{
|
||||
if ((in_array('A',$addressbook_home_set) || in_array((string)$id,$addressbook_home_set)) &&
|
||||
is_numeric($id) && ($owner = $this->accounts->id2name($id)))
|
||||
@ -934,50 +942,50 @@ class groupdav_principals extends groupdav_handler
|
||||
{
|
||||
$addressbooks = $calendars = array();
|
||||
// since we "show" shared addressbooks and calendars in the user home, no need for individualiced homes
|
||||
$addressbooks[] = HTTP_WebDAV_Server::mkprop('href',
|
||||
$addressbooks[] = Api\CalDAV::mkprop('href',
|
||||
$this->base_uri.'/'.$account['account_lid'].'/');
|
||||
$calendars[] = HTTP_WebDAV_Server::mkprop('href',
|
||||
$calendars[] = Api\CalDAV::mkprop('href',
|
||||
$this->base_uri.'/'.$account['account_lid'].'/');
|
||||
|
||||
$displayname = translation::convert($account['account_fullname'], translation::charset(),'utf-8');
|
||||
$displayname = Api\Translation::convert($account['account_fullname'], Api\Translation::charset(),'utf-8');
|
||||
|
||||
return $this->add_principal('users/'.$account['account_lid'], array(
|
||||
'getetag' => $this->get_etag($account),
|
||||
'displayname' => $displayname,
|
||||
// CalDAV
|
||||
'calendar-home-set' => HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-home-set',$calendars),
|
||||
'calendar-home-set' => Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-home-set',$calendars),
|
||||
// CalDAV scheduling
|
||||
'schedule-outbox-URL' => HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'schedule-outbox-URL',array(
|
||||
HTTP_WebDAV_Server::mkprop('href',$this->base_uri.'/'.$account['account_lid'].'/outbox/'))),
|
||||
'schedule-inbox-URL' => HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'schedule-inbox-URL',array(
|
||||
HTTP_WebDAV_Server::mkprop('href',$this->base_uri.'/'.$account['account_lid'].'/inbox/'))),
|
||||
'calendar-user-address-set' => HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-user-address-set',array(
|
||||
HTTP_WebDAV_Server::mkprop('href','mailto:'.$account['account_email']),
|
||||
HTTP_WebDAV_Server::mkprop('href',$this->base_uri(true).'/principals/users/'.$account['account_lid'].'/'),
|
||||
HTTP_WebDAV_Server::mkprop('href',$this->base_uri(false).'/principals/users/'.$account['account_lid'].'/'),
|
||||
HTTP_WebDAV_Server::mkprop('href','urn:uuid:'.common::generate_uid('accounts', $account['account_id'])),
|
||||
'schedule-outbox-URL' => Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'schedule-outbox-URL',array(
|
||||
Api\CalDAV::mkprop('href',$this->base_uri.'/'.$account['account_lid'].'/outbox/'))),
|
||||
'schedule-inbox-URL' => Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'schedule-inbox-URL',array(
|
||||
Api\CalDAV::mkprop('href',$this->base_uri.'/'.$account['account_lid'].'/inbox/'))),
|
||||
'calendar-user-address-set' => Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-user-address-set',array(
|
||||
Api\CalDAV::mkprop('href','mailto:'.$account['account_email']),
|
||||
Api\CalDAV::mkprop('href',$this->base_uri(true).'/principals/users/'.$account['account_lid'].'/'),
|
||||
Api\CalDAV::mkprop('href',$this->base_uri(false).'/principals/users/'.$account['account_lid'].'/'),
|
||||
Api\CalDAV::mkprop('href','urn:uuid:'.Api\CalDAV::generate_uid('accounts', $account['account_id'])),
|
||||
)),
|
||||
'calendar-user-type' => HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-user-type','INDIVIDUAL'),
|
||||
'calendar-user-type' => Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-user-type','INDIVIDUAL'),
|
||||
// Calendarserver
|
||||
'email-address-set' => HTTP_WebDAV_Server::mkprop(groupdav::CALENDARSERVER,'email-address-set',array(
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALENDARSERVER,'email-address',$account['account_email']))),
|
||||
'last-name' => HTTP_WebDAV_Server::mkprop(groupdav::CALENDARSERVER,'last-name',$account['account_lastname']),
|
||||
'first-name' => HTTP_WebDAV_Server::mkprop(groupdav::CALENDARSERVER,'first-name',$account['account_firstname']),
|
||||
'record-type' => HTTP_WebDAV_Server::mkprop(groupdav::CALENDARSERVER,'record-type','users'),
|
||||
'email-address-set' => Api\CalDAV::mkprop(Api\CalDAV::CALENDARSERVER,'email-address-set',array(
|
||||
Api\CalDAV::mkprop(Api\CalDAV::CALENDARSERVER,'email-address',$account['account_email']))),
|
||||
'last-name' => Api\CalDAV::mkprop(Api\CalDAV::CALENDARSERVER,'last-name',$account['account_lastname']),
|
||||
'first-name' => Api\CalDAV::mkprop(Api\CalDAV::CALENDARSERVER,'first-name',$account['account_firstname']),
|
||||
'record-type' => Api\CalDAV::mkprop(Api\CalDAV::CALENDARSERVER,'record-type','users'),
|
||||
// WebDAV ACL and CalDAV proxy
|
||||
'group-membership' => $this->principal_set('group-membership', $this->accounts->memberships($account['account_id']),
|
||||
array('calendar', 'resources'), $account['account_id']), // add proxy-rights
|
||||
'alternate-URI-set' => array(
|
||||
HTTP_WebDAV_Server::mkprop('href','mailto:'.$account['account_email'])),
|
||||
Api\CalDAV::mkprop('href','mailto:'.$account['account_email'])),
|
||||
// CardDAV
|
||||
'addressbook-home-set' => HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'addressbook-home-set',$addressbooks),
|
||||
'principal-address' => HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'principal-address',
|
||||
'addressbook-home-set' => Api\CalDAV::mkprop(Api\CalDAV::CARDDAV,'addressbook-home-set',$addressbooks),
|
||||
'principal-address' => Api\CalDAV::mkprop(Api\CalDAV::CARDDAV,'principal-address',
|
||||
$GLOBALS['egw_info']['user']['preferences']['addressbook']['hide_accounts'] ? '' : array(
|
||||
HTTP_WebDAV_Server::mkprop('href',$this->base_uri.'/addressbook-accounts/'.$account['person_id'].'.vcf'))),
|
||||
Api\CalDAV::mkprop('href',$this->base_uri.'/addressbook-accounts/'.$account['person_id'].'.vcf'))),
|
||||
// CardDAV directory
|
||||
'directory-gateway' => HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV, 'directory-gateway',array(
|
||||
HTTP_WebDAV_Server::mkprop('href', $this->base_uri.'/addressbook/'))),
|
||||
'resource-id' => array(HTTP_WebDAV_Server::mkprop('href','urn:uuid:'.common::generate_uid('accounts', $account['account_id']))),
|
||||
'directory-gateway' => Api\CalDAV::mkprop(Api\CalDAV::CARDDAV, 'directory-gateway',array(
|
||||
Api\CalDAV::mkprop('href', $this->base_uri.'/addressbook/'))),
|
||||
'resource-id' => array(Api\CalDAV::mkprop('href','urn:uuid:'.Api\CalDAV::generate_uid('accounts', $account['account_id']))),
|
||||
));
|
||||
}
|
||||
|
||||
@ -1096,7 +1104,7 @@ class groupdav_principals extends groupdav_handler
|
||||
*/
|
||||
protected function add_group(array $account)
|
||||
{
|
||||
$displayname = translation::convert(lang('Group').' '.$account['account_lid'], translation::charset(), 'utf-8');
|
||||
$displayname = Api\Translation::convert(lang('Group').' '.$account['account_lid'], Api\Translation::charset(), 'utf-8');
|
||||
|
||||
// only return current user, if account-selection == 'none'
|
||||
if ($GLOBALS['egw_info']['user']['preferences']['common']['account_selection'] == 'none')
|
||||
@ -1111,19 +1119,19 @@ class groupdav_principals extends groupdav_handler
|
||||
return $this->add_principal('groups/'.$account['account_lid'], array(
|
||||
'getetag' => $this->get_etag($account),
|
||||
'displayname' => $displayname,
|
||||
'calendar-home-set' => HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-home-set',array(
|
||||
HTTP_WebDAV_Server::mkprop('href',$this->base_uri.'/'.$account['account_lid'].'/'))),
|
||||
'addressbook-home-set' => HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'addressbook-home-set',array(
|
||||
HTTP_WebDAV_Server::mkprop('href',$this->base_uri.'/'.$account['account_lid'].'/'))),
|
||||
'calendar-user-address-set' => HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-user-address-set',array(
|
||||
HTTP_WebDAV_Server::mkprop('href',$this->base_uri(true).'/principals/groups/'.$account['account_lid'].'/'),
|
||||
HTTP_WebDAV_Server::mkprop('href',$this->base_uri(false).'/principals/groups/'.$account['account_lid'].'/'),
|
||||
HTTP_WebDAV_Server::mkprop('href','urn:uuid:'.common::generate_uid('accounts', $account['account_id'])),
|
||||
'calendar-home-set' => Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-home-set',array(
|
||||
Api\CalDAV::mkprop('href',$this->base_uri.'/'.$account['account_lid'].'/'))),
|
||||
'addressbook-home-set' => Api\CalDAV::mkprop(Api\CalDAV::CARDDAV,'addressbook-home-set',array(
|
||||
Api\CalDAV::mkprop('href',$this->base_uri.'/'.$account['account_lid'].'/'))),
|
||||
'calendar-user-address-set' => Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-user-address-set',array(
|
||||
Api\CalDAV::mkprop('href',$this->base_uri(true).'/principals/groups/'.$account['account_lid'].'/'),
|
||||
Api\CalDAV::mkprop('href',$this->base_uri(false).'/principals/groups/'.$account['account_lid'].'/'),
|
||||
Api\CalDAV::mkprop('href','urn:uuid:'.Api\CalDAV::generate_uid('accounts', $account['account_id'])),
|
||||
)),
|
||||
'record-type' => HTTP_WebDAV_Server::mkprop(groupdav::CALENDARSERVER,'record-type','groups'),
|
||||
'calendar-user-type' => HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-user-type','GROUP'),
|
||||
'record-type' => Api\CalDAV::mkprop(Api\CalDAV::CALENDARSERVER,'record-type','groups'),
|
||||
'calendar-user-type' => Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-user-type','GROUP'),
|
||||
'group-member-set' => $this->principal_set('group-member-set', $groupmembers),
|
||||
'resource-id' => array(HTTP_WebDAV_Server::mkprop('href','urn:uuid:'.common::generate_uid('accounts', $account['account_id']))),
|
||||
'resource-id' => array(Api\CalDAV::mkprop('href','urn:uuid:'.Api\CalDAV::generate_uid('accounts', $account['account_id']))),
|
||||
));
|
||||
}
|
||||
|
||||
@ -1142,18 +1150,18 @@ class groupdav_principals extends groupdav_handler
|
||||
return $this->add_principal($name, array(
|
||||
'getetag' => $this->get_resource_etag($resource),
|
||||
'displayname' => $displayname,
|
||||
'calendar-user-address-set' => HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-user-address-set',array(
|
||||
HTTP_WebDAV_Server::mkprop('href',$this->base_uri(true).'/principals/'.$name.'/'),
|
||||
HTTP_WebDAV_Server::mkprop('href',$this->base_uri(false).'/principals/'.$name.'/'),
|
||||
HTTP_WebDAV_Server::mkprop('href','urn:uuid:'.common::generate_uid('resources', $resource['res_id'])),
|
||||
'calendar-user-address-set' => Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-user-address-set',array(
|
||||
Api\CalDAV::mkprop('href',$this->base_uri(true).'/principals/'.$name.'/'),
|
||||
Api\CalDAV::mkprop('href',$this->base_uri(false).'/principals/'.$name.'/'),
|
||||
Api\CalDAV::mkprop('href','urn:uuid:'.Api\CalDAV::generate_uid('resources', $resource['res_id'])),
|
||||
)),
|
||||
'record-type' => HTTP_WebDAV_Server::mkprop(groupdav::CALENDARSERVER,'record-type',$is_location ? 'locations' : 'resources'),
|
||||
'calendar-user-type' => HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-user-type',$is_location ? 'ROOM' : 'RESOURCE'),
|
||||
'resource-id' => array(HTTP_WebDAV_Server::mkprop('href','urn:uuid:'.common::generate_uid('resources', $resource['res_id']))),
|
||||
'record-type' => Api\CalDAV::mkprop(Api\CalDAV::CALENDARSERVER,'record-type',$is_location ? 'locations' : 'resources'),
|
||||
'calendar-user-type' => Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-user-type',$is_location ? 'ROOM' : 'RESOURCE'),
|
||||
'resource-id' => array(Api\CalDAV::mkprop('href','urn:uuid:'.Api\CalDAV::generate_uid('resources', $resource['res_id']))),
|
||||
// Calendarserver also reports empty email-address-set, thought iCal still does not show resources (only locations)
|
||||
'email-address-set' => HTTP_WebDAV_Server::mkprop(groupdav::CALENDARSERVER,'email-address-set',''),
|
||||
'calendar-home-set' => HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-home-set',array(
|
||||
HTTP_WebDAV_Server::mkprop('href',$this->base_uri.'/'.$name.'/'))),
|
||||
'email-address-set' => Api\CalDAV::mkprop(Api\CalDAV::CALENDARSERVER,'email-address-set',''),
|
||||
'calendar-home-set' => Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-home-set',array(
|
||||
Api\CalDAV::mkprop('href',$this->base_uri.'/'.$name.'/'))),
|
||||
));
|
||||
}
|
||||
|
||||
@ -1173,10 +1181,10 @@ class groupdav_principals extends groupdav_handler
|
||||
}
|
||||
if (is_null($is_location)) $is_location = self::resource_is_location($resource);
|
||||
|
||||
$displayname = translation::convert($resource['name'], translation::charset(), 'utf-8');
|
||||
$displayname = Api\Translation::convert($resource['name'], Api\Translation::charset(), 'utf-8');
|
||||
|
||||
return ($is_location ? 'locations/' : 'resources/').$resource['res_id'].'-'.
|
||||
preg_replace('/[^a-z0-9]+/i','-', translation::to_ascii($resource['name']));
|
||||
preg_replace('/[^a-z0-9]+/i','-', Api\Translation::to_ascii($resource['name']));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1190,7 +1198,7 @@ class groupdav_principals extends groupdav_handler
|
||||
static $location_cats=null;
|
||||
if (is_null($location_cats))
|
||||
{
|
||||
$config = config::read('resources');
|
||||
$config = Api\Config::read('resources');
|
||||
$location_cats = $config['location_cats'] ? explode(',', $config['location_cats']) : array();
|
||||
}
|
||||
if (!is_array($resource) && !($resource = self::read_resource($resource)))
|
||||
@ -1298,16 +1306,16 @@ class groupdav_principals extends groupdav_handler
|
||||
* Add a collection
|
||||
*
|
||||
* @param string $path
|
||||
* @param array $props =array() extra properties 'resourcetype' is added anyway, name => value pairs or name => HTTP_WebDAV_Server([namespace,]name,value)
|
||||
* @param array $props =array() extra properties 'resourcetype' is added anyway, name => value pairs or name => Api\CalDAV([namespace,]name,value)
|
||||
* @return array with values for keys 'path' and 'props'
|
||||
*/
|
||||
protected function add_collection($path, array $props = array())
|
||||
{
|
||||
if ($this->groupdav->prop_requested('supported-report-set'))
|
||||
if ($this->caldav->prop_requested('supported-report-set'))
|
||||
{
|
||||
$props['supported-report-set'] = $this->supported_report_set($path);
|
||||
}
|
||||
return $this->groupdav->add_collection($path, $props);
|
||||
return $this->caldav->add_collection($path, $props);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1320,17 +1328,17 @@ class groupdav_principals extends groupdav_handler
|
||||
*/
|
||||
protected function add_principal($principal, array $props = array(), $principal_url=null)
|
||||
{
|
||||
$props['resourcetype'][] = HTTP_WebDAV_Server::mkprop('principal', '');
|
||||
$props['resourcetype'][] = Api\CalDAV::mkprop('principal', '');
|
||||
|
||||
// required props per WebDAV ACL
|
||||
foreach(array('alternate-URI-set', 'group-membership') as $name)
|
||||
{
|
||||
if (!isset($props[$name])) $props[$name] = HTTP_WebDAV_Server::mkprop($name,'');
|
||||
if (!isset($props[$name])) $props[$name] = Api\CalDAV::mkprop($name,'');
|
||||
}
|
||||
if (!$principal_url) $principal_url = $principal;
|
||||
|
||||
$props['principal-URL'] = array(
|
||||
HTTP_WebDAV_Server::mkprop('href',$this->base_uri.'/principals/'.$principal.'/'));
|
||||
Api\CalDAV::mkprop('href',$this->base_uri.'/principals/'.$principal.'/'));
|
||||
|
||||
return $this->add_collection('/principals/'.$principal.'/', $props);
|
||||
}
|
||||
@ -1412,7 +1420,7 @@ class groupdav_principals extends groupdav_handler
|
||||
'displayname' => lang('%1 proxy of %2', lang($app).' '.lang($what), basename($principal)),
|
||||
'group-member-set' => $this->principal_set('group-member-set', $proxys),
|
||||
'getetag' => md5(serialize($proxys)),
|
||||
'resourcetype' => array(HTTP_WebDAV_Server::mkprop(groupdav::CALENDARSERVER, $type, '')),
|
||||
'resourcetype' => array(Api\CalDAV::mkprop(Api\CalDAV::CALENDARSERVER, $type, '')),
|
||||
));
|
||||
}
|
||||
|
||||
@ -1434,7 +1442,7 @@ class groupdav_principals extends groupdav_handler
|
||||
{
|
||||
if ($this->accounts->visible($account_lid)) // only add visible accounts, gives error in iCal otherwise
|
||||
{
|
||||
$set[] = HTTP_WebDAV_Server::mkprop('href', $this->base_uri.'/principals/'.($account_id < 0 ? 'groups/' : 'users/').$account_lid.'/');
|
||||
$set[] = Api\CalDAV::mkprop('href', $this->base_uri.'/principals/'.($account_id < 0 ? 'groups/' : 'users/').$account_lid.'/');
|
||||
}
|
||||
}
|
||||
if ($app_proxys)
|
||||
@ -1493,7 +1501,7 @@ class groupdav_principals extends groupdav_handler
|
||||
$rights = $location_grants['L'.$resource['cat_id']];
|
||||
if (isset($rights))
|
||||
{
|
||||
$set[] = HTTP_WebDAV_Server::mkprop('href', $this->base_uri.'/principals/'.$this->resource2name($resource).
|
||||
$set[] = Api\CalDAV::mkprop('href', $this->base_uri.'/principals/'.$this->resource2name($resource).
|
||||
'/calendar-proxy-'.($rights & EGW_ACL_DIRECT_BOOKING ? 'write' : 'read').'/');
|
||||
}
|
||||
}
|
||||
@ -1518,7 +1526,7 @@ class groupdav_principals extends groupdav_handler
|
||||
($account_lid = $this->accounts->id2name($account_id)) &&
|
||||
$this->accounts->visible($account_lid)) // only add visible accounts, gives error in iCal otherwise
|
||||
{
|
||||
$set[] = HTTP_WebDAV_Server::mkprop('href', $this->base_uri.'/principals/'.
|
||||
$set[] = Api\CalDAV::mkprop('href', $this->base_uri.'/principals/'.
|
||||
($account_id < 0 ? 'groups/' : 'users/').
|
||||
$account_lid.'/'.$app.'-proxy-'.($rights & EGW_ACL_EDIT ? 'write' : 'read').'/');
|
||||
}
|
186
api/src/CalDAV/PropfindIterator.php
Normal file
186
api/src/CalDAV/PropfindIterator.php
Normal file
@ -0,0 +1,186 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware: CalDAV/CardDAV/GroupDAV access: iterator for (huge) propfind sets
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage caldav
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2007-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\CalDAV;
|
||||
|
||||
/**
|
||||
* Iterator for propfinds using propfind callback of a Handler to query results in chunks
|
||||
*
|
||||
* The propfind method just computes a filter and then returns an instance of this iterator instead of the files:
|
||||
*
|
||||
* function propfind($path,$options,&$files,$user,$id='')
|
||||
* {
|
||||
* $filter = array();
|
||||
* // compute filter from path, options, ...
|
||||
*
|
||||
* $files['files'] = new groupdav_propfind_iterator($this,$filter,$files['files']);
|
||||
*
|
||||
* return true;
|
||||
* }
|
||||
*/
|
||||
class PropfindIterator implements \Iterator
|
||||
{
|
||||
/**
|
||||
* current path
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $path;
|
||||
|
||||
/**
|
||||
* Handler to call for entries
|
||||
*
|
||||
* @var Handler
|
||||
*/
|
||||
protected $handler;
|
||||
|
||||
/**
|
||||
* Filter of propfind call
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $filter;
|
||||
|
||||
/**
|
||||
* Extra responses to return too
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $common_files;
|
||||
|
||||
/**
|
||||
* current chunk
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $files;
|
||||
|
||||
|
||||
/**
|
||||
* Start value for callback
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $start=0;
|
||||
|
||||
/**
|
||||
* Number of entries queried from callback in one call
|
||||
*
|
||||
*/
|
||||
const CHUNK_SIZE = 500;
|
||||
|
||||
/**
|
||||
* Log calls via error_log()
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $debug = false;
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Handler $handler
|
||||
* @param array $filter filter for propfind call
|
||||
* @param array $files =array() extra files/responses to return too
|
||||
*/
|
||||
public function __construct(Handler $handler, $path, array $filter,array &$files=array())
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."('$path', ".array2string($filter).",)");
|
||||
$this->path = $path;
|
||||
$this->handler = $handler;
|
||||
$this->filter = $filter;
|
||||
$this->files = $this->common_files = $files;
|
||||
reset($this->files);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current element
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."() returning ".array2string(current($this->files)));
|
||||
return current($this->files);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the key of the current element
|
||||
*
|
||||
* @return int|string
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
$current = current($this->files);
|
||||
|
||||
if ($this->debug) error_log(__METHOD__."() returning ".array2string($current['path']));
|
||||
return $current['path']; // we return path as key
|
||||
}
|
||||
|
||||
/**
|
||||
* Move forward to next element (called after each foreach loop)
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
if (next($this->files) !== false)
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."() returning TRUE");
|
||||
return true;
|
||||
}
|
||||
// check if previous query gave less then CHUNK_SIZE entries --> we're done
|
||||
if ($this->start && count($this->files) < self::CHUNK_SIZE)
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."() returning FALSE (no more entries)");
|
||||
return false;
|
||||
}
|
||||
// try query further files via propfind callback of handler and store result in $this->files
|
||||
$this->files = $this->handler->propfind_callback($this->path,$this->filter,array($this->start,self::CHUNK_SIZE));
|
||||
if (!is_array($this->files) || !($entries = count($this->files)))
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."() returning FALSE (no more entries)");
|
||||
return false; // no further entries
|
||||
}
|
||||
$this->start += self::CHUNK_SIZE;
|
||||
reset($this->files);
|
||||
|
||||
if ($this->debug) error_log(__METHOD__."() this->start=$this->start, entries=$entries, count(this->files)=".count($this->files)." returning ".array2string(current($this->files) !== false));
|
||||
|
||||
return current($this->files) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewind the Iterator to the first element (called at beginning of foreach loop)
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."()");
|
||||
|
||||
$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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if current position is valid
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function valid ()
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."() returning ".array2string(current($this->files) !== false));
|
||||
return current($this->files) !== false;
|
||||
}
|
||||
}
|
218
api/src/Json/Tail.php
Normal file
218
api/src/Json/Tail.php
Normal file
@ -0,0 +1,218 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware - Ajax log file viewer (tail -f)
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Ralf Becker <RalfBecker@outdoor-training.de>
|
||||
* @copyright 2012-16 by RalfBecker@outdoor-training.de
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage json
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Json;
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
/**
|
||||
* Ajax log file viewer (tail -f)
|
||||
*
|
||||
* To not allow to view arbitrary files, allowed filenames are stored in the session.
|
||||
* Class fetches log-file periodically in chunks for 8k.
|
||||
* If fetch returns no new content next request will be in 2s, otherwise in 200ms.
|
||||
* As logfiles can be quiet huge, we display at max the last 32k of it!
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* $error_log = new Api\Json\Tail('/var/log/apache2/error_log');
|
||||
* echo $error_log->show();
|
||||
*
|
||||
* Strongly prefered for security reasons is to use a path relative to EGroupware's files_dir,
|
||||
* eg. new Api\Json\Tail('groupdav/somelog')!
|
||||
*/
|
||||
class Tail
|
||||
{
|
||||
/**
|
||||
* Maximum size of single ajax request
|
||||
*
|
||||
* Currently also maximum size / 4 of displayed logfile content!
|
||||
*/
|
||||
const MAX_CHUNK_SIZE = 8192;
|
||||
|
||||
/**
|
||||
* Contains allowed filenames to display, we can NOT allow to display arbitrary files!
|
||||
*
|
||||
* @param array
|
||||
*/
|
||||
protected $filenames;
|
||||
|
||||
/**
|
||||
* Filename class is instanciated to view, set by constructor
|
||||
*
|
||||
* @param string
|
||||
*/
|
||||
protected $filename;
|
||||
|
||||
/**
|
||||
* Methods allowed to call via menuaction
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $public_functions = array(
|
||||
'download' => true,
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $filename =null if not starting with as slash relative to EGw files dir (this is strongly prefered for security reasons)
|
||||
*/
|
||||
public function __construct($filename=null)
|
||||
{
|
||||
$this->filenames =& Api\Cache::getSession('phpgwapi', __CLASS__);
|
||||
|
||||
if ($filename)
|
||||
{
|
||||
$this->filename = $filename;
|
||||
|
||||
if (!$this->filenames || !in_array($filename,$this->filenames)) $this->filenames[] = $filename;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax callback to load next chunk of log-file
|
||||
*
|
||||
* @param string $filename
|
||||
* @param int $start =0 last position in log-file
|
||||
* @throws Api\Exception\WrongParameter
|
||||
*/
|
||||
public function ajax_chunk($filename,$start=0)
|
||||
{
|
||||
if (!in_array($filename,$this->filenames))
|
||||
{
|
||||
throw new Api\Exception\WrongParameter("Not allowed to view '$filename'!");
|
||||
}
|
||||
if ($filename[0] != '/') $filename = $GLOBALS['egw_info']['server']['files_dir'].'/'.$filename;
|
||||
|
||||
if (file_exists($filename))
|
||||
{
|
||||
$size = filesize($filename);
|
||||
if (!$start || $start < 0 || $start > $size || $size-$start > 4*self::MAX_CHUNK_SIZE)
|
||||
{
|
||||
$start = $size - 4*self::MAX_CHUNK_SIZE;
|
||||
if ($start < 0) $start = 0;
|
||||
}
|
||||
$hsize = Api\Vfs::hsize($size);
|
||||
$content = file_get_contents($filename, false, null, $start, self::MAX_CHUNK_SIZE);
|
||||
$length = bytes($content);
|
||||
$writable = is_writable($filename) || is_writable(dirname($filename));
|
||||
}
|
||||
else
|
||||
{
|
||||
$start = $length = 0;
|
||||
$content = '';
|
||||
$writable = $hsize = false;
|
||||
}
|
||||
$response = Response::get();
|
||||
$response->data(array( // send all responses as data
|
||||
'size' => $hsize,
|
||||
'writable' => $writable,
|
||||
'next' => $start + $length,
|
||||
'length' => $length,
|
||||
'content' => $content,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax callback to delete log-file
|
||||
*
|
||||
* @param string $filename
|
||||
* @param boolean $truncate =false true: truncate file, false: delete file
|
||||
* @throws Api\Exception\WrongParameter
|
||||
*/
|
||||
public function ajax_delete($filename,$truncate=false)
|
||||
{
|
||||
if (!in_array($filename,$this->filenames))
|
||||
{
|
||||
throw new Api\Exception\WrongParameter("Not allowed to view '$filename'!");
|
||||
}
|
||||
if ($filename[0] != '/') $filename = $GLOBALS['egw_info']['server']['files_dir'].'/'.$filename;
|
||||
if ($truncate)
|
||||
{
|
||||
file_put_contents($filename, '');
|
||||
}
|
||||
else
|
||||
{
|
||||
unlink($filename);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return html & javascript for logviewer
|
||||
*
|
||||
* @param string $header =null default $this->filename
|
||||
* @return string
|
||||
* @throws Api\Exception\WrongParameter
|
||||
*/
|
||||
public function show($header=null)
|
||||
{
|
||||
if (!isset($this->filename))
|
||||
{
|
||||
throw new Api\Exception\WrongParameter("Must be instanciated with filename!");
|
||||
}
|
||||
if (is_null($header)) $header = $this->filename;
|
||||
|
||||
return '
|
||||
<p style="float: left; margin: 5px"><b>'.htmlspecialchars($header).'</b></p>
|
||||
<div style="float: right; margin: 2px; margin-right: 5px">
|
||||
'.Api\Html::form(
|
||||
Api\Html::input('clear_log',lang('Clear window'),'button','id="clear_log"')."\n".
|
||||
Api\Html::input('delete_log',lang('Delete file'),'button','id="purge_log"')."\n".
|
||||
Api\Html::input('empty_log',lang('Empty file'),'button','id="empty_log"')."\n".
|
||||
Api\Html::input('download_log',lang('Download'),'submit','id="download_log"'),
|
||||
'','/index.php',array(
|
||||
'menuaction' => 'api.'.__CLASS__.'.download',
|
||||
'filename' => $this->filename,
|
||||
)).'
|
||||
</div>
|
||||
<pre class="tail" id="log" data-filename="'.$this->filename.'" style="clear: both; width: 99.5%; border: 2px groove silver; margin-bottom: 0; overflow: auto;"></pre>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a file specified per GET parameter (must be in $this->filesnames!)
|
||||
*
|
||||
* @throws Api\Exception\WrongParameter
|
||||
*/
|
||||
public function download()
|
||||
{
|
||||
$filename = $_GET['filename'];
|
||||
if (!in_array($filename,$this->filenames))
|
||||
{
|
||||
throw new Api\Exception\WrongParameter("Not allowed to download '$filename'!");
|
||||
}
|
||||
Api\Header\Content::type(basename($filename), 'text/plain');
|
||||
if ($filename[0] != '/') $filename = $GLOBALS['egw_info']['server']['files_dir'].'/'.$filename;
|
||||
for($n=ob_get_level(); $n > 0; --$n)
|
||||
{
|
||||
ob_end_clean(); // stop all output buffering, to NOT run into memory_limit
|
||||
}
|
||||
readfile($filename);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// some testcode, if this file is called via it's URL (you need to uncomment and adapt filename!)
|
||||
/*if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE__)
|
||||
{
|
||||
$GLOBALS['egw_info'] = array(
|
||||
'flags' => array(
|
||||
'currentapp' => 'admin',
|
||||
'nonavbar' => true,
|
||||
),
|
||||
);
|
||||
include_once '../../header.inc.php';
|
||||
|
||||
$error_log = new Tail('/opt/local/apache2/logs/error_log');
|
||||
echo $error_log->show();
|
||||
}*/
|
@ -1054,7 +1054,7 @@ class Account implements \ArrayAccess
|
||||
}
|
||||
if ($data['acc_smtp_type'])
|
||||
{
|
||||
if (substr($data['acc_imap_type'], 0, 4) == 'Smtp')
|
||||
if (substr($data['acc_smtp_type'], 0, 4) == 'Smtp')
|
||||
{
|
||||
$data['acc_smtp_type'] = __NAMESPACE__.'\\'.$data['acc_smtp_type'];
|
||||
}
|
||||
|
@ -11,17 +11,19 @@
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
/**
|
||||
* EGroupware: CalDAV / GroupDAV access: calendar handler
|
||||
* CalDAV/CardDAV/GroupDAV access: Calendar handler
|
||||
*
|
||||
* Permanent error_log() calls should use $this->groupdav->log($str) instead, to be send to PHP error_log()
|
||||
* Permanent error_log() calls should use $this->caldav->log($str) instead, to be send to PHP error_log()
|
||||
* and our request-log (prefixed with "### " after request and response, like exceptions).
|
||||
*
|
||||
* @ToDo: new properties on calendars and it's ressources specially from sharing:
|
||||
* - for the invite property: 5.2.2 in https://trac.calendarserver.org/browser/CalendarServer/trunk/doc/Extensions/caldav-sharing.txt
|
||||
* - https://trac.calendarserver.org/browser/CalendarServer/trunk/doc/Extensions/caldav-schedulingchanges.txt
|
||||
*/
|
||||
class calendar_groupdav extends groupdav_handler
|
||||
class calendar_groupdav extends Api\CalDAV\Handler
|
||||
{
|
||||
/**
|
||||
* bo class of the application
|
||||
@ -78,7 +80,7 @@ class calendar_groupdav extends groupdav_handler
|
||||
/**
|
||||
* 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 = ''!
|
||||
* Get's set in constructor to 'caldav_name' and self::$path_extension = ''!
|
||||
*/
|
||||
static $path_attr = 'id';
|
||||
|
||||
@ -86,11 +88,11 @@ class calendar_groupdav extends groupdav_handler
|
||||
* Constructor
|
||||
*
|
||||
* @param string $app 'calendar', 'addressbook' or 'infolog'
|
||||
* @param groupdav $groupdav calling class
|
||||
* @param Api\CalDAV $caldav calling class
|
||||
*/
|
||||
function __construct($app, groupdav $groupdav)
|
||||
function __construct($app, Api\CalDAV $caldav)
|
||||
{
|
||||
parent::__construct($app, $groupdav);
|
||||
parent::__construct($app, $caldav);
|
||||
|
||||
$this->bo = new calendar_boupdate();
|
||||
$this->vCalendar = new Horde_Icalendar;
|
||||
@ -99,7 +101,7 @@ class calendar_groupdav extends groupdav_handler
|
||||
if (version_compare($GLOBALS['egw_info']['apps']['calendar']['version'], '1.9.003', '>='))
|
||||
{
|
||||
self::$path_attr = 'caldav_name';
|
||||
groupdav_handler::$path_extension = '';
|
||||
self::$path_extension = '';
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,8 +122,8 @@ class calendar_groupdav extends groupdav_handler
|
||||
if (!is_array($event)) $event = $this->bo->read($event);
|
||||
$name = $event[self::$path_attr];
|
||||
}
|
||||
$name .= groupdav_handler::$path_extension;
|
||||
//error_log(__METHOD__.'('.array2string($event).") path_attr='".self::$path_attr."', path_extension='".groupdav_handler::$path_extension."' returning ".array2string($name));
|
||||
$name .= self::$path_extension;
|
||||
//error_log(__METHOD__.'('.array2string($event).") path_attr='".self::$path_attr."', path_extension='".self::$path_extension."' returning ".array2string($name));
|
||||
return $name;
|
||||
}
|
||||
|
||||
@ -152,8 +154,8 @@ class calendar_groupdav extends groupdav_handler
|
||||
|
||||
if (isset($_GET['download']))
|
||||
{
|
||||
$this->groupdav->propfind_options['props'] = array(array(
|
||||
'xmlns' => groupdav::CALDAV,
|
||||
$this->caldav->propfind_options['props'] = array(array(
|
||||
'xmlns' => Api\CalDAV::CALDAV,
|
||||
'name' => 'calendar-data',
|
||||
));
|
||||
}
|
||||
@ -251,7 +253,7 @@ class calendar_groupdav extends groupdav_handler
|
||||
else
|
||||
{
|
||||
// return iterator, calling ourself to return result in chunks
|
||||
$files['files'] = new groupdav_propfind_iterator($this,$path,$filter,$files['files']);
|
||||
$files['files'] = new Api\CalDAV\PropfindIterator($this,$path,$filter,$files['files']);
|
||||
}
|
||||
if (isset($_GET['download']))
|
||||
{
|
||||
@ -319,7 +321,7 @@ class calendar_groupdav extends groupdav_handler
|
||||
{
|
||||
if ($this->debug) $starttime = microtime(true);
|
||||
|
||||
$calendar_data = $this->groupdav->prop_requested('calendar-data', groupdav::CALDAV, true);
|
||||
$calendar_data = $this->caldav->prop_requested('calendar-data', Api\CalDAV::CALDAV, true);
|
||||
if (!is_array($calendar_data)) $calendar_data = false; // not in allprop or autoindex
|
||||
|
||||
$files = array();
|
||||
@ -358,14 +360,14 @@ class calendar_groupdav extends groupdav_handler
|
||||
'getetag' => '"'.$etag.'"',
|
||||
'getlastmodified' => $event['modified'],
|
||||
// user and timestamp of creation or last modification of event, used in calendarserver only for shared calendars
|
||||
'created-by' => HTTP_WebDAV_Server::mkprop(groupdav::CALENDARSERVER, 'created-by',
|
||||
'created-by' => Api\CalDAV::mkprop(Api\CalDAV::CALENDARSERVER, 'created-by',
|
||||
$this->_created_updated_by_prop($event['creator'], $event['created'])),
|
||||
'updated-by' => HTTP_WebDAV_Server::mkprop(groupdav::CALENDARSERVER, 'updated-by',
|
||||
'updated-by' => Api\CalDAV::mkprop(Api\CalDAV::CALENDARSERVER, 'updated-by',
|
||||
$this->_created_updated_by_prop($event['modifier'], $event['modified'])),
|
||||
);
|
||||
if ($this->use_schedule_tag)
|
||||
{
|
||||
$props['schedule-tag'] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV, 'schedule-tag', '"'.$schedule_tag.'"');
|
||||
$props['schedule-tag'] = Api\CalDAV::mkprop(Api\CalDAV::CALDAV, 'schedule-tag', '"'.$schedule_tag.'"');
|
||||
}
|
||||
//error_log(__FILE__ . __METHOD__ . "Calendar Data : $calendar_data");
|
||||
if ($calendar_data)
|
||||
@ -375,16 +377,16 @@ class calendar_groupdav extends groupdav_handler
|
||||
!isset($calendar_data['children']['expand']) ? false :
|
||||
($calendar_data['children']['expand']['attrs'] ? $calendar_data['children']['expand']['attrs'] : true));
|
||||
$props['getcontentlength'] = bytes($content);
|
||||
$props['calendar-data'] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-data',$content);
|
||||
$props['calendar-data'] = Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-data',$content);
|
||||
}
|
||||
/* Calendarserver reports new events with schedule-changes: action: create, which iCal request
|
||||
* adding it, unfortunately does not lead to showing the new event in the users inbox
|
||||
if (strpos($path, '/inbox/') !== false && $this->groupdav->prop_requested('schedule-changes'))
|
||||
if (strpos($path, '/inbox/') !== false && $this->caldav->prop_requested('schedule-changes'))
|
||||
{
|
||||
$props['schedule-changes'] = HTTP_WebDAV_Server::mkprop(groupdav::CALENDARSERVER,'schedule-changes',array(
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALENDARSERVER,'dtstamp',gmdate('Ymd\THis',$event['created']).'Z'),
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALENDARSERVER,'action',array(
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALENDARSERVER,'create',''),
|
||||
$props['schedule-changes'] = Api\CalDAV::mkprop(Api\CalDAV::CALENDARSERVER,'schedule-changes',array(
|
||||
Api\CalDAV::mkprop(Api\CalDAV::CALENDARSERVER,'dtstamp',gmdate('Ymd\THis',$event['created']).'Z'),
|
||||
Api\CalDAV::mkprop(Api\CalDAV::CALENDARSERVER,'action',array(
|
||||
Api\CalDAV::mkprop(Api\CalDAV::CALENDARSERVER,'create',''),
|
||||
)),
|
||||
));
|
||||
}*/
|
||||
@ -438,18 +440,18 @@ class calendar_groupdav extends groupdav_handler
|
||||
{
|
||||
if ($user && ($val = $this->accounts->id2name($user, $name)))
|
||||
{
|
||||
$ns = groupdav::CALENDARSERVER;
|
||||
$ns = Api\CalDAV::CALENDARSERVER;
|
||||
if ($prop == 'href')
|
||||
{
|
||||
$ns = '';
|
||||
$val = 'mailto:'.$val;
|
||||
}
|
||||
$props[$prop] = $ns ? HTTP_WebDAV_Server::mkprop($ns, $prop, $val) : HTTP_WebDAV_Server::mkprop($prop, $val);
|
||||
$props[$prop] = $ns ? Api\CalDAV::mkprop($ns, $prop, $val) : Api\CalDAV::mkprop($prop, $val);
|
||||
}
|
||||
}
|
||||
if ($time)
|
||||
{
|
||||
$props['dtstamp'] = HTTP_WebDAV_Server::mkprop(groupdav::CALENDARSERVER, 'dtstamp', gmdate('Ymd\\This\\Z', $time));
|
||||
$props['dtstamp'] = Api\CalDAV::mkprop(Api\CalDAV::CALENDARSERVER, 'dtstamp', gmdate('Ymd\\This\\Z', $time));
|
||||
}
|
||||
//error_log(__METHOD__."($user, $time) returning ".array2string($props));
|
||||
return $props ? $props : '';
|
||||
@ -567,11 +569,11 @@ class calendar_groupdav extends groupdav_handler
|
||||
case 'sync-level':
|
||||
if ($option['data'] != '1')
|
||||
{
|
||||
$this->groupdav->log(__METHOD__."(...) only sync-level {$option['data']} requested, but only 1 supported! options[other]=".array2string($options['other']));
|
||||
$this->caldav->log(__METHOD__."(...) only sync-level {$option['data']} requested, but only 1 supported! options[other]=".array2string($options['other']));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$this->groupdav->log(__METHOD__."(...) unknown xml tag '{$option['name']}': options[other]=".array2string($options['other']));
|
||||
$this->caldav->log(__METHOD__."(...) unknown xml tag '{$option['name']}': options[other]=".array2string($options['other']));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -587,8 +589,8 @@ class calendar_groupdav extends groupdav_handler
|
||||
|
||||
if ($id)
|
||||
{
|
||||
$cal_filters['query'][self::$path_attr] = groupdav_handler::$path_extension ?
|
||||
basename($id,groupdav_handler::$path_extension) : $id;
|
||||
$cal_filters['query'][self::$path_attr] = self::$path_extension ?
|
||||
basename($id,self::$path_extension) : $id;
|
||||
}
|
||||
else // fetch all given url's
|
||||
{
|
||||
@ -599,8 +601,8 @@ class calendar_groupdav extends groupdav_handler
|
||||
$parts = explode('/',$option['data']);
|
||||
if (($id = urldecode(array_pop($parts))))
|
||||
{
|
||||
$cal_filters['query'][self::$path_attr][] = groupdav_handler::$path_extension ?
|
||||
basename($id,groupdav_handler::$path_extension) : $id;
|
||||
$cal_filters['query'][self::$path_attr][] = self::$path_extension ?
|
||||
basename($id,self::$path_extension) : $id;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -872,12 +874,12 @@ class calendar_groupdav extends groupdav_handler
|
||||
{
|
||||
if ($oldEvent['owner'] == $GLOBALS['egw_info']['user']['account_id'])
|
||||
{
|
||||
$this->groupdav->log("Both If-Match and If-Schedule-Tag-Match header given: If-Schedule-Tag-Match ignored for event owner!");
|
||||
$this->caldav->log("Both If-Match and If-Schedule-Tag-Match header given: If-Schedule-Tag-Match ignored for event owner!");
|
||||
unset($_SERVER['HTTP_IF_SCHEDULE_TAG_MATCH']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->groupdav->log("Both If-Match and If-Schedule-Tag-Match header given: If-Schedule-Tag-Match takes precedence for participants!");
|
||||
$this->caldav->log("Both If-Match and If-Schedule-Tag-Match header given: If-Schedule-Tag-Match takes precedence for participants!");
|
||||
}
|
||||
}
|
||||
// check CalDAV Scheduling schedule-tag precondition
|
||||
@ -935,7 +937,7 @@ class calendar_groupdav extends groupdav_handler
|
||||
!($oldEvent['recur_date'] == $event['recurrence'] || !$event['recurrence'] && !$oldEvent['recurrence']))
|
||||
{
|
||||
// if recurrence not found --> log it and continue with other recurrence
|
||||
$this->groupdav->log(__METHOD__."(,,$user) could NOT find recurrence=$event[recurrence]=".egw_time::to($event['recurrence']).' of event series! event='.array2string($event));
|
||||
$this->caldav->log(__METHOD__."(,,$user) could NOT find recurrence=$event[recurrence]=".egw_time::to($event['recurrence']).' of event series! event='.array2string($event));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -966,7 +968,7 @@ class calendar_groupdav extends groupdav_handler
|
||||
}
|
||||
if (!$modified) // NO modififictions, or none we understood --> log it and return Ok: "204 No Content"
|
||||
{
|
||||
$this->groupdav->log(__METHOD__."(,,$user) NO changes for current user events=".array2string($events).', old-event='.array2string($oldEvent));
|
||||
$this->caldav->log(__METHOD__."(,,$user) NO changes for current user events=".array2string($events).', old-event='.array2string($oldEvent));
|
||||
}
|
||||
$this->put_response_headers($eventId, $options['path'], '204 No Content', self::$path_attr == 'caldav_name');
|
||||
|
||||
@ -1002,7 +1004,7 @@ class calendar_groupdav extends groupdav_handler
|
||||
}
|
||||
|
||||
if (!($cal_id = $handler->importVCal($vCalendar, $eventId,
|
||||
self::etag2value($this->http_if_match), false, 0, $this->groupdav->current_user_principal, $user, $charset, $id)))
|
||||
self::etag2value($this->http_if_match), false, 0, $this->caldav->current_user_principal, $user, $charset, $id)))
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."(,$id) eventId=$eventId: importVCal('$options[content]') returned ".array2string($cal_id));
|
||||
if ($eventId && $cal_id === false)
|
||||
@ -1092,7 +1094,7 @@ class calendar_groupdav extends groupdav_handler
|
||||
list($eventId) = explode(':', $id);
|
||||
|
||||
if (!($cal_id = $handler->importVCal($vCalendar, $eventId, null,
|
||||
false, 0, $this->groupdav->current_user_principal, $user, $charset)))
|
||||
false, 0, $this->caldav->current_user_principal, $user, $charset)))
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."() importVCal($eventId) returned false");
|
||||
}
|
||||
@ -1128,13 +1130,13 @@ class calendar_groupdav extends groupdav_handler
|
||||
$handler->setSupportedFields('groupdav');
|
||||
$handler->calendarOwner = $handler->user = 0; // to NOT default owner/organizer to something
|
||||
if (!($component = $vcal->getComponent(0)) ||
|
||||
!($event = $handler->vevent2egw($component, $version, $handler->supportedFields, $this->groupdav->current_user_principal, 'Horde_Icalendar_Vfreebusy')))
|
||||
!($event = $handler->vevent2egw($component, $version, $handler->supportedFields, $this->caldav->current_user_principal, 'Horde_Icalendar_Vfreebusy')))
|
||||
{
|
||||
return '400 Bad request';
|
||||
}
|
||||
if ($event['owner'] != $user)
|
||||
{
|
||||
$this->groupdav->log(__METHOD__."('$ical',,$user) ORGANIZER is NOT principal!");
|
||||
$this->caldav->log(__METHOD__."('$ical',,$user) ORGANIZER is NOT principal!");
|
||||
return '403 Forbidden';
|
||||
}
|
||||
//print_r($event);
|
||||
@ -1149,7 +1151,7 @@ class calendar_groupdav extends groupdav_handler
|
||||
$xml->openMemory();
|
||||
$xml->setIndent(true);
|
||||
$xml->startDocument('1.0', 'UTF-8');
|
||||
$xml->startElementNs('C', 'schedule-response', groupdav::CALDAV);
|
||||
$xml->startElementNs('C', 'schedule-response', Api\CalDAV::CALDAV);
|
||||
|
||||
foreach(array_keys($event['participants']) as $uid)
|
||||
{
|
||||
@ -1224,16 +1226,16 @@ class calendar_groupdav extends groupdav_handler
|
||||
|
||||
if ($this->bo->check_perms(EGW_ACL_FREEBUSY, 0, $user))
|
||||
{
|
||||
$privileges['read-free-busy'] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV, 'read-free-busy', '');
|
||||
$privileges['read-free-busy'] = Api\CalDAV::mkprop(Api\CalDAV::CALDAV, 'read-free-busy', '');
|
||||
|
||||
if (substr($path, -8) == '/outbox/' && $this->bo->check_acl_invite($user))
|
||||
{
|
||||
$privileges['schedule-send'] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV, 'schedule-send', '');
|
||||
$privileges['schedule-send'] = Api\CalDAV::mkprop(Api\CalDAV::CALDAV, 'schedule-send', '');
|
||||
}
|
||||
}
|
||||
if (substr($path, -7) == '/inbox/' && $this->bo->check_acl_invite($user))
|
||||
{
|
||||
$privileges['schedule-deliver'] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV, 'schedule-deliver', '');
|
||||
$privileges['schedule-deliver'] = Api\CalDAV::mkprop(Api\CalDAV::CALDAV, 'schedule-deliver', '');
|
||||
}
|
||||
// remove bind privilege on other users or groups calendars, if calendar config require_acl_invite is set
|
||||
// and current user has no invite grant
|
||||
@ -1494,47 +1496,47 @@ class calendar_groupdav extends groupdav_handler
|
||||
if (!isset($props['calendar-description']))
|
||||
{
|
||||
// default calendar description: can be overwritten via PROPPATCH, in which case it's already set
|
||||
$props['calendar-description'] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-description',$displayname);
|
||||
$props['calendar-description'] = Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-description',$displayname);
|
||||
}
|
||||
$supported_components = array(
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'comp',array('name' => 'VCALENDAR')),
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'comp',array('name' => 'VEVENT')),
|
||||
Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'comp',array('name' => 'VCALENDAR')),
|
||||
Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'comp',array('name' => 'VEVENT')),
|
||||
);
|
||||
// outbox supports VFREEBUSY too, it is required from OS X iCal to autocomplete locations
|
||||
if (substr($path,-8) == '/outbox/')
|
||||
{
|
||||
$supported_components[] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'comp',array('name' => 'VFREEBUSY'));
|
||||
$supported_components[] = Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'comp',array('name' => 'VFREEBUSY'));
|
||||
}
|
||||
$props['supported-calendar-component-set'] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,
|
||||
$props['supported-calendar-component-set'] = Api\CalDAV::mkprop(Api\CalDAV::CALDAV,
|
||||
'supported-calendar-component-set',$supported_components);
|
||||
// supported reports
|
||||
$props['supported-report-set'] = array(
|
||||
'calendar-query' => HTTP_WebDAV_Server::mkprop('supported-report',array(
|
||||
HTTP_WebDAV_Server::mkprop('report',array(
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-query',''))))),
|
||||
'calendar-multiget' => HTTP_WebDAV_Server::mkprop('supported-report',array(
|
||||
HTTP_WebDAV_Server::mkprop('report',array(
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-multiget',''))))),
|
||||
'free-busy-query' => HTTP_WebDAV_Server::mkprop('supported-report',array(
|
||||
HTTP_WebDAV_Server::mkprop('report',array(
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'free-busy-query',''))))),
|
||||
'calendar-query' => Api\CalDAV::mkprop('supported-report',array(
|
||||
Api\CalDAV::mkprop('report',array(
|
||||
Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-query',''))))),
|
||||
'calendar-multiget' => Api\CalDAV::mkprop('supported-report',array(
|
||||
Api\CalDAV::mkprop('report',array(
|
||||
Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-multiget',''))))),
|
||||
'free-busy-query' => Api\CalDAV::mkprop('supported-report',array(
|
||||
Api\CalDAV::mkprop('report',array(
|
||||
Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'free-busy-query',''))))),
|
||||
);
|
||||
// rfc 6578 sync-collection report for everything but outbox
|
||||
// only if "delete-prevention" is switched on (deleted entries get marked deleted but not actualy deleted
|
||||
if (strpos($path, '/outbox/') === false && $GLOBALS['egw_info']['server']['calendar_delete_history'])
|
||||
{
|
||||
$props['supported-report-set']['sync-collection'] = HTTP_WebDAV_Server::mkprop('supported-report',array(
|
||||
HTTP_WebDAV_Server::mkprop('report',array(
|
||||
HTTP_WebDAV_Server::mkprop('sync-collection','')))));
|
||||
$props['supported-report-set']['sync-collection'] = Api\CalDAV::mkprop('supported-report',array(
|
||||
Api\CalDAV::mkprop('report',array(
|
||||
Api\CalDAV::mkprop('sync-collection','')))));
|
||||
}
|
||||
$props['supported-calendar-data'] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'supported-calendar-data',array(
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-data', array('content-type' => 'text/calendar', 'version'=> '2.0')),
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-data', array('content-type' => 'text/x-calendar', 'version'=> '1.0'))));
|
||||
$props['supported-calendar-data'] = Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'supported-calendar-data',array(
|
||||
Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-data', array('content-type' => 'text/calendar', 'version'=> '2.0')),
|
||||
Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-data', array('content-type' => 'text/x-calendar', 'version'=> '1.0'))));
|
||||
|
||||
// get timezone of calendar
|
||||
if ($this->groupdav->prop_requested('calendar-timezone'))
|
||||
if ($this->caldav->prop_requested('calendar-timezone'))
|
||||
{
|
||||
$props['calendar-timezone'] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-timezone',
|
||||
$props['calendar-timezone'] = Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-timezone',
|
||||
calendar_timezones::user_timezone($user));
|
||||
}
|
||||
return $props;
|
||||
@ -1594,7 +1596,7 @@ class calendar_groupdav extends groupdav_handler
|
||||
foreach(explode(',', $pref) as $res_id)
|
||||
{
|
||||
$is_location = $res == 'locations';
|
||||
$shared['r'.$res_id] = str_replace('s/', '-', groupdav_principals::resource2name($res_id, $is_location));
|
||||
$shared['r'.$res_id] = str_replace('s/', '-', Api\CalDAV\Principals::resource2name($res_id, $is_location));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1652,12 +1654,12 @@ class calendar_groupdav extends groupdav_handler
|
||||
);
|
||||
|
||||
// allow to subscribe to resources
|
||||
if ($GLOBALS['egw_info']['user']['apps']['resources'] && ($all_resources = groupdav_principals::get_resources()))
|
||||
if ($GLOBALS['egw_info']['user']['apps']['resources'] && ($all_resources = Api\CalDAV\Principals::get_resources()))
|
||||
{
|
||||
$resources = $locations = array();
|
||||
foreach($all_resources as $resource)
|
||||
{
|
||||
if (groupdav_principals::resource_is_location($resource))
|
||||
if (Api\CalDAV\Principals::resource_is_location($resource))
|
||||
{
|
||||
$locations[$resource['res_id']] = $resource['name'];
|
||||
}
|
||||
|
10
groupdav.php
10
groupdav.php
@ -9,17 +9,17 @@
|
||||
*
|
||||
* Otherwise authentication request will be send over and over again, as password is NOT available to PHP!
|
||||
*
|
||||
* Using the PEAR HTTP/WebDAV/Server class (which need to be installed!)
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage groupdav
|
||||
* @subpackage caldav
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2007-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
// switching off output compression for Lighttpd and HTTPS, as it makes problems with TB Lightning
|
||||
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' &&
|
||||
strpos($_SERVER['SERVER_SOFTWARE'],'lighttpd/1.4') === 0 &&
|
||||
@ -48,6 +48,6 @@ $GLOBALS['egw_info']['user']['preferences'] = $GLOBALS['egw']->preferences->read
|
||||
|
||||
$headertime = microtime(true);
|
||||
|
||||
$groupdav = new groupdav();
|
||||
$groupdav->ServeRequest();
|
||||
$caldav = new Api\CalDAV();
|
||||
$caldav->ServeRequest();
|
||||
//error_log(sprintf('GroupDAV %s: status "%s", took %5.3f s'.($headertime?' (header include took %5.3f s)':''),$_SERVER['REQUEST_METHOD'].($_SERVER['REQUEST_METHOD']=='REPORT'?' '.$groupdav->propfind_options['root']['name']:'').' '.$_SERVER['PATH_INFO'],$groupdav->_http_status,microtime(true)-$starttime,$headertime-$starttime));
|
||||
|
@ -11,13 +11,15 @@
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
/**
|
||||
* EGroupware: GroupDAV access: infolog handler
|
||||
*
|
||||
* Permanent error_log() calls should use $this->groupdav->log($str) instead, to be send to PHP error_log()
|
||||
* Permanent error_log() calls should use $this->caldav->log($str) instead, to be send to PHP error_log()
|
||||
* and our request-log (prefixed with "### " after request and response, like exceptions).
|
||||
*/
|
||||
class infolog_groupdav extends groupdav_handler
|
||||
class infolog_groupdav extends Api\CalDAV\Handler
|
||||
{
|
||||
/**
|
||||
* bo class of the application
|
||||
@ -49,7 +51,7 @@ class infolog_groupdav extends groupdav_handler
|
||||
/**
|
||||
* Are we using info_id, info_uid or caldav_name for the path/url
|
||||
*
|
||||
* Get's set in constructor to 'caldav_name' and groupdav_handler::$path_extension = ''!
|
||||
* Get's set in constructor to 'caldav_name' and self::$path_extension = ''!
|
||||
*/
|
||||
static $path_attr = 'info_id';
|
||||
|
||||
@ -57,11 +59,11 @@ class infolog_groupdav extends groupdav_handler
|
||||
* Constructor
|
||||
*
|
||||
* @param string $app 'calendar', 'addressbook' or 'infolog'
|
||||
* @param groupdav $groupdav calling class
|
||||
* @param Api\CalDAV $caldav calling class
|
||||
*/
|
||||
function __construct($app, groupdav $groupdav)
|
||||
function __construct($app, Api\CalDAV $caldav)
|
||||
{
|
||||
parent::__construct($app, $groupdav);
|
||||
parent::__construct($app, $caldav);
|
||||
|
||||
$this->bo = new infolog_bo();
|
||||
$this->vCalendar = new Horde_Icalendar;
|
||||
@ -70,7 +72,7 @@ class infolog_groupdav extends groupdav_handler
|
||||
if (version_compare($GLOBALS['egw_info']['apps']['calendar']['version'], '1.9.002', '>='))
|
||||
{
|
||||
self::$path_attr = 'caldav_name';
|
||||
groupdav_handler::$path_extension = '';
|
||||
self::$path_extension = '';
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,7 +93,7 @@ class infolog_groupdav extends groupdav_handler
|
||||
if (!is_array($info)) $info = $this->bo->read($info);
|
||||
$name = $info[self::$path_attr];
|
||||
}
|
||||
return $name.groupdav_handler::$path_extension;
|
||||
return $name.self::$path_extension;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -166,7 +168,7 @@ class infolog_groupdav extends groupdav_handler
|
||||
|
||||
// check if we have to return the full calendar data or just the etag's
|
||||
if (!($filter['calendar_data'] = $options['props'] == 'all' &&
|
||||
$options['root']['ns'] == groupdav::CALDAV) && is_array($options['props']))
|
||||
$options['root']['ns'] == Api\CalDAV::CALDAV) && is_array($options['props']))
|
||||
{
|
||||
foreach($options['props'] as $prop)
|
||||
{
|
||||
@ -208,7 +210,7 @@ class infolog_groupdav extends groupdav_handler
|
||||
else
|
||||
{
|
||||
// return iterator, calling ourself to return result in chunks
|
||||
$files['files'] = new groupdav_propfind_iterator($this,$path,$filter,$files['files']);
|
||||
$files['files'] = new Api\CalDAV\PropfindIterator($this,$path,$filter,$files['files']);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -295,7 +297,7 @@ class infolog_groupdav extends groupdav_handler
|
||||
{
|
||||
$content = $handler->exportVTODO($task, '2.0', null); // no METHOD:PUBLISH for CalDAV
|
||||
$props['getcontentlength'] = bytes($content);
|
||||
$props[] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-data',$content);
|
||||
$props[] = Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-data',$content);
|
||||
}
|
||||
$files[] = $this->add_resource($path, $task, $props);
|
||||
}
|
||||
@ -317,7 +319,7 @@ class infolog_groupdav extends groupdav_handler
|
||||
// hack to support limit with sync-collection report: tasks are returned in modified ASC order (oldest first)
|
||||
// if limit is smaller then full result, return modified-1 as sync-token, so client requests next chunk incl. modified
|
||||
// (which might contain further entries with identical modification time)
|
||||
if ($start[0] == 0 && $start[1] != groupdav_propfind_iterator::CHUNK_SIZE && $this->bo->total > $start[1])
|
||||
if ($start[0] == 0 && $start[1] != Api\CalDAV\PropfindIterator::CHUNK_SIZE && $this->bo->total > $start[1])
|
||||
{
|
||||
--$this->sync_collection_token;
|
||||
}
|
||||
@ -414,11 +416,11 @@ class infolog_groupdav extends groupdav_handler
|
||||
case 'sync-level':
|
||||
if ($option['data'] != '1')
|
||||
{
|
||||
$this->groupdav->log(__METHOD__."(...) only sync-level {$option['data']} requested, but only 1 supported! options[other]=".array2string($options['other']));
|
||||
$this->caldav->log(__METHOD__."(...) only sync-level {$option['data']} requested, but only 1 supported! options[other]=".array2string($options['other']));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$this->groupdav->log(__METHOD__."(...) unknown xml tag '{$option['name']}': options[other]=".array2string($options['other']));
|
||||
$this->caldav->log(__METHOD__."(...) unknown xml tag '{$option['name']}': options[other]=".array2string($options['other']));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -429,8 +431,8 @@ class infolog_groupdav extends groupdav_handler
|
||||
$ids = array();
|
||||
if ($id)
|
||||
{
|
||||
$cal_filters[self::$path_attr] = groupdav_handler::$path_extension ?
|
||||
basename($id,groupdav_handler::$path_extension) : $id;
|
||||
$cal_filters[self::$path_attr] = self::$path_extension ?
|
||||
basename($id,self::$path_extension) : $id;
|
||||
}
|
||||
else // fetch all given url's
|
||||
{
|
||||
@ -441,8 +443,8 @@ class infolog_groupdav extends groupdav_handler
|
||||
$parts = explode('/',$option['data']);
|
||||
if (($id = basename(urldecode(array_pop($parts)))))
|
||||
{
|
||||
$cal_filters[self::$path_attr][] = groupdav_handler::$path_extension ?
|
||||
basename($id,groupdav_handler::$path_extension) : $id;
|
||||
$cal_filters[self::$path_attr][] = self::$path_extension ?
|
||||
basename($id,self::$path_extension) : $id;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -474,7 +476,7 @@ class infolog_groupdav extends groupdav_handler
|
||||
}
|
||||
elseif (empty($attrs['start']))
|
||||
{
|
||||
$this->groupdav->log(__METHOD__.'('.array2string($attrs).') minimum one of start or end is required!');
|
||||
$this->caldav->log(__METHOD__.'('.array2string($attrs).') minimum one of start or end is required!');
|
||||
return '1'; // to not give sql error, but simply not filter out anything
|
||||
}
|
||||
// we dont need to care for DURATION line in rfc4791#section-9.9, as we always put that in DUE/info_enddate
|
||||
@ -784,33 +786,33 @@ class infolog_groupdav extends groupdav_handler
|
||||
|
||||
// calendar description
|
||||
$displayname = translation::convert(lang('Tasks of'),translation::charset(),'utf-8').' '.$displayname;
|
||||
$props['calendar-description'] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-description',$displayname);
|
||||
$props['calendar-description'] = Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-description',$displayname);
|
||||
// supported components, currently only VEVENT
|
||||
$props['supported-calendar-component-set'] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'supported-calendar-component-set',array(
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'comp',array('name' => 'VCALENDAR')),
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'comp',array('name' => 'VTODO')),
|
||||
$props['supported-calendar-component-set'] = Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'supported-calendar-component-set',array(
|
||||
Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'comp',array('name' => 'VCALENDAR')),
|
||||
Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'comp',array('name' => 'VTODO')),
|
||||
));
|
||||
// supported reports
|
||||
$props['supported-report-set'] = array(
|
||||
'calendar-query' => HTTP_WebDAV_Server::mkprop('supported-report',array(
|
||||
HTTP_WebDAV_Server::mkprop('report',array(
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-query',''))))),
|
||||
'calendar-multiget' => HTTP_WebDAV_Server::mkprop('supported-report',array(
|
||||
HTTP_WebDAV_Server::mkprop('report',array(
|
||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-multiget',''))))),
|
||||
'calendar-query' => Api\CalDAV::mkprop('supported-report',array(
|
||||
Api\CalDAV::mkprop('report',array(
|
||||
Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-query',''))))),
|
||||
'calendar-multiget' => Api\CalDAV::mkprop('supported-report',array(
|
||||
Api\CalDAV::mkprop('report',array(
|
||||
Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-multiget',''))))),
|
||||
);
|
||||
// only advertice rfc 6578 sync-collection report, if "delete-prevention" is switched on (deleted entries get marked deleted but not actualy deleted
|
||||
$config = config::read('infolog');
|
||||
if ($config['history'])
|
||||
{
|
||||
$props['supported-report-set']['sync-collection'] = HTTP_WebDAV_Server::mkprop('supported-report',array(
|
||||
HTTP_WebDAV_Server::mkprop('report',array(
|
||||
HTTP_WebDAV_Server::mkprop('sync-collection','')))));
|
||||
$props['supported-report-set']['sync-collection'] = Api\CalDAV::mkprop('supported-report',array(
|
||||
Api\CalDAV::mkprop('report',array(
|
||||
Api\CalDAV::mkprop('sync-collection','')))));
|
||||
}
|
||||
// get timezone of calendar
|
||||
if ($this->groupdav->prop_requested('calendar-timezone'))
|
||||
if ($this->caldav->prop_requested('calendar-timezone'))
|
||||
{
|
||||
$props['calendar-timezone'] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-timezone',
|
||||
$props['calendar-timezone'] = Api\CalDAV::mkprop(Api\CalDAV::CALDAV,'calendar-timezone',
|
||||
calendar_timezones::user_timezone($user));
|
||||
}
|
||||
return $props;
|
||||
|
@ -119,22 +119,19 @@ class common
|
||||
*
|
||||
* @param string $_appName the appname
|
||||
* @param string $_eventID the id of the content
|
||||
* @deprecated use Api\CalDAV::generate_uid($_appName, $_eventID)
|
||||
* @return string the unique id
|
||||
*/
|
||||
static function generate_uid($_appName, $_eventID)
|
||||
{
|
||||
if(empty($_appName) || empty($_eventID)) return false;
|
||||
|
||||
// not used: $suffix = $GLOBALS['egw_info']['server']['hostname'] ? $GLOBALS['egw_info']['server']['hostname'] : 'local';
|
||||
$prefix = $_appName.'-'.$_eventID.'-'.$GLOBALS['egw_info']['server']['install_id'];
|
||||
|
||||
return $prefix;
|
||||
return Api\CalDAV::generate_uid($_appName, $_eventID);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the local content id from a global UID
|
||||
*
|
||||
* @param sting $_globalUid the global UID
|
||||
* @deprecated dont use, as only EGroupware interal uids are reversable
|
||||
* @return int local egw content id
|
||||
*/
|
||||
static function get_egwId($_globalUid)
|
||||
|
@ -4,13 +4,15 @@
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Ralf Becker <RalfBecker@outdoor-training.de>
|
||||
* @copyright 2012 by RalfBecker@outdoor-training.de
|
||||
* @copyright 2012-16 by RalfBecker@outdoor-training.de
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package etemplate
|
||||
* @subpackage api
|
||||
* @package api
|
||||
* @subpackage json
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
use EGroupware\Api\Json\Tail;
|
||||
|
||||
/**
|
||||
* Ajax log file viewer (tail -f)
|
||||
*
|
||||
@ -26,186 +28,7 @@
|
||||
*
|
||||
* Strongly prefered for security reasons is to use a path relative to EGroupware's files_dir,
|
||||
* eg. new egw_tail('groupdav/somelog')!
|
||||
*/
|
||||
class egw_tail
|
||||
{
|
||||
/**
|
||||
* Maximum size of single ajax request
|
||||
*
|
||||
* Currently also maximum size / 4 of displayed logfile content!
|
||||
* @deprecated use Api\Json\Tail
|
||||
*/
|
||||
const MAX_CHUNK_SIZE = 8192;
|
||||
|
||||
/**
|
||||
* Contains allowed filenames to display, we can NOT allow to display arbitrary files!
|
||||
*
|
||||
* @param array
|
||||
*/
|
||||
protected $filenames;
|
||||
|
||||
/**
|
||||
* Filename class is instanciated to view, set by constructor
|
||||
*
|
||||
* @param string
|
||||
*/
|
||||
protected $filename;
|
||||
|
||||
/**
|
||||
* Methods allowed to call via menuaction
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $public_functions = array(
|
||||
'download' => true,
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $filename=null if not starting with as slash relative to EGw files dir (this is strongly prefered for security reasons)
|
||||
*/
|
||||
public function __construct($filename=null)
|
||||
{
|
||||
$this->filenames =& egw_cache::getSession('phpgwapi', __CLASS__);
|
||||
|
||||
if ($filename)
|
||||
{
|
||||
$this->filename = $filename;
|
||||
|
||||
if (!$this->filenames || !in_array($filename,$this->filenames)) $this->filenames[] = $filename;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax callback to load next chunk of log-file
|
||||
*
|
||||
* @param string $filename
|
||||
* @param int $start=0 last position in log-file
|
||||
* @throws egw_exception_wrong_parameter
|
||||
*/
|
||||
public function ajax_chunk($filename,$start=0)
|
||||
{
|
||||
if (!in_array($filename,$this->filenames))
|
||||
{
|
||||
throw new egw_exception_wrong_parameter("Not allowed to view '$filename'!");
|
||||
}
|
||||
if ($filename[0] != '/') $filename = $GLOBALS['egw_info']['server']['files_dir'].'/'.$filename;
|
||||
|
||||
if (file_exists($filename))
|
||||
{
|
||||
$size = filesize($filename);
|
||||
if (!$start || $start < 0 || $start > $size || $size-$start > 4*self::MAX_CHUNK_SIZE)
|
||||
{
|
||||
$start = $size - 4*self::MAX_CHUNK_SIZE;
|
||||
if ($start < 0) $start = 0;
|
||||
}
|
||||
$size = egw_vfs::hsize($size);
|
||||
$content = file_get_contents($filename, false, null, $start, self::MAX_CHUNK_SIZE);
|
||||
$length = bytes($content);
|
||||
$writable = is_writable($filename) || is_writable(dirname($filename));
|
||||
}
|
||||
else
|
||||
{
|
||||
$start = $length = 0;
|
||||
$content = '';
|
||||
$writable = $size = false;
|
||||
}
|
||||
$response = egw_json_response::get();
|
||||
$response->data(array( // send all responses as data
|
||||
'size' => $size,
|
||||
'writable' => $writable,
|
||||
'next' => $start + $length,
|
||||
'length' => $length,
|
||||
'content' => $content,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax callback to delete log-file
|
||||
*
|
||||
* @param string $filename
|
||||
* @param boolean $truncate=false true: truncate file, false: delete file
|
||||
* @throws egw_exception_wrong_parameter
|
||||
*/
|
||||
public function ajax_delete($filename,$truncate=false)
|
||||
{
|
||||
if (!in_array($filename,$this->filenames))
|
||||
{
|
||||
throw new egw_exception_wrong_parameter("Not allowed to view '$filename'!");
|
||||
}
|
||||
if ($filename[0] != '/') $filename = $GLOBALS['egw_info']['server']['files_dir'].'/'.$filename;
|
||||
if ($truncate)
|
||||
{
|
||||
file_put_contents($filename, '');
|
||||
}
|
||||
else
|
||||
{
|
||||
unlink($filename);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return html & javascript for logviewer
|
||||
*
|
||||
* @param string $header=null default $this->filename
|
||||
* @return string
|
||||
* @throws egw_exception_wrong_parameter
|
||||
*/
|
||||
public function show($header=null)
|
||||
{
|
||||
if (!isset($this->filename))
|
||||
{
|
||||
throw new egw_exception_wrong_parameter("Must be instanciated with filename!");
|
||||
}
|
||||
if (is_null($header)) $header = $this->filename;
|
||||
|
||||
return '
|
||||
<p style="float: left; margin: 5px"><b>'.htmlspecialchars($header).'</b></p>
|
||||
<div style="float: right; margin: 2px; margin-right: 5px">
|
||||
'.html::form(
|
||||
html::input('clear_log',lang('Clear window'),'button','id="clear_log"')."\n".
|
||||
html::input('delete_log',lang('Delete file'),'button','id="purge_log"')."\n".
|
||||
html::input('empty_log',lang('Empty file'),'button','id="empty_log"')."\n".
|
||||
html::input('download_log',lang('Download'),'submit','id="download_log"'),
|
||||
'','/index.php',array(
|
||||
'menuaction' => 'phpgwapi.egw_tail.download',
|
||||
'filename' => $this->filename,
|
||||
)).'
|
||||
</div>
|
||||
<pre class="tail" id="log" data-filename="'.$this->filename.'" style="clear: both; width: 99.5%; border: 2px groove silver; margin-bottom: 0; overflow: auto;"></pre>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a file specified per GET parameter (must be in $this->filesnames!)
|
||||
*
|
||||
* @throws egw_exception_wrong_parameter
|
||||
*/
|
||||
public function download()
|
||||
{
|
||||
$filename = $_GET['filename'];
|
||||
if (!in_array($filename,$this->filenames))
|
||||
{
|
||||
throw new egw_exception_wrong_parameter("Not allowed to download '$filename'!");
|
||||
}
|
||||
html::content_header(basename($filename),'text/plain');
|
||||
if ($filename[0] != '/') $filename = $GLOBALS['egw_info']['server']['files_dir'].'/'.$filename;
|
||||
for($n=ob_get_level(); $n > 0; --$n) ob_end_clean(); // stop all output buffering, to NOT run into memory_limit
|
||||
readfile($filename);
|
||||
common::egw_exit();
|
||||
}
|
||||
}
|
||||
|
||||
// some testcode, if this file is called via it's URL (you need to uncomment and adapt filename!)
|
||||
/*if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE__)
|
||||
{
|
||||
$GLOBALS['egw_info'] = array(
|
||||
'flags' => array(
|
||||
'currentapp' => 'admin',
|
||||
'nonavbar' => true,
|
||||
),
|
||||
);
|
||||
include_once '../../header.inc.php';
|
||||
|
||||
$error_log = new egw_tail('/opt/local/apache2/logs/error_log');
|
||||
echo $error_log->show();
|
||||
}*/
|
||||
class egw_tail extends Tail {}
|
||||
|
@ -1127,6 +1127,10 @@ function ExecMethod($method, $functionparam = '_UNDEF_', $loglevel = 3, $classpa
|
||||
{
|
||||
$GLOBALS[$classname] = CreateObject($appname.'.'.$classname, $classparams);
|
||||
}
|
||||
elseif (class_exists($classname))
|
||||
{
|
||||
$GLOBALS[$classname] = new $classname;
|
||||
}
|
||||
else
|
||||
{
|
||||
$GLOBALS[$classname] = CreateObject($appname.'.'.$classname);
|
||||
|
@ -27,15 +27,15 @@ jQuery(function()
|
||||
{
|
||||
if (buttonId != "clear_log")
|
||||
{
|
||||
var ajax = new egw_json_request("home.egw_tail.ajax_delete",[filename,buttonId=="empty_log"]);
|
||||
ajax.sendRequest(true);
|
||||
egw.json("api.EGroupware\\Api\\Json\\Tail.ajax_delete",[filename,buttonId=="empty_log"])
|
||||
.sendRequest(true);
|
||||
}
|
||||
$j("#log").text("");
|
||||
}
|
||||
function refresh_log()
|
||||
{
|
||||
var ajax = new egw_json_request("home.egw_tail.ajax_chunk",[filename,log_tail_start]);
|
||||
ajax.sendRequest(true,function(_data) {
|
||||
egw.json("api.EGroupware\\Api\\Json\\Tail.ajax_chunk",[filename,log_tail_start], function(_data)
|
||||
{
|
||||
if (_data.length) {
|
||||
log_tail_start = _data.next;
|
||||
var log = $j("#log").append(_data.content.replace(/</g,"<"));
|
||||
@ -60,7 +60,7 @@ jQuery(function()
|
||||
$j("#empty_log").show();
|
||||
}
|
||||
window.setTimeout(refresh_log,_data.length?200:2000);
|
||||
});
|
||||
}).sendRequest(true);
|
||||
}
|
||||
function resize_log()
|
||||
{
|
||||
|
@ -70,7 +70,7 @@ $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';
|
||||
$setup_info['groupdav']['hooks']['preferences'] = 'EGroupware\\Api\\CalDAV\\Hooks::menus';
|
||||
$setup_info['groupdav']['hooks']['settings'] = 'EGroupware\\Api\\CalDAV\\Hooks::settings';
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user