]> git.mxchange.org Git - friendica-addons.git/commitdiff
Exporting and Importing ICS-Files
authorTobias Hößl <tobias@hoessl.eu>
Sat, 14 Jul 2012 17:02:21 +0000 (17:02 +0000)
committerTobias Hößl <tobias@hoessl.eu>
Sat, 14 Jul 2012 17:02:21 +0000 (17:02 +0000)
16 files changed:
dav/SabreDAV/ChangeLog
dav/SabreDAV/lib/Sabre/CalDAV/Backend/PDO.php
dav/SabreDAV/lib/Sabre/CardDAV/Plugin.php
dav/SabreDAV/lib/Sabre/DAV/Property.php
dav/SabreDAV/lib/Sabre/VObject/RecurrenceIterator.php
dav/SabreDAV/lib/Sabre/VObject/Version.php
dav/SabreDAV/tests/Sabre/CalDAV/CalendarQueryValidatorTest.php
dav/SabreDAV/tests/Sabre/VObject/Component/VEventTest.php
dav/SabreDAV/tests/Sabre/VObject/RecurrenceIteratorTest.php
dav/calendar.friendica.fnk.php
dav/common/calendar.fnk.php
dav/common/dav_caldav_backend_common.inc.php
dav/common/dav_caldav_backend_private.inc.php
dav/common/wdcal_edit.inc.php
dav/layout.fnk.php
dav/main.php

index adafd9c9ad23c3e2b317c4a3e51150e20c7d65d3..0fe7758f533636ab7a7e0836cfc34834ef481093 100644 (file)
@@ -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
          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
index aafea1c55e1a5e7e649e471610fb2af72efa4310..105ebd338f3601f652157dd831de79946b0392f9 100644 (file)
@@ -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
index e1d70e92fc9dc482cdd2910ed89dfbc3cebf4f22..c31d0b1be14da89e70a4f451fec76318aeed8f13 100644 (file)
@@ -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;
 
             }
         }
index db4fef51afad441a864b341dcc8a755e432ef23f..26f2c1d08489bbf2adcddc6bf6f800306474186b 100644 (file)
@@ -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');
index 39d1b69907c859221a7f65e5fb8b1967d9040436..7ccd2049beaf862f940c4899ca8022fe1fc94f28 100644 (file)
@@ -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;
 
         }
index 2617c7b129d620196f425083b2b149b11c5327f9..9ee03d871181899be61043c38e056978d8d082f1 100644 (file)
@@ -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
index b75c398ab232880e9acd1f92812aae31fe76e41a..18c8330db203d1e31326a4d1ce6476203cb6388c 100644 (file)
@@ -343,6 +343,14 @@ DURATION:PT1H
 RRULE:FREQ=YEARLY
 END:VEVENT
 END:VCALENDAR
+yow;
+        $blob33 = <<<yow
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20120628
+RRULE:FREQ=DAILY
+END:VEVENT
+END:VCALENDAR
 yow;
 
         $filter1 = array(
@@ -604,8 +612,16 @@ yow;
             'time-range' => 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),
+
         );
 
     }
index a5a855f60214ad0bbf22aa7c1bdd84d2202e74be..90579cb41a86093e3c847bdc2af317e738253dbe 100644 (file)
@@ -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;
 
     }
index d1ef2da6048efd7ce7b8f6e9d43fbc8d9352dce3..0bb42bb87342519e533ed7a6b57139abab775bcb 100644 (file)
@@ -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
      */
index 2783339fd5a61283b714393cc74adb5bf323cb68..b1b0b3b358960b086713f5a5520a10ca993b54c2 100644 (file)
@@ -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)
                        );
                }
        }
+
 }
