use groupdav->log() for all permanent error-messages, to log the into request-log too, if both If-Match and If-Schdule-Tag-Match given use If-Match for organiser/owner and If-Schedule-Tag-Match for attendees/participants

This commit is contained in:
Ralf Becker 2012-02-21 20:04:45 +00:00
parent 77eaf8e7f1
commit 2bc821f428
6 changed files with 70 additions and 31 deletions

View File

@ -17,6 +17,9 @@
* Propfind now uses a groupdav_propfind_iterator with a callback to query huge addressbooks in chunk, * Propfind now uses a groupdav_propfind_iterator with a callback to query huge addressbooks in chunk,
* without getting into problems with memory_limit. * 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()
* and our request-log (prefixed with "### " after request and response, like exceptions).
*
* @todo check/fix contacts in LDAP (no carddav_name column!) * @todo check/fix contacts in LDAP (no carddav_name column!)
*/ */
class addressbook_groupdav extends groupdav_handler class addressbook_groupdav extends groupdav_handler
@ -281,7 +284,7 @@ class addressbook_groupdav extends groupdav_handler
switch((string)$filter['name']) switch((string)$filter['name'])
{ {
case 'param-filter': case 'param-filter':
error_log(__METHOD__."(...) param-filter='{$filter['attrs']['name']}' not (yet) implemented!"); $this->groupdav->log(__METHOD__."(...) param-filter='{$filter['attrs']['name']}' not (yet) implemented!");
break; break;
case 'prop-filter': // can be multiple prop-filter, see example case 'prop-filter': // can be multiple prop-filter, see example
if ($matches) $prop_filters[] = implode($prop_test=='allof'?' AND ':' OR ',$matches); if ($matches) $prop_filters[] = implode($prop_test=='allof'?' AND ':' OR ',$matches);
@ -346,7 +349,7 @@ class addressbook_groupdav extends groupdav_handler
} }
// fall through // fall through
default: default:
error_log(__METHOD__."(".array2string($options).",,$id) unknown filter=".array2string($filter).' --> ignored'); $this->groupdav->log(__METHOD__."(".array2string($options).",,$id) unknown filter=".array2string($filter).' --> ignored');
break; break;
} }
} }
@ -376,7 +379,7 @@ class addressbook_groupdav extends groupdav_handler
case 'href': case 'href':
break; // from addressbook-multiget, handled below break; // from addressbook-multiget, handled below
default: default:
error_log(__METHOD__."(...) unknown xml: options[other]=".array2string($options['other'])); $this->groupdav->log(__METHOD__."(...) unknown xml: options[other]=".array2string($options['other']));
break; break;
} }
} }

View File

@ -14,7 +14,10 @@
require_once EGW_SERVER_ROOT.'/phpgwapi/inc/horde/lib/core.php'; require_once EGW_SERVER_ROOT.'/phpgwapi/inc/horde/lib/core.php';
/** /**
* eGroupWare: GroupDAV access: calendar handler * EGroupware: CalDAV / GroupDAV access: calendar handler
*
* Permanent error_log() calls should use $this->groupdav->log($str) instead, to be send to PHP error_log()
* and our request-log (prefixed with "### " after request and response, like exceptions).
*/ */
class calendar_groupdav extends groupdav_handler class calendar_groupdav extends groupdav_handler
{ {
@ -597,6 +600,20 @@ class calendar_groupdav extends groupdav_handler
{ {
$eventId = $oldEvent['id']; $eventId = $oldEvent['id'];
//client specified a CalDAV Scheduling schedule-tag AND an etag If-Match precondition
if ($this->use_schedule_tag && isset($_SERVER['HTTP_IF_SCHEDULE_TAG_MATCH']) &&
isset($_SERVER['HTTP_IF_MATCH']))
{
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!");
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!");
}
}
//client specified a CalDAV Scheduling schedule-tag precondition //client specified a CalDAV Scheduling schedule-tag precondition
if ($this->use_schedule_tag && isset($_SERVER['HTTP_IF_SCHEDULE_TAG_MATCH'])) if ($this->use_schedule_tag && isset($_SERVER['HTTP_IF_SCHEDULE_TAG_MATCH']))
{ {
@ -638,7 +655,7 @@ class calendar_groupdav extends groupdav_handler
} }
elseif (!isset($event['participants']) || $event['participants'][$user] === $oldEvent['participants'][$user]) elseif (!isset($event['participants']) || $event['participants'][$user] === $oldEvent['participants'][$user])
{ {
error_log(__METHOD__."(,,$user) schedule-tag given, but NO change for current user event=".array2string($event).', old-event='.array2string($oldEvent)); $this->groupdav->log(__METHOD__."(,,$user) schedule-tag given, but NO change for current user event=".array2string($event).', old-event='.array2string($oldEvent));
return '412 Precondition Failed'; return '412 Precondition Failed';
} }
} }
@ -858,7 +875,7 @@ class calendar_groupdav extends groupdav_handler
} }
if ($event['owner'] != $user) if ($event['owner'] != $user)
{ {
error_log(__METHOD__."('$ical',,$user) ORGANIZER is NOT principal!"); $this->groupdav->log(__METHOD__."('$ical',,$user) ORGANIZER is NOT principal!");
return '403 Forbidden'; return '403 Forbidden';
} }
//print_r($event); //print_r($event);

