4 commits - plugins/calendar plugins/libcalendaring

Thomas Brüderli bruederli at kolabsys.com
Wed Oct 16 13:08:02 CEST 2013


 plugins/calendar/calendar.php            |   21 +++++++++++++++------
 plugins/calendar/calendar_ui.js          |   17 +++++++++++++++++
 plugins/libcalendaring/libcalendaring.js |    6 +++++-
 plugins/libcalendaring/libvcalendar.php  |    9 +++++++++
 4 files changed, 46 insertions(+), 7 deletions(-)

New commits:
commit 6dbbdba8a0f49ca35775d5699cbaf8edb8659017
Merge: 6951f8d 5c6a528
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Wed Oct 16 13:07:36 2013 +0200

    Merge branch 'master' of ssh://git.kolab.org/git/roundcubemail-plugins-kolab



commit 6951f8d4a4e710f959c0df3895fc57c61bfbb0f8
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Wed Oct 16 13:01:55 2013 +0200

    Catch errors on iCal import and provide appropriate feedback to the user (#2353)

diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index 4dec708..de4645e 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -975,10 +975,18 @@ class calendar extends rcube_plugin
 
     if (!$err && $_FILES['_data']['tmp_name']) {
       $calendar = get_input_value('calendar', RCUBE_INPUT_GPC);
-      $events = $this->get_ical()->import_from_file($_FILES['_data']['tmp_name']);
-
-      $count = $errors = 0;
       $rangestart = $_REQUEST['_range'] ? date_create("now -" . intval($_REQUEST['_range']) . " months") : 0;
+      $count = $errors = 0;
+
+      try {
+          $events = $this->get_ical()->import_from_file($_FILES['_data']['tmp_name'], 'UTF-8', true);
+      }
+      catch (Exception $e) {
+          $errors = 1;
+          $msg = $e->getMessage();
+          $events = array();
+      }
+
       foreach ($events as $event) {
         // TODO: correctly handle recurring events which start before $rangestart
         if ($event['end'] < $rangestart && (!$event['recurrence'] || ($event['recurrence']['until'] && $event['recurrence']['until'] < $rangestart)))
@@ -1000,8 +1008,9 @@ class calendar extends rcube_plugin
         $this->rc->output->command('display_message', $this->gettext('importnone'), 'notice');
         $this->rc->output->command('plugin.import_success', array('source' => $calendar));
       }
-      else
-        $this->rc->output->command('display_message', $this->gettext('importerror'), 'error');
+      else {
+        $this->rc->output->command('plugin.import_error', array('message' => $this->gettext('importerror') . ($msg ? ': ' . $msg : '')));
+      }
     }
     else {
       if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
@@ -1012,7 +1021,7 @@ class calendar extends rcube_plugin
         $msg = rcube_label('fileuploaderror');
       }
 
-      $this->rc->output->command('display_message', $msg, 'error');
+      $this->rc->output->command('plugin.import_error', array('message' => $msg));
       $this->rc->output->command('plugin.unlock_saving', false);
     }
 
diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index 81e350f..d627253 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -1963,10 +1963,17 @@ function rcube_calendar_ui(settings)
         if (form && form.elements._data.value) {
           rcmail.async_upload_form(form, 'import_events', function(e) {
             rcmail.set_busy(false, null, me.saving_lock);
+            $('.ui-dialog-buttonpane button', $dialog.parent()).button('enable');
+
+            // display error message if no sophisticated response from server arrived (e.g. iframe load error)
+            if (me.import_succeeded === null)
+              rcmail.display_message(rcmail.get_label('importerror', 'calendar'), 'error');
           });
 
           // display upload indicator
+          me.import_succeeded = null;
           me.saving_lock = rcmail.set_busy(true, 'uploading');
+          $('.ui-dialog-buttonpane button', $dialog.parent()).button('disable');
         }
       };
       
@@ -1981,6 +1988,7 @@ function rcube_calendar_ui(settings)
         closeOnEscape: false,
         title: rcmail.gettext('importevents', 'calendar'),
         close: function() {
+          $('.ui-dialog-buttonpane button', $dialog.parent()).button('enable');
           $dialog.dialog("destroy").hide();
         },
         buttons: buttons,
