plugins/calendar

Thomas Brüderli bruederli at kolabsys.com
Wed Oct 23 14:18:07 CEST 2013


 plugins/calendar/calendar.php        |   92 +++++++++++++++++++++++++++--------
 plugins/calendar/calendar_ui.js      |    1 
 plugins/calendar/lib/calendar_ui.php |    3 -
 3 files changed, 74 insertions(+), 22 deletions(-)

New commits:
commit 6d7acac603373cc6bda777bca083afd00c30d1c9
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Wed Oct 23 14:17:33 2013 +0200

    Allow to import events from zip files (#2266)

diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index 3d8bc20..2ab4e7b 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -999,29 +999,45 @@ class calendar extends rcube_plugin
     if (!$err && $_FILES['_data']['tmp_name']) {
       $calendar = get_input_value('calendar', RCUBE_INPUT_GPC);
       $rangestart = $_REQUEST['_range'] ? date_create("now -" . intval($_REQUEST['_range']) . " months") : 0;
-      $user_email = $this->rc->user->get_username();
-
-      $ical = $this->get_ical();
-      $errors = !$ical->fopen($_FILES['_data']['tmp_name']);
-      $count = $i = 0;
-      foreach ($ical as $event) {
-        // keep the browser connection alive on long import jobs
-        if (++$i > 100 && $i % 100 == 0) {
-            echo "<!-- -->";
-            ob_flush();
-        }
 
-        // TODO: correctly handle recurring events which start before $rangestart
-        if ($event['end'] < $rangestart && (!$event['recurrence'] || ($event['recurrence']['until'] && $event['recurrence']['until'] < $rangestart)))
-          continue;
+      // extract zip file
+      if ($_FILES['_data']['type'] == 'application/zip') {
+        $count = 0;
+        if (class_exists('ZipArchive', false)) {
+          $zip = new ZipArchive();
+          if ($zip->open($_FILES['_data']['tmp_name'])) {
+            $randname = uniqid('zip-' . session_id(), true);
+            $tmpdir = slashify($this->rc->config->get('temp_dir', sys_get_temp_dir())) . $randname;
+            mkdir($tmpdir, 0700);
+
+            // extract each ical file from the archive and import it
+            for ($i = 0; $i < $zip->numFiles; $i++) { 
+              $filename = $zip->getNameIndex($i);
+              if (preg_match('/\.ics$/i', $filename)) {
+                $tmpfile = $tmpdir . '/' . $filename;
+                if (copy('zip://' . $_FILES['_data']['tmp_name'] . '#'.$filename, $tmpfile)) {
+                  $count += $this->import_from_file($tmpfile, $calendar, $rangestart, $errors);
+                  unlink($tmpfile);
+                }
+              }
+            }
 
-        $event['_owner'] = $user_email;
-        $event['calendar'] = $calendar;
-        if ($this->driver->new_event($event)) {
-          $count++;
+            rmdir($tmpdir);
+            $zip->close();
+          }
+          else {
+            $errors = 1;
+            $msg = 'Failed to open zip file.';
+          }
         }
-        else
-          $errors++;
+        else {
+          $errors = 1;
+          $msg = 'Zip files are not supported for import.';
+        }
+      }
+      else {
+        // attempt to import teh uploaded file directly
+        $count = $this->import_from_file($_FILES['_data']['tmp_name'], $calendar, $rangestart, $errors);
       }
 
       if ($count) {
@@ -1046,13 +1062,47 @@ class calendar extends rcube_plugin
       }
 
       $this->rc->output->command('plugin.import_error', array('message' => $msg));
-      $this->rc->output->command('plugin.unlock_saving', false);
     }
 
     $this->rc->output->send('iframe');
   }
 
   /**
+   * Helper function to parse and import a single .ics file
+   */
+  private function import_from_file($filepath, $calendar, $rangestart, &$errors)
+  {
+    $user_email = $this->rc->user->get_username();
+
+    $ical = $this->get_ical();
+    $errors = !$ical->fopen($filepath);
+    $count = $i = 0;
+    foreach ($ical as $event) {
+      // keep the browser connection alive on long import jobs
+      if (++$i > 100 && $i % 100 == 0) {
+          echo "<!-- -->";
+          ob_flush();
+      }
+
+      // TODO: correctly handle recurring events which start before $rangestart
+      if ($event['end'] < $rangestart && (!$event['recurrence'] || ($event['recurrence']['until'] && $event['recurrence']['until'] < $rangestart)))
+        continue;
+
+      $event['_owner'] = $user_email;
+      $event['calendar'] = $calendar;
+      if ($this->driver->new_event($event)) {
+        $count++;
+      }
+      else {
+        $errors++;
+      }
+    }
+
+    return $count;
+  }
+
+
+  /**
    * Construct the ics file for exporting events to iCalendar format;
    */
   function export_events($terminate = true)
diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index e716545..4a633eb 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -2036,6 +2036,7 @@ function rcube_calendar_ui(settings)
     this.import_error = function(p)
     {
       this.import_succeeded = false;
+      rcmail.set_busy(false, null, me.saving_lock);
       rcmail.display_message(p.message || rcmail.get_label('importerror', 'calendar'), 'error');
     }
 
diff --git a/plugins/calendar/lib/calendar_ui.php b/plugins/calendar/lib/calendar_ui.php
index 85e87f8..4a08a0c 100644
--- a/plugins/calendar/lib/calendar_ui.php
+++ b/plugins/calendar/lib/calendar_ui.php
@@ -537,7 +537,8 @@ class calendar_ui
     $max_filesize = rcube_upload_init();
 
     $input = new html_inputfield(array(
-      'type' => 'file', 'name' => '_data', 'size' => $attrib['uploadfieldsize']));
+      'type' => 'file', 'name' => '_data', 'size' => $attrib['uploadfieldsize'],
+      'accept' => '.ics, text/calendar, text/x-vcalendar, application/ics, .zip, application/zip'));
 
     $select = new html_select(array('name' => '_range', 'id' => 'event-import-range'));
     $select->add(array(




More information about the commits mailing list