1: <?php
2: /**
3: * Copyright 2002-2014 Horde LLC (http://www.horde.org/)
4: *
5: * See the enclosed file COPYING for license information (GPL). If you
6: * did not receive this file, see http://www.horde.org/licenses/gpl.
7: *
8: * @category Horde
9: * @copyright 2002-2014 Horde LLC
10: * @license http://www.horde.org/licenses/gpl GPL
11: * @package IMP
12: */
13:
14: /**
15: * Renderer for multipart/alternative content (RFC 2046 [5.1.4]).
16: *
17: * @author Michael Slusarz <slusarz@horde.org>
18: * @category Horde
19: * @copyright 2002-2014 Horde LLC
20: * @license http://www.horde.org/licenses/gpl GPL
21: * @package IMP
22: */
23: class IMP_Mime_Viewer_Alternative extends Horde_Mime_Viewer_Base
24: {
25: /**
26: * This driver's display capabilities.
27: *
28: * @var array
29: */
30: protected $_capability = array(
31: 'full' => true,
32: 'info' => false,
33: 'inline' => true,
34: 'raw' => false
35: );
36:
37: /**
38: * Return the full rendered version of the Horde_Mime_Part object.
39: *
40: * @return array See parent::render().
41: */
42: protected function _render()
43: {
44: return $this->_IMPrender(false);
45: }
46:
47: /**
48: * Return the rendered inline version of the Horde_Mime_Part object.
49: *
50: * @return array See parent::render().
51: */
52: protected function _renderInline()
53: {
54: return $this->_IMPrender(true);
55: }
56:
57: /**
58: * Render out the currently set contents.
59: *
60: * @param boolean $inline Are we viewing inline?
61: *
62: * @return array See parent::render().
63: */
64: protected function _IMPrender($inline)
65: {
66: $base_id = $this->_mimepart->getMimeId();
67: $subparts = $this->_mimepart->contentTypeMap();
68:
69: $display_ids = $ret = array();
70:
71: $prefer_plain = (($GLOBALS['registry']->getView() == Horde_Registry::VIEW_MINIMAL) ||
72: ($GLOBALS['prefs']->getValue('alternative_display') == 'text'));
73:
74: /* Look for a displayable part. RFC: show the LAST choice that can be
75: * displayed inline. If an alternative is itself a multipart, the user
76: * agent is allowed to show that alternative, an earlier alternative,
77: * or both. If we find a multipart alternative that contains at least
78: * one viewable part, we will display all viewable subparts of that
79: * alternative. */
80: $imp_contents = $this->getConfigParam('imp_contents');
81: foreach ($subparts as $mime_id => $type) {
82: $ret[$mime_id] = null;
83: if ((strcmp($base_id, $mime_id) !== 0) &&
84: $imp_contents->canDisplay($mime_id, $inline ? IMP_Contents::RENDER_INLINE : IMP_Contents::RENDER_FULL) &&
85: /* Show HTML if $prefer_plain is false-y or if
86: * alternative_display is not 'html'. */
87: (!$prefer_plain ||
88: (($type != 'text/html') &&
89: (strpos($type, 'text/') === 0)))) {
90: $display_ids[strval($mime_id)] = true;
91: }
92: }
93:
94: /* If we found no IDs, return now. */
95: if (empty($display_ids)) {
96: $ret[$base_id] = array(
97: 'data' => '',
98: 'status' => new IMP_Mime_Status(
99: _("There are no alternative parts that can be displayed inline.")
100: ),
101: 'type' => 'text/html; charset=' . $this->getConfigParam('charset')
102: );
103: return $ret;
104: }
105:
106: /* If the last viewable message exists in a subpart, back up to the
107: * base multipart and display all viewable parts in that multipart.
108: * Else, display the single part. */
109: end($display_ids);
110: $curr_id = key($display_ids);
111: while (!is_null($curr_id) && (strcmp($base_id, $curr_id) !== 0)) {
112: if (isset($subparts[$curr_id])) {
113: $disp_id = $curr_id;
114: }
115:
116: $id_ob = new Horde_Mime_Id($curr_id);
117: $curr_id = $id_ob->idArithmetic($id_ob::ID_UP);
118: }
119:
120: /* At this point, $ret contains stubs for all parts living in the base
121: * alternative part.
122: * Go through all subparts of displayable part and make sure all parts
123: * are rendered. Parts not rendered will be marked as not being
124: * handled by this viewer (Bug #9365). */
125: $render_part = $this->_mimepart->getPart($disp_id);
126: $need_render = $subparts = $render_part->contentTypeMap();
127:
128: foreach (array_keys($subparts) as $val) {
129: if (isset($display_ids[$val]) && isset($need_render[$val])) {
130: $render = $this->getConfigParam('imp_contents')->renderMIMEPart($val, $inline ? IMP_Contents::RENDER_INLINE : IMP_Contents::RENDER_FULL);
131:
132: foreach (array_keys($render) as $id) {
133: unset($need_render[$id]);
134:
135: if (!$inline) {
136: if (!is_null($render[$id])) {
137: return array($base_id => $render[$id]);
138: }
139: } else {
140: $ret[$id] = $render[$id];
141: }
142: }
143: }
144: }
145:
146: unset($need_render[$disp_id]);
147: foreach (array_keys($need_render) as $val) {
148: unset($ret[$val]);
149: }
150:
151: return $inline
152: ? $ret
153: : null;
154: }
155:
156: }
157: