Show photos in vcard attachments, even if they don't fit into a data: url.
authorJan Schneider <jan@horde.org>
Mon, 1 Mar 2010 15:06:16 +0000 (16:06 +0100)
committerJan Schneider <jan@horde.org>
Mon, 1 Mar 2010 15:06:16 +0000 (16:06 +0100)
framework/Mime/lib/Horde/Mime/Viewer/Vcard.php
imp/config/mime_drivers.php.dist
imp/lib/Mime/Viewer/Vcard.php [new file with mode: 0644]
imp/themes/graphics/mime/vcard.png [new file with mode: 0644]
imp/themes/silver/graphics/mime/vcard.png [new file with mode: 0644]
imp/themes/tango-blue/graphics/mime/vcard.png [new file with mode: 0644]

index 01c569c..8f636a5 100644 (file)
@@ -25,6 +25,13 @@ class Horde_Mime_Viewer_Vcard extends Horde_Mime_Viewer_Driver
     );
 
     /**
+     * URL that can be used as a callback for displaying images.
+     *
+     * @var Horde_Url
+     */
+    protected $_imageUrl;
+
+    /**
      * Return the full rendered version of the Horde_Mime_Part object.
      *
      * @return array  See Horde_Mime_Viewer_Driver::render().
@@ -86,12 +93,10 @@ class Horde_Mime_Viewer_Vcard extends Horde_Mime_Viewer_Driver
 
         $html .= '<table cellspacing="1" border="0" cellpadding="1">';
 
-        $i = 0;
-        foreach ($iCal->getComponents() as $vc) {
+        foreach ($iCal->getComponents() as $i => $vc) {
             if ($i > 0) {
                 $html .= '<tr><td colspan="2">&nbsp;</td></tr>';
             }
-            ++$i;
 
             $html .= '<tr><td colspan="2" class="header">';
             $fullname = $vc->getAttributeDefault('FN', false);
@@ -118,7 +123,7 @@ class Horde_Mime_Viewer_Vcard extends Horde_Mime_Viewer_Driver
             }
 
             $photos = $vc->getAllAttributes('PHOTO');
-            foreach ($photos as $photo) {
+            foreach ($photos as $p => $photo) {
                 if (isset($photo['params']['VALUE']) &&
                     Horde_String::upper($photo['params']['VALUE']) == 'URI') {
                     $html .= $this->_row(_("Photo"),
@@ -126,12 +131,17 @@ class Horde_Mime_Viewer_Vcard extends Horde_Mime_Viewer_Driver
                                          false);
                 } elseif (isset($photo['params']['ENCODING']) &&
                           Horde_String::upper($photo['params']['ENCODING']) == 'B' &&
-                          isset($photo['params']['TYPE']) &&
-                          ($GLOBALS['browser']->hasFeature('datauri') === true ||
-                           $GLOBALS['browser']->hasFeature('datauri') >= strlen($photo['value']))) {
-                    $html .= $this->_row(_("Photo"),
-                                         '<img src="data:' . htmlspecialchars($photo['params']['TYPE'] . ';base64,' . $photo['value']) . '" />',
-                                         false);
+                          isset($photo['params']['TYPE'])) {
+                    if ($GLOBALS['browser']->hasFeature('datauri') === true ||
+                        $GLOBALS['browser']->hasFeature('datauri') >= strlen($photo['value'])) {
+                        $html .= $this->_row(_("Photo"),
+                                             '<img src="data:' . htmlspecialchars($photo['params']['TYPE'] . ';base64,' . $photo['value']) . '" />',
+                                             false);
+                    } elseif ($this->_imageUrl) {
+                        $html .= $this->_row(_("Photo"),
+                                             '<img src="' . htmlspecialchars($this->_imageUrl->add(array('c' => $i, 'p' => $p))) . '" />',
+                                             false);
+                    }
                 }
             }
 
index 1b66dbe..b8dc816 100644 (file)
  * smime          S/MIME signed/encrypted messages
  * status         Mail delivery status messages
  * tnef           MS-TNEF attachments
+ * vcard          vCards
  * zip            ZIP attachments
  */
 $mime_drivers_map['imp']['registered'] = array(
     'alternative', 'appledouble', 'enriched', 'html', 'images', 'itip',
     'mdn', 'partial', 'pdf', 'pgp', 'plain', 'related', 'rfc822', 'smil',
-    'smime', 'status', 'tnef', 'zip'
+    'smime', 'status', 'tnef', 'vcard', 'zip'
 );
 
 /**
@@ -177,6 +178,18 @@ $mime_drivers['imp']['smime'] = array(
 );
 
 /**
+ * vCard driver settings
+ */
+$mime_drivers['imp']['vcard'] = array(
+    'handles' => array(
+        'text/vcard', 'text/x-vcard', 'text/directory'
+    ),
+    'icons' => array(
+        'default' => 'vcard.png'
+    )
+);
+
+/**
  * Zip File Attachments settings
  */
 $mime_drivers['imp']['zip'] = array(
diff --git a/imp/lib/Mime/Viewer/Vcard.php b/imp/lib/Mime/Viewer/Vcard.php
new file mode 100644 (file)
index 0000000..372503d
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+/**
+ * The IMP_Horde_Mime_Viewer_Vcard class renders out the contents of vCard
+ * files in HTML format and allows inline display of embedded photos.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @package IMP
+ */
+class IMP_Horde_Mime_Viewer_Vcard extends Horde_Mime_Viewer_Vcard
+{
+    /**
+     * Return the full rendered version of the Horde_Mime_Part object.
+     *
+     * URL parameters used by this function:
+     * <pre>
+     * 'c' - (integer) The VCARD component that contains an image.
+     * 'p' - (integer) The index of image inside the component to display.
+     * </pre>
+     *
+     * @return array  See Horde_Mime_Viewer_Driver::render().
+     * @throws Horde_Exception
+     */
+    protected function _render()
+    {
+        if (is_null(Horde_Util::getFormData('p'))) {
+            $this->_imageUrl = $this->_params['contents']->urlView($this->_mimepart, 'download_render');
+            return parent::_render();
+        }
+
+        /* Send the requested photo. */
+        $data = $this->_mimepart->getContents();
+        $ical = new Horde_iCalendar();
+        if (!$ical->parsevCalendar($data, 'VCALENDAR', $this->_mimepart->getCharset())) {
+            // TODO: Error reporting
+            return array();
+        }
+        $components = $ical->getComponents();
+        $c = Horde_Util::getFormData('c');
+        $p = Horde_Util::getFormData('p');
+        if (!isset($components[$c])) {
+            // TODO: Error reporting
+            return array();
+        }
+        $name = $components[$c]->getAttributeDefault('FN', false);
+        if ($name === false) {
+            $name = $components[$c]->printableName();
+        }
+        if (empty($name)) {
+            $name = preg_replace('/\..*?$/', '', $this->_mimepart->getName());
+        }
+
+        $photos = $components[$c]->getAllAttributes('PHOTO');
+        if (!isset($photos[$p])) {
+            // TODO: Error reporting
+            return array();
+        }
+        return array(
+            $this->_mimepart->getMimeId() => array(
+                'data' => base64_decode($photos[$p]['value']),
+                'name' => $name . '.' . Horde_Mime_Magic::mimeToExt($photos[$p]['params']['TYPE']),
+                'status' => array(),
+                'type' => $photos[$p]['params']['TYPE'],
+            )
+        );
+    }
+
+}
diff --git a/imp/themes/graphics/mime/vcard.png b/imp/themes/graphics/mime/vcard.png
new file mode 100644 (file)
index 0000000..3ac4325
Binary files /dev/null and b/imp/themes/graphics/mime/vcard.png differ
diff --git a/imp/themes/silver/graphics/mime/vcard.png b/imp/themes/silver/graphics/mime/vcard.png
new file mode 100644 (file)
index 0000000..c02f315
Binary files /dev/null and b/imp/themes/silver/graphics/mime/vcard.png differ
diff --git a/imp/themes/tango-blue/graphics/mime/vcard.png b/imp/themes/tango-blue/graphics/mime/vcard.png
new file mode 100644 (file)
index 0000000..fdbcbe0
Binary files /dev/null and b/imp/themes/tango-blue/graphics/mime/vcard.png differ