@@ -1992,6 +2000,7 @@ function rcube_calendar_ui(settings)
     // callback from server if import succeeded
     this.import_success = function(p)
     {
+      this.import_succeeded = true;
       $("#eventsimport:ui-dialog").dialog('close');
       rcmail.set_busy(false, null, me.saving_lock);
       rcmail.gui_objects.importform.reset();
@@ -2000,6 +2009,13 @@ function rcube_calendar_ui(settings)
         this.refresh(p);
     };
 
+    // callback from server to report errors on import
+    this.import_error = function(p)
+    {
+      this.import_succeeded = false;
+      rcmail.display_message(p.message || rcmail.get_label('importerror', 'calendar'), 'error');
+    }
+
     // show URL of the given calendar in a dialog box
     this.showurl = function(calendar)
     {
@@ -2762,6 +2778,7 @@ window.rcmail && rcmail.addEventListener('init', function(evt) {
   rcmail.addEventListener('plugin.unlock_saving', function(p){ cal.unlock_saving(); });
   rcmail.addEventListener('plugin.refresh_calendar', function(p){ cal.refresh(p); });
   rcmail.addEventListener('plugin.import_success', function(p){ cal.import_success(p); });
+  rcmail.addEventListener('plugin.import_error', function(p){ cal.import_error(p); });
 
   // let's go
   var cal = new rcube_calendar_ui($.extend(rcmail.env.calendar_settings, rcmail.env.libcal_settings));


commit 1f851a7663e1ffd738ccb5357b386e88fdd11828
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Wed Oct 16 12:46:13 2013 +0200

    iCal parsing can consume high memory when file contains lots of events. Abort import if memory is expected to get exhausted (#2353)

diff --git a/plugins/libcalendaring/libvcalendar.php b/plugins/libcalendaring/libvcalendar.php
index c23d40b..24781c9 100644
--- a/plugins/libcalendaring/libvcalendar.php
+++ b/plugins/libcalendaring/libvcalendar.php
@@ -113,6 +113,15 @@ class libvcalendar
         // TODO: convert charset to UTF-8 if other
 
         try {
+            // estimate the memory usage and try to avoid fatal errors when allowed memory gets exhausted
+            $count = substr_count($vcal, 'BEGIN:VEVENT');
+            $memory_available = parse_bytes(ini_get('memory_limit')) - (function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024);
+            $expected_memory = $count * 70*1024;  // assume ~ 70K per event (empirically determined)
+
+            if ($memory_available > 0 && $expected_memory > $memory_available) {
+                throw new Exception("iCal file too big");
+            }
+
             $vobject = VObject\Reader::read($vcal, VObject\Reader::OPTION_FORGIVING | VObject\Reader::OPTION_IGNORE_INVALID_LINES);
             if ($vobject)
                 return $this->import_from_vobject($vobject);


commit dae0af24cd19d8c533ab4f89ea7eda8e495ed92a
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Wed Oct 16 12:30:20 2013 +0200

    Avoid warnings if libcalendaring env variables are not set (#2356)

diff --git a/plugins/libcalendaring/libcalendaring.js b/plugins/libcalendaring/libcalendaring.js
index 73d1c1e..5dcc3d4 100644
--- a/plugins/libcalendaring/libcalendaring.js
+++ b/plugins/libcalendaring/libcalendaring.js
@@ -23,12 +23,16 @@
 function rcube_libcalendaring(settings)
 {
     // member vars
-    this.settings = settings;
+    this.settings = settings || {};
     this.alarm_ids = [];
     this.alarm_dialog = null;
     this.snooze_popup = null;
     this.dismiss_link = null;
 
+    // abort if env isn't set
+    if (!settings || !settings.date_format)
+      return;
+
     // private vars
     var me = this;
     var gmt_offset = (new Date().getTimezoneOffset() / -60) - (settings.timezone || 0) - (settings.dst || 0);




More information about the commits mailing list