4 commits - plugins/calendar plugins/libkolab

Thomas Brüderli bruederli at kolabsys.com
Wed Jun 13 17:42:53 CEST 2012


 plugins/calendar/calendar_ui.js                   |    4 +-
 plugins/calendar/drivers/kolab/kolab_calendar.php |   36 ++++++++++--------
 plugins/calendar/drivers/kolab/kolab_driver.php   |    1 
 plugins/calendar/skins/larry/calendar.css         |    9 ++++
 plugins/libkolab/lib/kolab_format_event.php       |    7 ++-
 plugins/libkolab/lib/kolab_storage_cache.php      |    7 ++-
 plugins/libkolab/lib/kolab_storage_folder.php     |   43 ++++++++++++++++------
 7 files changed, 74 insertions(+), 33 deletions(-)

New commits:
commit d5c2f15ccbdadb54af5309fe7a316d87353a0340
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Wed Jun 13 17:39:18 2012 +0200

    Improve attachments handling:
    - use Content-ID as key in _attachments list; new attachments have numeric keys
    - generate a unique Content-ID for new/changed attachments in libkolab
    - bugfix: don't cache empty attachment entries

diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index 520f8a5..5d84b1b 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -220,7 +220,7 @@ function rcube_calendar_ui(settings)
     // check if the event has 'real' attendees, excluding the current user
     var has_attendees = function(event)
     {
-      return (event.attendees && (event.attendees.length > 1 || event.attendees[0].email != settings.identity.email));
+      return (event.attendees && event.attendees.length && (event.attendees.length > 1 || event.attendees[0].email != settings.identity.email));
     };
     
     // check if the current user is an attendee of this event
diff --git a/plugins/calendar/drivers/kolab/kolab_calendar.php b/plugins/calendar/drivers/kolab/kolab_calendar.php
index f8525be..a8a2755 100644
--- a/plugins/calendar/drivers/kolab/kolab_calendar.php
+++ b/plugins/calendar/drivers/kolab/kolab_calendar.php
@@ -429,9 +429,10 @@ class kolab_calendar
       $record['end'] = $record['start'] + 3600;
 
     if (!empty($record['_attachments'])) {
-      foreach ($record['_attachments'] as $name => $attachment) {
+      foreach ($record['_attachments'] as $key => $attachment) {
         if ($attachment !== false) {
-          $attachment['name'] = $name;
+          if (!$attachment['name'])
+            $attachment['name'] = $key;
           $attachments[] = $attachment;
         }
       }
@@ -460,29 +461,34 @@ class kolab_calendar
   {
     $object = &$event;
 
-    // in Horde attachments are indexed by name
+    // in kolab_storage attachments are indexed by content-id
     $object['_attachments'] = array();
     if (is_array($event['attachments'])) {
       $collisions = array();
       foreach ($event['attachments'] as $idx => $attachment) {
-        // Roundcube ID has nothing to do with Horde ID, remove it
-        if ($attachment['content'])
+        $key = null;
+        // Roundcube ID has nothing to do with the storage ID, remove it
+        if ($attachment['content']) {
           unset($attachment['id']);
+        }
+        else {
+          foreach ((array)$old['_attachments'] as $cid => $oldatt) {
+            if ($attachment['id'] == $oldatt['id'])
+              $key = $cid;
+          }
+        }
 
         // flagged for deletion => set to false
         if ($attachment['_deleted']) {
-          $object['_attachments'][$attachment['name']] = false;
+          $object['_attachments'][$key] = false;
         }
+        // replace existing entry
+        else if ($key) {
+          $object['_attachments'][$key] = $attachment;
+        }
+        // append as new attachment
         else {
-          // Horde code assumes that there will be no more than
-          // one file with the same name: make filenames unique
-          $filename = $attachment['name'];
-          if ($collisions[$filename]++) {
-            $ext = preg_match('/(\.[a-z0-9]{1,6})$/i', $filename, $m) ? $m[1] : null;
-            $attachment['name'] = basename($filename, $ext) . '-' . $collisions[$filename] . $ext;
-          }
-
-          $object['_attachments'][$attachment['name']] = $attachment;
+          $object['_attachments'][] = $attachment;
         }
       }
 
diff --git a/plugins/calendar/drivers/kolab/kolab_driver.php b/plugins/calendar/drivers/kolab/kolab_driver.php
index 42d758c..41dc337 100644
--- a/plugins/calendar/drivers/kolab/kolab_driver.php
+++ b/plugins/calendar/drivers/kolab/kolab_driver.php
@@ -582,6 +582,7 @@ class kolab_driver extends calendar_driver
           }
         }
       }
+      unset($event['deleted_attachments']);
     }
 
     // handle attachments to add