index 27f51621b3240996faf43f46aad90ea7143884ee..22f1d18c51d25caf7c6292ad242cfae2345f879b 100644 (file)
@@ -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)
index 2381e713d72091d5c8102ea3a869d2b9ff0e1fbd..99fcb6c102c835bbf3920ba3ff39f3aed0197b2f 100644 (file)
@@ -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;
index d258b6ca7480974143170d14337f62498ea1e59d..b3b32e33698d26f11015213a24e70a02106e965f 100644 (file)
@@ -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);
index b3f8889b838536cb46de053f8201a64b099af1ad..c652d97495e361c901ee0bffe7c3a5324581a634 100644 (file)
@@ -325,7 +325,7 @@ function wdcal_getEditPage_str(&$localization, $baseurl, $uid, $calendar_id, $ur
        $out .= "</div>\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 .= "<div class='rec_yearly'>";
index 7eb3e4f000a57f7ec3b68e591933997fe5757046..6f59d745626c835eaf5ac9b5065f5e9a480519ad 100644 (file)
@@ -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 .= "<a href='" . $a->get_baseurl() . "/dav/wdcal/'>" . t("Go back to the calendar") . "</a><br><br>";
+
+       $num = q("SELECT COUNT(*) num FROM %s%scalendarobjects WHERE `calendar_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calendar_id);
+
+       $o .= "<h2>" . t("Import a ICS-file") . "</h2>";
+       $o .= '<form method="POST" action="' . $a->get_baseurl() . '/dav/wdcal/' . $calendar_id . '/ics-import/" enctype="multipart/form-data">';
+       $o .= "<input type='hidden' name='form_security_token' value='" . get_form_security_token('icsimport') . "'>\n";
+       $o .= "<label for='ics_file'>" . t("ICS-File") . "</label><input type='file' name='ics_file' id='ics_file'><br>\n";
+       if ($num[0]["num"] > 0) $o .= "<label for='overwrite'>" . str_replace("#num#", $num[0]["num"], t("Overwrite all #num# existing events")) . "</label> <input name='overwrite' id='overwrite' type='checkbox'><br>\n";
+       $o .= "<input type='submit' name='save' value='" . t("Upload") . "'>";
+       $o .= '</form>';
+
+       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 .= '<br><br><h3>' . t('Calendars') . '</h3>';
        $o .= '<form method="POST" action="' . $a->get_baseurl() . '/dav/settings/">';
        $o .= "<input type='hidden' name='form_security_token' value='" . get_form_security_token('calprop') . "'>\n";
-       $o .= "<table><tr><th>Type</th><th>Color</th><th>Name</th><th>URI (for CalDAV)</th></tr>";
+       $o .= "<table><tr><th>Type</th><th>Color</th><th>Name</th><th>URI (for CalDAV)</th><th>ICS</th></tr>";
 
        $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 .= "<td style='padding: 2px; text-align: center;'><input style='margin-left: 10px; width: 70px;' class='cal_color' name='color[" . $x["id"] . "]' id='cal_color_" . $x["id"] . "' value='#" . (strlen($x["calendarcolor"]) != 6 ? "5858ff" : escape_tags($x["calendarcolor"])) . "'></td>";
                $o .= "<td style='padding: 2px;'><input style='margin-left: 10px;' name='name[" . $x["id"] . "]' value='" . escape_tags($x["displayname"]) . "' $disabled></td>";
                $o .= "<td style='padding: 2px;'><input style='margin-left: 10px; width: 150px;' name='uri[" . $x["id"] . "]' value='" . escape_tags($x["uri"]) . "' $disabled></td>";
-               $o .= "<td style='padding: 2px;'>";
+               $o .= "<td style='padding: 2px;'><a href='" . $a->get_baseurl() . "/dav/wdcal/" . $x["id"] . "/ics-export/'>Export</a>";
+               if (!is_subclass_of($backend, "Sabre_CalDAV_Backend_Virtual") && $num_non_virtual > 1) $o .= " / <a href='" . $a->get_baseurl() . "/dav/wdcal/" . $x["id"] . "/ics-import/'>Import</a>";
+               $o .= "</td>";
+               $o .= "<td style='padding: 2px; padding-left: 50px;'>";
                if (!is_subclass_of($backend, "Sabre_CalDAV_Backend_Virtual") && $num_non_virtual > 1) $o .= "<a href='" . $a->get_baseurl() . "/dav/settings/?remove_cal=" . $x["id"] . "&amp;t=" . get_form_security_token("del_cal") . "' class='delete_cal'>Delete</a>";
                $o .= "</td>\n";
                $o .= "</tr>\n";
@@ -397,6 +482,7 @@ function wdcal_getSettingsPage(&$a)
        $o .= "<td style='padding: 2px; text-align: center;'><input style='margin-left: 10px; width: 70px;' class='cal_color' name='color[new]' id='cal_color_new' value='#5858ff'></td>";
        $o .= "<td style='padding: 2px;'><input style='margin-left: 10px;' name='name[new]' value='Another calendar'></td>";
        $o .= "<td style='padding: 2px;'><input style='margin-left: 10px; width: 150px;' name='uri[new]' value='private-${private_max}'></td>";
+       $o .= "<td></td><td></td>";
        $o .= "</tr>\n";
 
        $o .= "</table>";
index caea848525937f4786b957d10403de109cd836ca..2a0092acab8d39f79d31ca5552aa186db2b03e0b 100644 (file)
@@ -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 = "";