diff --git a/dav/SabreDAV/ChangeLog b/dav/SabreDAV/ChangeLog index 8798f9b0e..1199ae766 100644 --- a/dav/SabreDAV/ChangeLog +++ b/dav/SabreDAV/ChangeLog @@ -54,6 +54,8 @@ the instance of an event, but not the end. * Fixed: All-day recurring events wouldn't match if an occurence ended exactly on the start of a time-range. + * Fixed: HTTP basic auth did not correctly deal with passwords containing + colons on some servers. 1.6.3-stable (2012-06-12) * Added: It's now possible to specify in Sabre_DAV_Client which type of diff --git a/dav/SabreDAV/bin/migrateto17.php b/dav/SabreDAV/bin/migrateto17.php index 95db938f8..89207877c 100644 --- a/dav/SabreDAV/bin/migrateto17.php +++ b/dav/SabreDAV/bin/migrateto17.php @@ -223,7 +223,7 @@ function getDenormalizedData($calendarData) { } } else { $it = new Sabre_VObject_RecurrenceIterator($vObject, (string)$component->UID); - $maxDate = new DateTime(self::MAX_DATE); + $maxDate = new DateTime(Sabre_CalDAV_Backend_PDO::MAX_DATE); if ($it->isInfinite()) { $lastOccurence = $maxDate->getTimeStamp(); } else { diff --git a/dav/SabreDAV/examples/sql/mysql.locks.sql b/dav/SabreDAV/examples/sql/mysql.locks.sql index 2fafac9cb..cf3caf4f7 100644 --- a/dav/SabreDAV/examples/sql/mysql.locks.sql +++ b/dav/SabreDAV/examples/sql/mysql.locks.sql @@ -6,5 +6,8 @@ CREATE TABLE locks ( token VARCHAR(100), scope TINYINT, depth TINYINT, - uri text + uri VARCHAR(1000), + INDEX(token), + INDEX(uri) ); + diff --git a/dav/SabreDAV/lib/Sabre/HTTP/BasicAuth.php b/dav/SabreDAV/lib/Sabre/HTTP/BasicAuth.php index a747cc6a3..f90ed24f5 100644 --- a/dav/SabreDAV/lib/Sabre/HTTP/BasicAuth.php +++ b/dav/SabreDAV/lib/Sabre/HTTP/BasicAuth.php @@ -46,7 +46,7 @@ class Sabre_HTTP_BasicAuth extends Sabre_HTTP_AbstractAuth { if (strpos(strtolower($auth),'basic')!==0) return false; - return explode(':', base64_decode(substr($auth, 6))); + return explode(':', base64_decode(substr($auth, 6)),2); } diff --git a/dav/SabreDAV/lib/Sabre/HTTP/Version.php b/dav/SabreDAV/lib/Sabre/HTTP/Version.php index 23dc7f8a7..e6b4f7e53 100644 --- a/dav/SabreDAV/lib/Sabre/HTTP/Version.php +++ b/dav/SabreDAV/lib/Sabre/HTTP/Version.php @@ -14,7 +14,7 @@ class Sabre_HTTP_Version { /** * Full version number */ - const VERSION = '1.6.2'; + const VERSION = '1.6.4'; /** * Stability : alpha, beta, stable diff --git a/dav/SabreDAV/lib/Sabre/VObject/Component.php b/dav/SabreDAV/lib/Sabre/VObject/Component.php index 6d4b28ac8..ced593848 100644 --- a/dav/SabreDAV/lib/Sabre/VObject/Component.php +++ b/dav/SabreDAV/lib/Sabre/VObject/Component.php @@ -104,7 +104,7 @@ class Sabre_VObject_Component extends Sabre_VObject_Element { * @return int */ $sortScore = function($key, $array) { - + if ($array[$key] instanceof Sabre_VObject_Component) { // We want to encode VTIMEZONE first, this is a personal // preference. @@ -264,6 +264,27 @@ class Sabre_VObject_Component extends Sabre_VObject_Element { } + /** + * Validates the node for correctness. + * An array is returned with warnings. + * + * Every item in the array has the following properties: + * * level - (number between 1 and 3 with severity information) + * * message - (human readable message) + * * node - (reference to the offending node) + * + * @return array + */ + public function validate() { + + $result = array(); + foreach($this->children as $child) { + $result = array_merge($result, $child->validate()); + } + return $result; + + } + /* Magic property accessors {{{ */ /** diff --git a/dav/SabreDAV/lib/Sabre/VObject/Component/VCalendar.php b/dav/SabreDAV/lib/Sabre/VObject/Component/VCalendar.php index f3be29afd..35dd90f23 100644 --- a/dav/SabreDAV/lib/Sabre/VObject/Component/VCalendar.php +++ b/dav/SabreDAV/lib/Sabre/VObject/Component/VCalendar.php @@ -129,5 +129,110 @@ class Sabre_VObject_Component_VCalendar extends Sabre_VObject_Component { } + /** + * Validates the node for correctness. + * An array is returned with warnings. + * + * Every item in the array has the following properties: + * * level - (number between 1 and 3 with severity information) + * * message - (human readable message) + * * node - (reference to the offending node) + * + * @return array + */ + public function validate() { + + $warnings = array(); + + $version = $this->select('VERSION'); + if (count($version)!==1) { + $warnings[] = array( + 'level' => 1, + 'message' => 'The VERSION property must appear in the VCALENDAR component exactly 1 time', + 'node' => $this, + ); + } else { + if ((string)$this->VERSION !== '2.0') { + $warnings[] = array( + 'level' => 1, + 'message' => 'Only iCalendar version 2.0 as defined in rfc5545 is supported.', + 'node' => $this, + ); + } + } + $version = $this->select('PRODID'); + if (count($version)!==1) { + $warnings[] = array( + 'level' => 2, + 'message' => 'The PRODID property must appear in the VCALENDAR component exactly 1 time', + 'node' => $this, + ); + } + if (count($this->CALSCALE) > 1) { + $warnings[] = array( + 'level' => 2, + 'message' => 'The CALSCALE property must not be specified more than once.', + 'node' => $this, + ); + } + if (count($this->METHOD) > 1) { + $warnings[] = array( + 'level' => 2, + 'message' => 'The METHOD property must not be specified more than once.', + 'node' => $this, + ); + } + + $allowedComponents = array( + 'VEVENT', + 'VTODO', + 'VJOURNAL', + 'VFREEBUSY', + 'VTIMEZONE', + ); + $allowedProperties = array( + 'PRODID', + 'VERSION', + 'CALSCALE', + 'METHOD', + ); + $componentsFound = 0; + foreach($this->children as $child) { + if($child instanceof Sabre_VObject_Component) { + $componentsFound++; + if (!in_array($child->name, $allowedComponents)) { + $warnings[] = array( + 'level' => 1, + 'message' => 'The ' . $child->name . " component is not allowed in the VCALENDAR component", + 'node' => $this, + ); + } + } + if ($child instanceof Sabre_VObject_Property) { + if (!in_array($child->name, $allowedProperties)) { + $warnings[] = array( + 'level' => 2, + 'message' => 'The ' . $child->name . " property is not allowed in the VCALENDAR component", + 'node' => $this, + ); + } + } + } + + if ($componentsFound===0) { + $warnings[] = array( + 'level' => 1, + 'message' => 'An iCalendar object must have at least 1 component.', + 'node' => $this, + ); + } + + return array_merge( + $warnings, + parent::validate() + ); + + } + } diff --git a/dav/SabreDAV/lib/Sabre/VObject/Node.php b/dav/SabreDAV/lib/Sabre/VObject/Node.php index 7701309be..6c8319f76 100644 --- a/dav/SabreDAV/lib/Sabre/VObject/Node.php +++ b/dav/SabreDAV/lib/Sabre/VObject/Node.php @@ -32,6 +32,23 @@ abstract class Sabre_VObject_Node implements IteratorAggregate, ArrayAccess, Cou */ public $parent = null; + /** + * Validates the node for correctness. + * An array is returned with warnings. + * + * Every item in the array has the following properties: + * * level - (number between 1 and 3 with severity information) + * * message - (human readable message) + * * node - (reference to the offending node) + * + * @return array + */ + public function validate() { + + return array(); + + } + /* {{{ IteratorAggregator interface */ /** diff --git a/dav/SabreDAV/tests/Sabre/HTTP/BasicAuthTest.php b/dav/SabreDAV/tests/Sabre/HTTP/BasicAuthTest.php index b5dd51445..1bebcf85e 100644 --- a/dav/SabreDAV/tests/Sabre/HTTP/BasicAuthTest.php +++ b/dav/SabreDAV/tests/Sabre/HTTP/BasicAuthTest.php @@ -60,6 +60,25 @@ class Sabre_HTTP_BasicAuthTest extends PHPUnit_Framework_TestCase { } + function testGetUserPassWithColon() { + + $server = array( + 'HTTP_AUTHORIZATION' => 'Basic ' . base64_encode('admin:1234:5678'), + ); + + $request = new Sabre_HTTP_Request($server); + $this->basicAuth->setHTTPRequest($request); + + $userPass = $this->basicAuth->getUserPass(); + + $this->assertEquals( + array('admin','1234:5678'), + $userPass, + 'We did not get the username and password we expected' + ); + + } + function testGetUserPassApacheEdgeCase() { $server = array( diff --git a/dav/common/calendar_rendering.fnk.php b/dav/common/calendar_rendering.fnk.php index e97de36b5..f82247957 100644 --- a/dav/common/calendar_rendering.fnk.php +++ b/dav/common/calendar_rendering.fnk.php @@ -73,6 +73,8 @@ function renderCalDavEntry_data(&$calendar, &$calendarobject) throw new Sabre_DAV_Exception_BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component'); } + $timezoneOffset = date("P"); // @TODO Get the actual timezone from the event + if ($componentType !== 'VEVENT') return; @@ -106,15 +108,15 @@ function renderCalDavEntry_data(&$calendar, &$calendarobject) $start = $it->getDtStart()->getTimestamp(); q("INSERT INTO %s%sjqcalendar (`calendar_id`, `calendarobject_id`, `Summary`, `StartTime`, `EndTime`, `IsEditable`, `IsAllDayEvent`, `IsRecurring`, `Color`) VALUES - (%d, %d, '%s', '%s', '%s', %d, %d, %d, '%s')", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, - IntVal($calendar["id"]), IntVal($calendarobject["id"]), dbesc($event["summary"]), date("Y-m-d H:i:s", $start), date("Y-m-d H:i:s", $last_end), - 1, $allday, $recurring, dbesc(substr($event["color"], 1)) + (%d, %d, '%s', CONVERT_TZ('%s', '$timezoneOffset', @@session.time_zone), CONVERT_TZ('%s', '$timezoneOffset', @@session.time_zone), %d, %d, %d, '%s')", + CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendar["id"]), IntVal($calendarobject["id"]), dbesc($event["summary"]), date("Y-m-d H:i:s", $start), + date("Y-m-d H:i:s", $last_end), 1, $allday, $recurring, dbesc(substr($event["color"], 1)) ); foreach ($alarms as $alarm) { $alarm = renderCalDavEntry_calcalarm($alarm, $component); $notified = ($alarm->getTimestamp() < time() ? 1 : 0); - q("INSERT INTO %s%snotifications (`calendar_id`, `calendarobject_id`, `alert_date`, `notified`) VALUES (%d, %d, '%s', %d)", + q("INSERT INTO %s%snotifications (`calendar_id`, `calendarobject_id`, `alert_date`, `notified`) VALUES (%d, %d, CONVERT_TZ('%s', '$timezoneOffset', @@session.time_zone), %d)", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendar["id"]), IntVal($calendarobject["id"]), $alarm->format("Y-m-d H:i:s"), $notified ); } diff --git a/dav/common/dav_caldav_backend_private.inc.php b/dav/common/dav_caldav_backend_private.inc.php index b3b32e336..86da0270e 100644 --- a/dav/common/dav_caldav_backend_private.inc.php +++ b/dav/common/dav_caldav_backend_private.inc.php @@ -113,11 +113,12 @@ class Sabre_CalDAV_Backend_Private extends Sabre_CalDAV_Backend_Common $calendar = Sabre_CalDAV_Backend_Common::loadCalendarById($calendarId); $von = wdcal_php2MySqlTime($sd); $bis = wdcal_php2MySqlTime($ed); + $timezoneOffset = date("P"); // @TODO Events, die früher angefangen haben, aber noch andauern - $evs = q("SELECT * FROM %s%sjqcalendar WHERE `calendar_id` = %d AND `starttime` between '%s' and '%s'", - CALDAV_SQL_DB, CALDAV_SQL_PREFIX, - IntVal($calendarId), dbesc($von), dbesc($bis)); + $evs = q("SELECT *, CONVERT_TZ(`StartTime`, @@session.time_zone, '$timezoneOffset') StartTime, CONVERT_TZ(`EndTime`, @@session.time_zone, '$timezoneOffset') EndTime + FROM %s%sjqcalendar WHERE `calendar_id` = %d AND `StartTime` between '%s' and '%s'", + CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId), dbesc($von), dbesc($bis)); $events = array(); foreach ($evs as $row) $events[] = $this->jqcal2wdcal($row, $calendar, $base_path . $row["calendar_id"] . "/"); diff --git a/dav/common/wdcal_edit.inc.php b/dav/common/wdcal_edit.inc.php index 5595369f6..261e78660 100644 --- a/dav/common/wdcal_edit.inc.php +++ b/dav/common/wdcal_edit.inc.php @@ -70,7 +70,7 @@ function wdcal_getEditPage_str(&$localization, $baseurl, $calendar_id, $uri) if ($triggerDuration->s > 0) { $unit = "second"; $value = $triggerDuration->s + $triggerDuration->i * 60 + $triggerDuration->h * 3600 + $triggerDuration->d * 3600 * 24; // @TODO support more than days? - } elseif ($triggerDuration->m) { + } elseif ($triggerDuration->i) { $unit = "minute"; $value = $triggerDuration->i + $triggerDuration->h * 60 + $triggerDuration->d * 60 * 24; } elseif ($triggerDuration->h) { @@ -143,7 +143,7 @@ function wdcal_getEditPage_str(&$localization, $baseurl, $calendar_id, $uri) $out .= "