Yay! A totally working alternative Viewer!
authorMichael M Slusarz <slusarz@curecanti.org>
Thu, 13 Nov 2008 04:53:19 +0000 (21:53 -0700)
committerMichael M Slusarz <slusarz@curecanti.org>
Thu, 13 Nov 2008 04:53:19 +0000 (21:53 -0700)
That doesn't warp space/time in an effort to display subparts correctly!

imp/lib/Mime/Viewer/alternative.php

index bec5621..1806348 100644 (file)
@@ -35,40 +35,66 @@ class IMP_Horde_Mime_Viewer_alternative extends Horde_Mime_Viewer_Driver
      */
     protected function _renderInline()
     {
-        $display_id = $last_id = null;
-
+        $base_id = $this->_mimepart->getMimeId();
         $subparts = $this->_mimepart->contentTypeMap();
-        unset($subparts[key($subparts)]);
 
-        /* Look for a displayable part. RFC 2046: show the LAST choice that
-         * can be displayed inline. */
+        $base_ids = $display_ids = $ret = array();
+
+        /* Look for a displayable part. RFC: show the LAST choice that can be
+         * displayed inline. If an alternative is itself a multipart, the user
+         * agent is allowed to show that alternative, an earlier alternative,
+         * or both. If we find a multipart alternative that contains at least
+         * one viewable part, we will display all viewable subparts of that
+         * alternative. */
         foreach (array_keys($subparts) as $mime_id) {
-            if (is_null($last_id) || (strpos($mime_id, $last_id) !== 0)) {
-                $last_id = null;
-                if ($this->_params['contents']->canDisplayInline($mime_id)) {
-                    $display_id = $last_id = $mime_id;
-                }
+            $ret[$mime_id] = null;
+            if ((strcmp($base_id, $mime_id) !== 0) &&
+                $this->_params['contents']->canDisplay($mime_id, IMP_Contents::RENDER_INLINE)) {
+                $display_ids[] = $mime_id;
             }
         }
 
-        if (is_null($display_id)) {
-            return array(
+        /* If we found no IDs, return now. */
+        if (empty($display_ids)) {
+            $ret[$base_id] = array(
+                'data' => '',
                 'status' => array(
                     array(
                         'text' => array(_("There are no alternative parts that can be displayed inline.")),
                         'type' => 'info'
                     )
-                )
+                ),
+                'type' => 'text/html; charset=' . NLS::getCharset()
             );
+            return $ret;
         }
 
-        $render_data = $this->_params['contents']->renderMIMEPart($display_id, 'inline', array('params' => $this->_params));
+        /* Get the list of IDs directly under the subpart. */
+        $id = Horde_Mime::mimeIdArithmetic($base_id, 'down');
+        do {
+            $base_ids[] = $id;
+            $id = Horde_Mime::mimeIdArithmetic($id, 'next');
+        } while (isset($subparts[$id]));
+
+        /* If the last viewable message exists in a subpart, back up to the
+         * base multipart and display all viewable parts in that multipart.
+         * Else, display the single part. */
+        $disp_id = end($display_ids);
+        while (!is_null($disp_id) && !in_array($disp_id, $base_ids)) {
+            $disp_id = Horde_Mime::mimeIdArithmetic($disp_id, 'up');
+        }
+
+        /* Now grab all keys under this ID. */
+        $render_part = $this->_params['contents']->getMIMEPart($disp_id, array('nocontents' => true));
+        foreach (array_keys($render_part->contentTypeMap()) as $val) {
+            if (in_array($val, $display_ids) && !isset($ret[$val])) {
+                $render = $this->_params['contents']->renderMIMEPart($val, 'inline', array('params' => $this->_params));
+                foreach (array_keys($render) as $id) {
+                    $ret[$id] = $render[$id];
+                }
+            }
+        }
 
-        return array(
-            'data' => $render_data['data'],
-            'ids' => array_keys($subparts),
-            'status' => $render_data['status'],
-            'summary_id' => isset($render_data['summary_id']) ? $render_data['summary_id'] : $display_id
-        );
+        return $ret;
     }
 }