From 66384e2e2c8160479253b28deb1b77e838317f95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20H=C3=B6=C3=9Fl?= Date: Sat, 14 Jul 2012 17:02:21 +0000 Subject: [PATCH] Exporting and Importing ICS-Files --- dav/SabreDAV/ChangeLog | 9 ++ dav/SabreDAV/lib/Sabre/CalDAV/Backend/PDO.php | 7 +- dav/SabreDAV/lib/Sabre/CardDAV/Plugin.php | 3 +- dav/SabreDAV/lib/Sabre/DAV/Property.php | 2 - .../lib/Sabre/VObject/RecurrenceIterator.php | 40 +++++- dav/SabreDAV/lib/Sabre/VObject/Version.php | 2 +- .../CalDAV/CalendarQueryValidatorTest.php | 23 +++- .../Sabre/VObject/Component/VEventTest.php | 9 +- .../Sabre/VObject/RecurrenceIteratorTest.php | 45 +++++++ dav/calendar.friendica.fnk.php | 7 +- dav/common/calendar.fnk.php | 11 +- dav/common/dav_caldav_backend_common.inc.php | 1 + dav/common/dav_caldav_backend_private.inc.php | 1 - dav/common/wdcal_edit.inc.php | 2 +- dav/layout.fnk.php | 120 +++++++++++++++--- dav/main.php | 10 +- 16 files changed, 245 insertions(+), 47 deletions(-) diff --git a/dav/SabreDAV/ChangeLog b/dav/SabreDAV/ChangeLog index adafd9c9..0fe7758f 100644 --- a/dav/SabreDAV/ChangeLog +++ b/dav/SabreDAV/ChangeLog @@ -31,6 +31,8 @@ * Fixed: Uploaded VCards without a UID are now rejected. (thanks Dominik!) * Fixed: Rejecting calendar objects if they are not in the supported-calendar-component list. (thanks Armin!) + * Fixed: Workaround for 10.8 Mountain Lion vCards, as it needs \r line + endings to parse them correctly. 1.6.4-stable (2012-??-??) * Fixed: Issue 220: Calendar-query filters may fail when filtering on @@ -40,6 +42,13 @@ requests. * Fixed: Problem with POST requests to the outbox if mailto: was not lower cased. + * Fixed: Yearly recurrence rule expansion on leap-days no behaves + correctly. + * Fixed: Correctly checking if recurring, all-day events with no dtstart + fall in a timerange if the start of the time-range exceeds the start of + 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. 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/lib/Sabre/CalDAV/Backend/PDO.php b/dav/SabreDAV/lib/Sabre/CalDAV/Backend/PDO.php index aafea1c5..105ebd33 100644 --- a/dav/SabreDAV/lib/Sabre/CalDAV/Backend/PDO.php +++ b/dav/SabreDAV/lib/Sabre/CalDAV/Backend/PDO.php @@ -16,8 +16,13 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { /** * We need to specify a max date, because we need to stop *somewhere* + * + * On 32 bit system the maximum for a signed integer is 2147483647, so + * MAX_DATE cannot be higher than date('Y-m-d', 2147483647) which results + * in 2038-01-19 to avoid problems when the date is converted + * to a unix timestamp. */ - const MAX_DATE = '2040-01-01'; + const MAX_DATE = '2038-01-01'; /** * pdo diff --git a/dav/SabreDAV/lib/Sabre/CardDAV/Plugin.php b/dav/SabreDAV/lib/Sabre/CardDAV/Plugin.php index e1d70e92..c31d0b1b 100644 --- a/dav/SabreDAV/lib/Sabre/CardDAV/Plugin.php +++ b/dav/SabreDAV/lib/Sabre/CardDAV/Plugin.php @@ -154,8 +154,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { if (is_resource($val)) $val = stream_get_contents($val); - // Taking out \r to not screw up the xml output - $returnedProperties[200][$addressDataProp] = str_replace("\r","", $val); + $returnedProperties[200][$addressDataProp] = $val; } } diff --git a/dav/SabreDAV/lib/Sabre/DAV/Property.php b/dav/SabreDAV/lib/Sabre/DAV/Property.php index db4fef51..26f2c1d0 100644 --- a/dav/SabreDAV/lib/Sabre/DAV/Property.php +++ b/dav/SabreDAV/lib/Sabre/DAV/Property.php @@ -13,8 +13,6 @@ */ abstract class Sabre_DAV_Property implements Sabre_DAV_PropertyInterface { - abstract function serialize(Sabre_DAV_Server $server, DOMElement $prop); - static function unserialize(DOMElement $prop) { throw new Sabre_DAV_Exception('Unserialize has not been implemented for this class'); diff --git a/dav/SabreDAV/lib/Sabre/VObject/RecurrenceIterator.php b/dav/SabreDAV/lib/Sabre/VObject/RecurrenceIterator.php index 39d1b699..7ccd2049 100644 --- a/dav/SabreDAV/lib/Sabre/VObject/RecurrenceIterator.php +++ b/dav/SabreDAV/lib/Sabre/VObject/RecurrenceIterator.php @@ -337,6 +337,8 @@ class Sabre_VObject_RecurrenceIterator implements Iterator { $this->endDate = clone $this->startDate; if (isset($this->baseEvent->DURATION)) { $this->endDate->add(Sabre_VObject_DateTimeParser::parse($this->baseEvent->DURATION->value)); + } elseif ($this->baseEvent->DTSTART->getDateType()===Sabre_VObject_Property_DateTime::DATE) { + $this->endDate->modify('+1 day'); } } $this->currentDate = clone $this->startDate; @@ -565,7 +567,7 @@ class Sabre_VObject_RecurrenceIterator implements Iterator { */ public function fastForward(DateTime $dt) { - while($this->valid() && $this->getDTEnd() < $dt) { + while($this->valid() && $this->getDTEnd() <= $dt) { $this->next(); } @@ -838,9 +840,40 @@ class Sabre_VObject_RecurrenceIterator implements Iterator { */ protected function nextYearly() { + $currentMonth = $this->currentDate->format('n'); + $currentYear = $this->currentDate->format('Y'); + $currentDayOfMonth = $this->currentDate->format('j'); + + // No sub-rules, so we just advance by year if (!$this->byMonth) { + + // Unless it was a leap day! + if ($currentMonth==2 && $currentDayOfMonth==29) { + + $counter = 0; + do { + $counter++; + // Here we increase the year count by the interval, until + // we hit a date that's also in a leap year. + // + // We could just find the next interval that's dividable by + // 4, but that would ignore the rule that there's no leap + // year every year that's dividable by a 100, but not by + // 400. (1800, 1900, 2100). So we just rely on the datetime + // functions instead. + $nextDate = clone $this->currentDate; + $nextDate->modify('+ ' . ($this->interval*$counter) . ' years'); + } while ($nextDate->format('n')!=2); + $this->currentDate = $nextDate; + + return; + + } + + // The easiest form $this->currentDate->modify('+' . $this->interval . ' years'); return; + } $currentMonth = $this->currentDate->format('n'); @@ -892,8 +925,8 @@ class Sabre_VObject_RecurrenceIterator implements Iterator { } else { - // no byDay or byMonthDay, so we can just loop through the - // months. + // These are the 'byMonth' rules, if there are no byDay or + // byMonthDay sub-rules. do { $currentMonth++; @@ -903,6 +936,7 @@ class Sabre_VObject_RecurrenceIterator implements Iterator { } } while (!in_array($currentMonth, $this->byMonth)); $this->currentDate->setDate($currentYear, $currentMonth, $currentDayOfMonth); + return; } diff --git a/dav/SabreDAV/lib/Sabre/VObject/Version.php b/dav/SabreDAV/lib/Sabre/VObject/Version.php index 2617c7b1..9ee03d87 100644 --- a/dav/SabreDAV/lib/Sabre/VObject/Version.php +++ b/dav/SabreDAV/lib/Sabre/VObject/Version.php @@ -14,7 +14,7 @@ class Sabre_VObject_Version { /** * Full version number */ - const VERSION = '1.3.3'; + const VERSION = '1.3.4'; /** * Stability : alpha, beta, stable diff --git a/dav/SabreDAV/tests/Sabre/CalDAV/CalendarQueryValidatorTest.php b/dav/SabreDAV/tests/Sabre/CalDAV/CalendarQueryValidatorTest.php index b75c398a..18c8330d 100644 --- a/dav/SabreDAV/tests/Sabre/CalDAV/CalendarQueryValidatorTest.php +++ b/dav/SabreDAV/tests/Sabre/CalDAV/CalendarQueryValidatorTest.php @@ -343,6 +343,14 @@ DURATION:PT1H RRULE:FREQ=YEARLY END:VEVENT END:VCALENDAR +yow; + $blob33 = << null, ); - // Time-range with RRULE - + $filter38 = array( + 'name' => 'VEVENT', + 'comp-filters' => array(), + 'prop-filters' => array(), + 'is-not-defined' => false, + 'time-range' => array( + 'start' => new DateTime('2012-07-01 00:00:00', new DateTimeZone('UTC')), + 'end' => new DateTime('2012-08-01 00:00:00', new DateTimeZone('UTC')), + ) + ); return array( // Component check @@ -741,6 +757,9 @@ yow; array($blob31, $filter20, 1), array($blob32, $filter20, 0), + // Bug reported on mailing list, related to all-day events. + array($blob33, $filter38, 1), + ); } diff --git a/dav/SabreDAV/tests/Sabre/VObject/Component/VEventTest.php b/dav/SabreDAV/tests/Sabre/VObject/Component/VEventTest.php index a5a855f6..90579cb4 100644 --- a/dav/SabreDAV/tests/Sabre/VObject/Component/VEventTest.php +++ b/dav/SabreDAV/tests/Sabre/VObject/Component/VEventTest.php @@ -53,9 +53,14 @@ class Sabre_VObject_Component_VEventTest extends PHPUnit_Framework_TestCase { $vevent6->DTEND['VALUE'] = 'DATE'; $tests[] = array($vevent6, new DateTime('2011-01-01'), new DateTime('2012-01-01'), true); $tests[] = array($vevent6, new DateTime('2011-01-01'), new DateTime('2011-11-01'), false); - // Event with no end date should be treated as lasting the entire day. - $tests[] = array($vevent6, new DateTime('2011-12-25 16:00:00'), new DateTime('2011-12-25 17:00:00'), true); + // Added this test to ensure that recurrence rules with no DTEND also + // get checked for the entire day. + $vevent7 = clone $vevent; + $vevent7->DTSTART = '20120101'; + $vevent7->DTSTART['VALUE'] = 'DATE'; + $vevent7->RRULE = 'FREQ=MONTHLY'; + $tests[] = array($vevent7, new DateTime('2012-02-01 15:00:00'), new DateTime('2012-02-02'), true); return $tests; } diff --git a/dav/SabreDAV/tests/Sabre/VObject/RecurrenceIteratorTest.php b/dav/SabreDAV/tests/Sabre/VObject/RecurrenceIteratorTest.php index d1ef2da6..0bb42bb8 100644 --- a/dav/SabreDAV/tests/Sabre/VObject/RecurrenceIteratorTest.php +++ b/dav/SabreDAV/tests/Sabre/VObject/RecurrenceIteratorTest.php @@ -707,6 +707,51 @@ class Sabre_VObject_RecurrenceIteratorTest extends PHPUnit_Framework_TestCase { } + /** + * @depends testValues + */ + function testYearlyLeapYear() { + + $ev = new Sabre_VObject_Component('VEVENT'); + $ev->UID = 'bla'; + $ev->RRULE = 'FREQ=YEARLY;COUNT=3'; + $dtStart = new Sabre_VObject_Property_DateTime('DTSTART'); + $dtStart->setDateTime(new DateTime('2012-02-29'),Sabre_VObject_Property_DateTime::UTC); + + $ev->add($dtStart); + + $vcal = Sabre_VObject_Component::create('VCALENDAR'); + $vcal->add($ev); + + $it = new Sabre_VObject_RecurrenceIterator($vcal,(string)$ev->uid); + + $this->assertEquals('yearly', $it->frequency); + $this->assertEquals(3, $it->count); + + $max = 20; + $result = array(); + foreach($it as $k=>$item) { + + $result[] = $item; + $max--; + + if (!$max) break; + + } + + $tz = new DateTimeZone('UTC'); + + $this->assertEquals( + array( + new DateTime('2012-02-29', $tz), + new DateTime('2016-02-29', $tz), + new DateTime('2020-02-29', $tz), + ), + $result + ); + + } + /** * @depends testValues */ diff --git a/dav/calendar.friendica.fnk.php b/dav/calendar.friendica.fnk.php index 2783339f..b1b0b3b3 100644 --- a/dav/calendar.friendica.fnk.php +++ b/dav/calendar.friendica.fnk.php @@ -186,19 +186,22 @@ function wdcal_create_std_calendars() $a = get_app(); if (!local_user()) return; + $privates = q("SELECT COUNT(*) num FROM %s%scalendars WHERE `namespace` = %d AND `namespace_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CALDAV_NAMESPACE_PRIVATE, IntVal($a->user["uid"])); + if ($privates[0]["num"] > 0) return; + $uris = array( 'private' => t("Private Calendar"), CALDAV_FRIENDICA_MINE => t("Friendica Events: Mine"), CALDAV_FRIENDICA_CONTACTS => t("Friendica Events: Contacts"), ); foreach ($uris as $uri => $name) { - $cals = q("SELECT * FROM %s%scalendars WHERE `namespace` = %d AND `namespace_id` = %d AND `uri` = '%s'", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CALDAV_NAMESPACE_PRIVATE, $a->user["uid"], dbesc($uri)); if (count($cals) == 0) { - q("INSERT INTO %s%scalendars (`namespace`, `namespace_id`, `displayname`, `timezone`, `ctag`, `uri`, `has_vevent`, `has_vtodo`) VALUES (%d, %d, %d, '%s', '%s', 1, '%s', 1, 0)", + q("INSERT INTO %s%scalendars (`namespace`, `namespace_id`, `displayname`, `timezone`, `ctag`, `uri`, `has_vevent`, `has_vtodo`) VALUES (%d, %d, '%s', '%s', 1, '%s', 1, 0)", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CALDAV_NAMESPACE_PRIVATE, IntVal($a->user["uid"]), dbesc($name), dbesc($a->timezone), dbesc($uri) ); } } + } diff --git a/dav/common/calendar.fnk.php b/dav/common/calendar.fnk.php index 27f51621..22f1d18c 100644 --- a/dav/common/calendar.fnk.php +++ b/dav/common/calendar.fnk.php @@ -185,12 +185,7 @@ function wdcal_mySql2icalTime($myqlDate) */ function icalendar_sanitize_string($str = "") { - $str = str_replace("\r\n", "\n", $str); - $str = str_replace("\n\r", "\n", $str); - $str = str_replace("\r", "\n", $str); - $str = str_replace("\n\n", "\n", $str); - $str = str_replace("\n\n", "\n", $str); - return $str; + return preg_replace("/[\\r\\n]+/siu", "\r\n", $str); } @@ -361,10 +356,8 @@ function dav_create_empty_vevent($uid = "") } - - /** - * @param Sabre_VObject_Component_VEvent $vObject + * @param Sabre_VObject_Component_VCalendar $vObject * @return Sabre_VObject_Component_VEvent|null */ function dav_get_eventComponent(&$vObject) diff --git a/dav/common/dav_caldav_backend_common.inc.php b/dav/common/dav_caldav_backend_common.inc.php index 2381e713..99fcb6c1 100644 --- a/dav/common/dav_caldav_backend_common.inc.php +++ b/dav/common/dav_caldav_backend_common.inc.php @@ -130,6 +130,7 @@ abstract class Sabre_CalDAV_Backend_Common extends Sabre_CalDAV_Backend_Abstract $component = null; $firstOccurence = null; $lastOccurence = null; + foreach ($vObject->getComponents() as $component) { if ($component->name !== 'VTIMEZONE') { $componentType = $component->name; diff --git a/dav/common/dav_caldav_backend_private.inc.php b/dav/common/dav_caldav_backend_private.inc.php index d258b6ca..b3b32e33 100644 --- a/dav/common/dav_caldav_backend_private.inc.php +++ b/dav/common/dav_caldav_backend_private.inc.php @@ -431,7 +431,6 @@ class Sabre_CalDAV_Backend_Private extends Sabre_CalDAV_Backend_Common */ function createCalendarObject($calendarId, $objectUri, $calendarData) { - $calendarData = icalendar_sanitize_string($calendarData); $extraData = $this->getDenormalizedData($calendarData); diff --git a/dav/common/wdcal_edit.inc.php b/dav/common/wdcal_edit.inc.php index b3f8889b..c652d974 100644 --- a/dav/common/wdcal_edit.inc.php +++ b/dav/common/wdcal_edit.inc.php @@ -325,7 +325,7 @@ function wdcal_getEditPage_str(&$localization, $baseurl, $uid, $calendar_id, $ur $out .= "\n"; if ($recurrence->frequency == "yearly") { - if ($recurrence->byMonth != IntVal(date("m", $event["StartTime"]))) notice("The recurrence of this event cannot be parsed"); + if (count($recurrence->byMonth) != 1 || $recurrence->byMonth[0] != date("n", $event["StartTime"])) notice("The recurrence of this event cannot be parsed!"); } $out .= "
"; diff --git a/dav/layout.fnk.php b/dav/layout.fnk.php index 7eb3e4f0..6f59d745 100644 --- a/dav/layout.fnk.php +++ b/dav/layout.fnk.php @@ -39,26 +39,19 @@ function wdcal_addRequiredHeaders() /** - * @param array|int[] $calendars + * @param int $calendar_id */ -function wdcal_print_user_ics($calendars = array()) +function wdcal_print_user_ics($calendar_id) { - $add = ""; - if (count($calendars) > 0) { - $c = array(); - foreach ($calendars as $i) $c[] = IntVal($i); - $add = " AND `id` IN (" . implode(", ", $c) . ")"; - } + $calendar_id = IntVal($calendar_id); $a = get_app(); header("Content-type: text/plain"); $str = "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Friendica//DAV-Plugin//EN\r\n"; - $cals = q("SELECT * FROM %s%scalendars WHERE `namespace` = %d AND `namespace_id` = %d %s", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CALDAV_NAMESPACE_PRIVATE, $a->user["uid"], $add); + $cals = q("SELECT * FROM %s%scalendars WHERE `id` = %d AND `namespace` = %d AND `namespace_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calendar_id, CALDAV_NAMESPACE_PRIVATE, $a->user["uid"]); if (count($cals) > 0) { - $ids = array(); - foreach ($cals as $c) $ids[] = IntVal($c["id"]); - $objs = q("SELECT * FROM %s%scalendarobjects WHERE `calendar_id` IN (" . implode(", ", $ids) . ") ORDER BY `firstOccurence`", CALDAV_SQL_DB, CALDAV_SQL_PREFIX); + $objs = q("SELECT * FROM %s%scalendarobjects WHERE `calendar_id` = %d ORDER BY `firstOccurence`", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calendar_id); foreach ($objs as $obj) { preg_match("/BEGIN:VEVENT(.*)END:VEVENT/siu", $obj["calendardata"], $matches); @@ -74,6 +67,95 @@ function wdcal_print_user_ics($calendars = array()) } +/** + * @param int $calendar_id + * @return string + */ +function wdcal_import_user_ics($calendar_id) { + $a = get_app(); + $calendar_id = IntVal($calendar_id); + $o = ""; + + $server = dav_create_server(true, true, false); + $calendar = dav_get_current_user_calendar_by_id($server, $calendar_id, DAV_ACL_WRITE); + if (!$calendar) goaway($a->get_baseurl() . "/dav/wdcal/"); + + if (isset($_REQUEST["save"])) { + check_form_security_token_redirectOnErr('/dav/settings/', 'icsimport'); + + if ($_FILES["ics_file"]["tmp_name"] != "" && is_uploaded_file($_FILES["ics_file"]["tmp_name"])) try { + $text = file_get_contents($_FILES["ics_file"]["tmp_name"]); + + /** @var Sabre_VObject_Component_VCalendar $vObject */ + $vObject = Sabre_VObject_Reader::read($text); + $comp = $vObject->getComponents(); + $imported = array(); + foreach ($comp as $c) try { + /** @var Sabre_VObject_Component_VEvent $c */ + $uid = $c->__get("UID")->value; + if (!isset($imported[$uid])) $imported[$uid] = ""; + $imported[$uid] .= $c->serialize(); + } catch (Exception $e) { + notice(t("Something went wrong when trying to import the file. Sorry. Maybe some events were imported anyway.")); + } + + if (isset($_REQUEST["overwrite"])) { + $children = $calendar->getChildren(); + foreach ($children as $child) { + /** @var Sabre_CalDAV_CalendarObject $child */ + $child->delete(); + } + $i = 1; + } else { + $i = 0; + $children = $calendar->getChildren(); + foreach ($children as $child) { + /** @var Sabre_CalDAV_CalendarObject $child */ + $name = $child->getName(); + if (preg_match("/import\-([0-9]+)\.ics/siu", $name, $matches)) { + if ($matches[1] > $i) $i = $matches[1]; + }; + } + $i++; + } + + foreach ($imported as $object) try { + + $str = "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Friendica//DAV-Plugin//EN\r\n"; + $str .= trim($object); + $str .= "\r\nEND:VCALENDAR\r\n"; + + $calendar->createFile("import-" . $i . ".ics", $str); + $i++; + } catch (Exception $e) { + notice(t("Something went wrong when trying to import the file. Sorry.")); + } + + $o = t("The ICS-File has been imported."); + } catch (Exception $e) { + notice(t("Something went wrong when trying to import the file. Sorry. Maybe some events were imported anyway.")); + } else { + notice(t("No file was uploaded.")); + } + } + + + $o .= "" . t("Go back to the calendar") . "

"; + + $num = q("SELECT COUNT(*) num FROM %s%scalendarobjects WHERE `calendar_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calendar_id); + + $o .= "

" . t("Import a ICS-file") . "

"; + $o .= '
'; + $o .= "\n"; + $o .= "
\n"; + if ($num[0]["num"] > 0) $o .= "
\n"; + $o .= ""; + $o .= '
'; + + return $o; +} + + /** * @param array|Sabre_CalDAV_Calendar[] $calendars * @param array|int[] $calendars_selected @@ -276,13 +358,13 @@ function wdcal_getSettingsPage(&$a) } if (isset($_REQUEST["save"])) { - check_form_security_token_redirectOnErr($a->get_baseurl() . '/dav/settings/', 'calprop'); + check_form_security_token_redirectOnErr('/dav/settings/', 'calprop'); set_pconfig($a->user["uid"], "dav", "dateformat", $_REQUEST["wdcal_date_format"]); info(t('The new values have been saved.')); } if (isset($_REQUEST["save_cals"])) { - check_form_security_token_redirectOnErr($a->get_baseurl() . '/dav/settings/', 'calprop'); + check_form_security_token_redirectOnErr('/dav/settings/', 'calprop'); $r = q("SELECT * FROM %s%scalendars WHERE `namespace` = " . CALDAV_NAMESPACE_PRIVATE . " AND `namespace_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($a->user["uid"])); foreach ($r as $cal) { @@ -315,7 +397,7 @@ function wdcal_getSettingsPage(&$a) } if (isset($_REQUEST["remove_cal"])) { - check_form_security_token_redirectOnErr($a->get_baseurl() . '/dav/settings/', 'del_cal', 't'); + check_form_security_token_redirectOnErr('/dav/settings/', 'del_cal', 't'); $c = q("SELECT * FROM %s%scalendars WHERE `id` = %d AND `namespace_id` = %d AND `namespace_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($_REQUEST["remove_cal"]), CALDAV_NAMESPACE_PRIVATE, IntVal($a->user["uid"])); @@ -365,7 +447,7 @@ function wdcal_getSettingsPage(&$a) $o .= '

' . t('Calendars') . '

'; $o .= '
'; $o .= "\n"; - $o .= ""; + $o .= "
TypeColorNameURI (for CalDAV)
"; $r = q("SELECT * FROM %s%scalendars WHERE `namespace` = " . CALDAV_NAMESPACE_PRIVATE . " AND `namespace_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($a->user["uid"])); $private_max = 0; @@ -385,7 +467,10 @@ function wdcal_getSettingsPage(&$a) $o .= ""; $o .= ""; $o .= ""; - $o .= ""; + $o .= "\n"; $o .= "\n"; @@ -397,6 +482,7 @@ function wdcal_getSettingsPage(&$a) $o .= ""; $o .= ""; $o .= ""; + $o .= ""; $o .= "\n"; $o .= "
TypeColorNameURI (for CalDAV)ICS
"; + $o .= "Export"; + if (!is_subclass_of($backend, "Sabre_CalDAV_Backend_Virtual") && $num_non_virtual > 1) $o .= " / Import"; + $o .= ""; if (!is_subclass_of($backend, "Sabre_CalDAV_Backend_Virtual") && $num_non_virtual > 1) $o .= "Delete"; $o .= "
"; diff --git a/dav/main.php b/dav/main.php index caea8485..2a0092ac 100644 --- a/dav/main.php +++ b/dav/main.php @@ -127,9 +127,7 @@ function dav_content() return wdcal_getSettingsPage($a); } elseif ($a->argv[1] == "wdcal") { if (isset($a->argv[2]) && strlen($a->argv[2]) > 0) { - if ($a->argv[2] == "ics") { - wdcal_print_user_ics(); - } elseif ($a->argv[2] == "new") { + if ($a->argv[2] == "new") { $o = ""; if (isset($_REQUEST["save"])) { check_form_security_token_redirectOnErr($a->get_baseurl() . "/dav/wdcal/", "caledit"); @@ -142,7 +140,11 @@ function dav_content() return $o; } else { $calendar_id = IntVal($a->argv[2]); - if (isset($a->argv[3]) && $a->argv[3] > 0) { + if (isset($a->argv[3]) && $a->argv[3] == "ics-export") { + wdcal_print_user_ics($calendar_id); + } elseif (isset($a->argv[3]) && $a->argv[3] == "ics-import") { + return wdcal_import_user_ics($calendar_id); + } elseif (isset($a->argv[3]) && $a->argv[3] > 0) { $recurr_uri = ""; // @TODO if (isset($a->argv[4]) && $a->argv[4] == "edit") { $o = "";