diff --git a/plugins/libkolab/lib/kolab_format_event.php b/plugins/libkolab/lib/kolab_format_event.php
index c48b63d..4742b51 100644
--- a/plugins/libkolab/lib/kolab_format_event.php
+++ b/plugins/libkolab/lib/kolab_format_event.php
@@ -77,12 +77,12 @@ class kolab_format_event extends kolab_format_xcal
 
         // save attachments
         $vattach = new vectorattachment;
-        foreach ((array)$object['_attachments'] as $name => $attr) {
+        foreach ((array)$object['_attachments'] as $cid => $attr) {
             if (empty($attr))
                 continue;
             $attach = new Attachment;
-            $attach->setLabel($name);
-            $attach->setUri('cid:' . $name, $attr['mimetype']);
+            $attach->setLabel((string)$attr['name']);
+            $attach->setUri('cid:' . $cid, $attr['mimetype']);
             $vattach->push($attach);
         }
         $this->obj->setAttachments($vattach);
@@ -148,6 +148,7 @@ class kolab_format_event extends kolab_format_xcal
                 $name = $attach->label();
                 $data = $attach->data();
                 $object['_attachments'][$name] = array(
+                    'name' => $name,
                     'mimetype' => $attach->mimetype(),
                     'size' => strlen($data),
                     'content' => $data,
diff --git a/plugins/libkolab/lib/kolab_storage_folder.php b/plugins/libkolab/lib/kolab_storage_folder.php
index d2a78de..df5e811 100644
--- a/plugins/libkolab/lib/kolab_storage_folder.php
+++ b/plugins/libkolab/lib/kolab_storage_folder.php
@@ -415,6 +415,7 @@ class kolab_storage_folder
                 $key = $part->content_id ? trim($part->content_id, '<>') : $part->filename;
                 $attachments[$key] = array(
                     'id' => $part->mime_id,
+                    'name' => $part->filename,
                     'mimetype' => $part->mimetype,
                     'size' => $part->size,
                 );
@@ -509,14 +510,35 @@ class kolab_storage_folder
 
         // copy attachments from old message
         if (!empty($object['_msguid']) && ($old = $this->cache->get($object['_msguid'], $type, $object['_mailbox']))) {
-            foreach ((array)$old['_attachments'] as $name => $att) {
-                if (!isset($object['_attachments'][$name])) {
-                    $object['_attachments'][$name] = $old['_attachments'][$name];
+            foreach ((array)$old['_attachments'] as $key => $att) {
+                if (!isset($object['_attachments'][$key])) {
+                    $object['_attachments'][$key] = $old['_attachments'][$key];
+                }
+                // unset deleted attachment entries
+                if ($object['_attachments'][$key] == false) {
+                    unset($object['_attachments'][$key]);
                 }
                 // load photo.attachment from old Kolab2 format to be directly embedded in xcard block
-                if ($name == 'photo.attachment' && !isset($object['photo']) && !$object['_attachments'][$name]['content'] && $att['id']) {
+                else if ($key == 'photo.attachment' && !isset($object['photo']) && !$object['_attachments'][$key]['content'] && $att['id']) {
                     $object['photo'] = $this->get_attachment($object['_msguid'], $att['id'], $object['_mailbox']);
-                    unset($object['_attachments'][$name]);
+                    unset($object['_attachments'][$key]);
+                }
+            }
+        }
+
+        // generate unique keys (used as content-id) for attachments
+        if (is_array($object['_attachments'])) {
+            $numatt = count($object['_attachments']);
+            foreach ($object['_attachments'] as $key => $attachment) {
+                if (is_numeric($key) && $key < $numatt) {
+                    // derrive content-id from attachment file name
+                    $ext = preg_match('/(\.[a-z0-9]{1,6})$/i', $attachment['name'], $m) ? $m[1] : null;
+                    $basename = preg_replace('/[^a-z0-9_.-]/i', '', basename($attachment['name'], $ext));  // to 7bit ascii
+                    if (!$basename) $basename = 'noname';
+                    $cid = $basename . '.' . microtime(true) . $ext;
+
+                    $object['_attachments'][$cid] = $attachment;
+                    unset($object['_attachments'][$key]);
                 }
             }
         }
@@ -685,24 +707,25 @@ class kolab_storage_folder
 
         // save object attachments as separate parts
         // TODO: optimize memory consumption by using tempfiles for transfer
-        foreach ((array)$object['_attachments'] as $name => $att) {
+        foreach ((array)$object['_attachments'] as $key => $att) {
             if (empty($att['content']) && !empty($att['id'])) {
                 $msguid = !empty($object['_msguid']) ? $object['_msguid'] : $object['uid'];
                 $att['content'] = $this->get_attachment($msguid, $att['id'], $object['_mailbox']);
             }
 
-            $headers = array('Content-ID' => Mail_mimePart::encodeHeader('Content-ID', '<' . $name . '>', RCMAIL_CHARSET, 'quoted-printable'));
+            $headers = array('Content-ID' => Mail_mimePart::encodeHeader('Content-ID', '<' . $key . '>', RCMAIL_CHARSET, 'quoted-printable'));
+            $name = !empty($att['name']) ? $att['name'] : $key;
 
             if (!empty($att['content'])) {
-                $mime->addAttachment($att['content'], $att['mimetype'], $name, false, 'base64', 'attachment', '', '', '', null, null, '', null, $headers);
+                $mime->addAttachment($att['content'], $att['mimetype'], $name, false, 'base64', 'attachment', '', '', '', null, null, '', RCMAIL_CHARSET, $headers);
                 $part_id++;
             }
             else if (!empty($att['path'])) {
-                $mime->addAttachment($att['path'], $att['mimetype'], $name, true, 'base64', 'attachment', '', '', '', null, null, '', null, $headers);
+                $mime->addAttachment($att['path'], $att['mimetype'], $name, true, 'base64', 'attachment', '', '', '', null, null, '', RCMAIL_CHARSET, $headers);
                 $part_id++;
             }
 
-            $object['_attachments'][$name]['id'] = $part_id;
+            $object['_attachments'][$key]['id'] = $part_id;
         }
 
         return $mime->getMessage();


commit f678e8f16ae81b2189d668f0de15e8bbaf40c2f3
Merge: ab9c24b 0f9e0e5
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Wed Jun 13 10:36:53 2012 +0200

    Merge branch 'master' of ssh://git.kolabsys.com/git/roundcube



commit ab9c24b0dd80869db7c0879250d8c386b52cb94a
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Fri Jun 8 18:23:06 2012 +0200

    Display attendee delete link as icon

diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index b888825..520f8a5 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -1453,7 +1453,7 @@ function rcube_calendar_ui(settings)
 
       // delete icon
       var icon = rcmail.env.deleteicon ? '<img src="' + rcmail.env.deleteicon + '" alt="" />' : rcmail.gettext('delete');
-      var dellink = '<a href="#delete" class="deletelink" title="' + Q(rcmail.gettext('delete')) + '">' + icon + '</a>';
+      var dellink = '<a href="#delete" class="iconlink delete deletelink" title="' + Q(rcmail.gettext('delete')) + '">' + icon + '</a>';
       
       var html = '<td class="role">' + select + '</td>' +
         '<td class="name">' + dispname + '</td>' +
diff --git a/plugins/calendar/skins/larry/calendar.css b/plugins/calendar/skins/larry/calendar.css
index cba1149..0900ccf 100644
--- a/plugins/calendar/skins/larry/calendar.css
+++ b/plugins/calendar/skins/larry/calendar.css
@@ -575,6 +575,15 @@ td.topalign {
 	text-overflow: ellipsis;
 }
 
+#edit-attendees-table a.deletelink {
+	display: block;
+	width: 17px;
+	height: 17px;
+	padding: 0;
+	overflow: hidden;
+	text-indent: 1000px;
+}
+
 #edit-attendees-form {
 	position: relative;
 	margin-top: 1em;


commit d19ee85667582d51cd24b59aaae9de4e01bfb2a7
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Fri Jun 8 17:49:25 2012 +0200

    Save created timestamp with every cache entry

diff --git a/plugins/libkolab/lib/kolab_storage_cache.php b/plugins/libkolab/lib/kolab_storage_cache.php
index 6d36ae3..091ddeb 100644
--- a/plugins/libkolab/lib/kolab_storage_cache.php
+++ b/plugins/libkolab/lib/kolab_storage_cache.php
@@ -215,8 +215,8 @@ class kolab_storage_cache
 
                 $result = $this->db->query(
                     "INSERT INTO kolab_cache ".
-                    " (resource, type, msguid, uid, data, xml, dtstart, dtend, tags, words)".
-                    " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
+                    " (resource, type, msguid, uid, created, data, xml, dtstart, dtend, tags, words)".
+                    " VALUES (?, ?, ?, ?, " . $this->db->now() . ", ?, ?, ?, ?, ?, ?)",
                     $this->resource_uri,
                     $objtype,
                     $msguid,
@@ -542,6 +542,7 @@ class kolab_storage_cache
                 $this->db->quote($objtype),
                 $this->db->quote($msguid),
                 $this->db->quote($object['uid']),
+                $this->db->now(),
                 $this->db->quote($sql_data['data']),
                 $this->db->quote($sql_data['xml']),
                 $this->db->quote($sql_data['dtstart']),
@@ -555,7 +556,7 @@ class kolab_storage_cache
         if ($buffer && (!$msguid || (strlen($buffer) + strlen($line) > $this->max_sql_packet))) {
             $result = $this->db->query(
                 "INSERT INTO kolab_cache ".
-                " (resource, type, msguid, uid, data, xml, dtstart, dtend, tags, words)".
+                " (resource, type, msguid, uid, created, data, xml, dtstart, dtend, tags, words)".
                 " VALUES $buffer"
             );
             if (!$this->db->affected_rows($result)) {





More information about the commits mailing list