View File

@ -15,6 +15,9 @@ require_once EGW_SERVER_ROOT.'/phpgwapi/inc/horde/lib/core.php';
/** /**
* EGroupware: GroupDAV access: infolog handler * EGroupware: GroupDAV access: infolog handler
*
* Permanent error_log() calls should use $this->groupdav->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 groupdav_handler
{ {
@ -367,7 +370,7 @@ class infolog_groupdav extends groupdav_handler
} }
elseif (empty($attrs['start'])) elseif (empty($attrs['start']))
{ {
error_log(__METHOD__.'('.array2string($attrs).') minimum one of start or end is required!'); $this->groupdav->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 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 // we dont need to care for DURATION line in rfc4791#section-9.9, as we always put that in DUE/info_enddate

View File

@ -39,6 +39,9 @@ require_once('HTTP/WebDAV/Server.php');
* Calling one of the above collections with a GET request / regular browser generates an automatic index * Calling one of the above collections with a GET request / regular browser generates an automatic index
* from the data of a allprop PROPFIND, allow to browse CalDAV/CardDAV/GroupDAV tree with a regular browser. * from the data of a allprop PROPFIND, allow to browse CalDAV/CardDAV/GroupDAV tree with a regular browser.
* *
* Permanent error_log() calls should use groupdav->log($str) instead, to be send to PHP error_log()
* and our request-log (prefixed with "### " after request and response, like exceptions).
*
* @link http://www.groupdav.org/ GroupDAV spec * @link http://www.groupdav.org/ GroupDAV spec
* @link http://caldav.calconnect.org/ CalDAV resources * @link http://caldav.calconnect.org/ CalDAV resources
* @link http://carddav.calconnect.org/ CardDAV resources * @link http://carddav.calconnect.org/ CardDAV resources
@ -393,7 +396,7 @@ class groupdav extends HTTP_WebDAV_Server
// Hack for iOS 5.0.1 addressbook to stop asking directory gateway permissions with depth=1 // Hack for iOS 5.0.1 addressbook to stop asking directory gateway permissions with depth=1
if ($method == 'PROPFIND' && $options['path'] == '/addressbook/' && $handler->get_agent() == 'dataaccess') if ($method == 'PROPFIND' && $options['path'] == '/addressbook/' && $handler->get_agent() == 'dataaccess')
{ {
error_log(__CLASS__."::$method(".array2string($options).') Enabling hack for iOS 5.0.1 addressbook: force Depth: 0 on PROPFIND for directory gateway!'); $this->log(__CLASS__."::$method(".array2string($options).') Enabling hack for iOS 5.0.1 addressbook: force Depth: 0 on PROPFIND for directory gateway!');
return true; return true;
} }
if (!$options['depth']) return true; // depth 0 --> show only the self url if (!$options['depth']) return true; // depth 0 --> show only the self url
@ -901,9 +904,6 @@ class groupdav extends HTTP_WebDAV_Server
if (!$this->_parse_path($options['path'],$id,$app,$user) || $app == 'principals') if (!$this->_parse_path($options['path'],$id,$app,$user) || $app == 'principals')
{ {
return $this->autoindex($options); return $this->autoindex($options);
error_log(__METHOD__."(".array2string($options).") 404 Not Found");
return '404 Not Found';
} }
if (($handler = self::app_handler($app))) if (($handler = self::app_handler($app)))
{ {
@ -1553,19 +1553,9 @@ class groupdav extends HTTP_WebDAV_Server
if ($debug_level !== 'f' && strlen($c) > 1536) $c = substr($c,0,1536)."\n*** LOG TRUNKATED\n"; if ($debug_level !== 'f' && strlen($c) > 1536) $c = substr($c,0,1536)."\n*** LOG TRUNKATED\n";
$content .= $c; $content .= $c;
if ($extra) $content .= $extra; if ($extra) $content .= $extra;
if ($this->to_log) $content .= "\n### ".implode("\n### ", $this->to_log)."\n";
$content .= sprintf('*** %s --> "%s" took %5.3f s',$_SERVER['REQUEST_METHOD'].($_SERVER['REQUEST_METHOD']=='REPORT'?' '.$this->propfind_options['root']['name']:'').' '.$_SERVER['PATH_INFO'],$this->_http_status,microtime(true)-self::$request_starttime)."\n\n"; $content .= sprintf('*** %s --> "%s" took %5.3f s',$_SERVER['REQUEST_METHOD'].($_SERVER['REQUEST_METHOD']=='REPORT'?' '.$this->propfind_options['root']['name']:'').' '.$_SERVER['PATH_INFO'],$this->_http_status,microtime(true)-self::$request_starttime)."\n\n";
self::log($content,$msg_file);
}
}
/**
* Log to a given file or error_log
*
* @param string $content
* @param string $msg_file=null
*/
private static function log($content,$msg_file=null)
{
if ($msg_file && ($f = fopen($msg_file,'a'))) if ($msg_file && ($f = fopen($msg_file,'a')))
{ {
flock($f,LOCK_EX); flock($f,LOCK_EX);
@ -1578,6 +1568,26 @@ class groupdav extends HTTP_WebDAV_Server
foreach($explode("\n",$content) as $line) error_log($line); foreach($explode("\n",$content) as $line) error_log($line);
} }
} }
}
/**
* Content of log() calls, to be appended to request_log
*
* @var array
*/
private $to_log = array();
/**
* Log unconditional to own request- and PHP error-log
*
* @param string $str
*/
public function log($str)
{
$to_log[] = $str;
error_log($str);
}
/** /**
* Exception handler, which additionally logs the request (incl. a trace) * Exception handler, which additionally logs the request (incl. a trace)

View File

@ -13,6 +13,9 @@
/** /**
* EGroupware: GroupDAV access: abstract baseclass for groupdav/caldav/carddav handlers * 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()
* and our request-log (prefixed with "### " after request and response, like exceptions).
*/ */
abstract class groupdav_handler abstract class groupdav_handler
{ {

View File

@ -18,6 +18,9 @@
* to allow to check if required properties are set! * to allow to check if required properties are set!
* groupdav_principals::add_principal() converts simple associative props (name => value pairs) * groupdav_principals::add_principal() converts simple associative props (name => value pairs)
* to name => HTTP_WebDAV_Server(name, value) pairs. * to name => HTTP_WebDAV_Server(name, value) pairs.
*
* Permanent error_log() calls should use $this->groupdav->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 groupdav_principals extends groupdav_handler
{ {
@ -111,7 +114,7 @@ class groupdav_principals extends groupdav_handler
{ {
return $this->$method($path, $options, $files, $user); return $this->$method($path, $options, $files, $user);
} }
error_log(__METHOD__."('$path', ".array2string($options).",, $user) not implemented report, returning 501 Not Implemented"); $this->groupdav->log(__METHOD__."('$path', ".array2string($options).",, $user) not implemented report, returning 501 Not Implemented");
return '501 Not Implemented'; return '501 Not Implemented';
} }
list(,$principals,$type,$name,$rest) = explode('/',$path,5); list(,$principals,$type,$name,$rest) = explode('/',$path,5);
@ -290,7 +293,7 @@ class groupdav_principals extends groupdav_handler
} }
if (!isset($property_search) || !$search_props || !isset($search_props[$property_search]['match'])) if (!isset($property_search) || !$search_props || !isset($search_props[$property_search]['match']))
{ {
error_log(__METHOD__."('$path',...) Could not parse options[other]=".array2string($options['other'])); $this->groupdav->log(__METHOD__."('$path',...) Could not parse options[other]=".array2string($options['other']));
return '400 Bad Request'; return '400 Bad Request';
} }
// make sure search property is included in toplevel props (can be missing and defaults to property-search/prop's) // make sure search property is included in toplevel props (can be missing and defaults to property-search/prop's)
@ -310,7 +313,7 @@ class groupdav_principals extends groupdav_handler
substr($search_props[0]['match'],-13) == '/groupdav.php') substr($search_props[0]['match'],-13) == '/groupdav.php')
{ {
$path = '/principals/users/'.$GLOBALS['egw_info']['user']['account_lid'].'/'; $path = '/principals/users/'.$GLOBALS['egw_info']['user']['account_lid'].'/';
error_log('Enabling hack for Lightning prior 1.1.1 for searching calendar-home-set matching "/groupdav.php": limiting search to '.$path); $this->groupdav->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 // check type attribute to limit search on a certain tree
@ -894,7 +897,7 @@ class groupdav_principals extends groupdav_handler
break; break;
default: default:
error_log(__METHOD__."('$url') unsupported principal URL '$url'!"); $this->groupdav->log(__METHOD__."('$url') unsupported principal URL '$url'!");
return false; return false;
} }
return $uid && in_array($type, $only_type) ? $uid : false; return $uid && in_array($type, $only_type) ? $uid : false;