Branch 'roundcubemail-plugins-kolab-3.0' - plugins/calendar

Thomas Brüderli bruederli at kolabsys.com
Thu Jul 4 18:34:47 CEST 2013


 plugins/calendar/calendar.php          |    2 -
 plugins/calendar/lib/calendar_ical.php |   45 +++++++++++++++++++++++++++++++--
 plugins/calendar/lib/calendar_itip.php |    2 -
 3 files changed, 45 insertions(+), 4 deletions(-)

New commits:
commit 9e321380a7b19a1b78f273b53bf87805c05fdb21
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Thu Jul 4 17:10:17 2013 +0200

    Backport: Import and export embedded attachments in itip messages (#1988)

diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index 028b553..69df2e4 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -962,7 +962,7 @@ class calendar extends rcube_plugin
     header("Content-Type: text/calendar");
     header("Content-Disposition: inline; filename=".$calname.'.ics');
 
-    $this->get_ical()->export($events, '', true);
+    $this->get_ical()->export($events, '', true, array($this->driver, 'get_attachment_body'));
 
     if ($terminate)
       exit;
diff --git a/plugins/calendar/lib/calendar_ical.php b/plugins/calendar/lib/calendar_ical.php
index e4c8e74..7563ba8 100644
--- a/plugins/calendar/lib/calendar_ical.php
+++ b/plugins/calendar/lib/calendar_ical.php
@@ -99,6 +99,8 @@ class calendar_ical
     while (($line = fgets($fp, 2048)) !== false) {
       $buffer .= $line;
       if (preg_match('/END:VEVENT/i', $line)) {
+        if (preg_match('/BEGIN:VCALENDAR/i', $buffer))
+          $buffer .= self::EOL ."END:VCALENDAR";
         $parser->parsevCalendar($buffer, 'VCALENDAR', RCMAIL_CHARSET, false);
         $buffer = '';
       }
@@ -259,6 +261,26 @@ class calendar_ical
             $event['free_busy'] = strtolower($attr['value']);
           break;
 
+        case 'ATTACH':
+          // decode inline attachment
+          if (strtoupper($attr['params']['VALUE']) == 'BINARY' && !empty($attr['value'])) {
+            $data = !strcasecmp($attr['params']['ENCODING'], 'BASE64') ? base64_decode($attr['value']) : $attr['value'];
+            $mimetype = $attr['params']['FMTTYPE'] ? $attr['params']['FMTTYPE'] : rcube_mime::file_content_type($data, $attr['params']['X-LABEL'], 'application/octet-stream', true);
+            $extensions = rcube_mime::get_mime_extensions($mimetype);
+            $filename = $attr['params']['X-LABEL'] ? $attr['params']['X-LABEL'] : 'attachment' . count($event['attachments']) . '.' . $extensions[0];
+            $event['attachments'][] = array(
+              'mimetype' => $mimetype,
+              'name' => $filename,
+              'data' => $data,
+              'size' => strlen($data),
+            );
+          }
+          else if (!empty($attr['value']) && preg_match('!^[hftps]+://!', $attr['value'])) {
+            // TODO: add support for displaying/managing link attachments in UI
+            $event['links'][] = $attr['value'];
+          }
+          break;
+
         default:
           if (substr($attr['name'], 0, 2) == 'X-')
             $event['x-custom'][] = array($attr['name'], $attr['value']);
@@ -345,10 +367,13 @@ class calendar_ical
    * @param  array   Events as array
    * @param  string  VCalendar method to advertise
    * @param  boolean Directly send data to stdout instead of returning
+   * @param  callable Callback function to fetch attachment contents, false if no attachment export
    * @return string  Events in iCalendar format (http://tools.ietf.org/html/rfc5545)
    */
-  public function export($events, $method = null, $write = false)
+  public function export($events, $method = null, $write = false, $get_attachment = false)
   {
+      $memory_limit = parse_bytes(ini_get('memory_limit'));
+      
       $ical = "BEGIN:VCALENDAR" . self::EOL;
       $ical .= "VERSION:2.0" . self::EOL;
       $ical .= "PRODID:-//Roundcube Webmail " . RCMAIL_VERSION . "//NONSGML Calendar//EN" . self::EOL;
@@ -423,7 +448,23 @@ class calendar_ical
         foreach ((array)$event['x-custom'] as $prop)
           $vevent .= $prop[0] . ':' . self::escape($prop[1]) . self::EOL;
         
-        // TODO: export attachments
+        // export attachments using the given callback function
+        if (is_callable($get_attachment) && !empty($event['attachments'])) {
+          foreach ((array)$event['attachments'] as $attach) {
+            // check available memory and skip attachment export if we can't buffer it
+            if ($memory_limit > 0 && ($memory_used = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024)
+                  && $attach['size'] && $memory_used + $attach['size'] * 3 > $memory_limit) {
+                continue;
+            }
+            // TODO: let the callback print the data directly to stdout (with b64 encoding)
+            if ($data = call_user_func($get_attachment, $attach['id'], $event)) {
+              $vevent .= sprintf('ATTACH;VALUE=BINARY;ENCODING=BASE64;FMTTYPE=%s;X-LABEL=%s:',
+                self::escape($attach['mimetype']), self::escape($attach['name']));
+              $vevent .= base64_encode($data) . self::EOL;
+            }
+            unset($data);  // attempt to free memory
+          }
+        }
         
         $vevent .= "END:VEVENT" . self::EOL;
         
diff --git a/plugins/calendar/lib/calendar_itip.php b/plugins/calendar/lib/calendar_itip.php
index cb19646..30fb812 100644
--- a/plugins/calendar/lib/calendar_itip.php
+++ b/plugins/calendar/lib/calendar_itip.php
@@ -159,7 +159,7 @@ class calendar_itip
     
     // attach ics file for this event
     $ical = $this->cal->get_ical();
-    $ics = $ical->export(array($event), $method);
+    $ics = $ical->export(array($event), $method, false, $method == 'REQUEST' ? array($this->cal->driver, 'get_attachment_body') : false);
     $message->addAttachment($ics, 'text/calendar', 'event.ics', false, '8bit', '', RCMAIL_CHARSET . "; method=" . $method);
     
     return $message;





More information about the commits mailing list