From c0763dc37066404c997e4b961d568c78f064c400 Mon Sep 17 00:00:00 2001 From: Michael M Slusarz Date: Mon, 10 Nov 2008 22:47:12 -0700 Subject: [PATCH] More rendering fixes/improvements. multipart/alternative driver now works on basic messages. Be more liberal about what an 'attachment' is for now. Determination of what should be shown inline ultimately rests with view code, not base IMP_Contents library code. Also, it is necessary to determine the rendered data before we can create the list of attachments (since the attachments may already be displayed in the body). --- imp/lib/Contents.php | 54 +++++-------- imp/lib/Mime/Viewer/alternative.php | 150 ++++++++++++++---------------------- imp/message.php | 103 ++++++++++++++----------- 3 files changed, 133 insertions(+), 174 deletions(-) diff --git a/imp/lib/Contents.php b/imp/lib/Contents.php index 452953fec..97ec21b6e 100644 --- a/imp/lib/Contents.php +++ b/imp/lib/Contents.php @@ -25,7 +25,6 @@ class IMP_Contents const SUMMARY_IMAGE_SAVE = 256; const SUMMARY_STRIP_LINK = 512; const SUMMARY_DOWNLOAD_ALL = 1024; - const SUMMARY_TEXTBODY = 2048; /** * The IMAP index of the message. @@ -411,9 +410,6 @@ class IMP_Contents * * IMP_Contents::SUMMARY_DOWNLOAD_ALL * Output: info = 'download_all' - * - * IMP_Contents::SUMMARY_TEXTBODY - * Output: info = 'textbody' * * * @return array An array with two keys: 'info' and 'parts'. See above @@ -421,12 +417,10 @@ class IMP_Contents */ public function getSummary($mask = 0) { - $last_id = null; $info = array( 'download_all' => array(), 'has' => array(), - 'render' => array(), - 'textbody' => null + 'render' => array() ); $parts = array(); @@ -449,18 +443,10 @@ class IMP_Contents 'render_info' => false, 'render_inline' => false, 'size' => null, - 'strip' => null, - 'textbody' => null + 'strip' => null ); $part = &$parts[$mime_id]; - if (($mask & self::SUMMARY_TEXTBODY) && - is_null($info['textbody']) && - (strpos($mime_type, 'text/') === 0) && - (intval($mime_id) == 1)) { - $info['textbody'] = $mime_id; - } - $mime_part = $this->getMIMEPart($mime_id, array('nocontents' => true, 'nodecode' => true)); /* If this is an attachment that has no specific MIME type info, @@ -473,24 +459,22 @@ class IMP_Contents $part['type'] = $mime_type; /* Determine if part can be viewed inline or has viewable info. */ - if (($mask & self::SUMMARY_RENDER) && - (is_null($last_id) || - (($last_id !== 0) && - (strpos($mime_id, $last_id) !== 0)))) { - $last_id = null; + if ($mask & self::SUMMARY_RENDER) { $viewer = Horde_Mime_Viewer::factory($mime_type); if ($viewer->canRender('inline') && ($mime_part->getDisposition() == 'inline')) { $part['render_inline'] = true; $info['render'][$mime_id] = 'inline'; - $last_id = $mime_id; - } elseif (is_null($last_id) && $viewer->canRender('info')) { + } elseif ($viewer->canRender('info')) { $part['render_info'] = true; $info['render'][$mime_id] = 'info'; } } + /* Is this part an attachment? */ + $is_atc = $this->isAttachment($mime_part); + /* Get bytes/size information. */ if (($mask & self::SUMMARY_BYTES) || $download_zip || @@ -522,13 +506,16 @@ class IMP_Contents } if ($mask & self::SUMMARY_DESCRIP_LINK) { - $part['description'] = $this->linkViewJS($mime_part, 'view_attach', htmlspecialchars($description), array('jstext' => sprintf(_("View %s [%s]"), $description, $mime_type), 'params' => $param_array)); + $part['description'] = $is_atc + ? $this->linkViewJS($mime_part, 'view_attach', htmlspecialchars($description), array('jstext' => sprintf(_("View %s [%s]"), $description, $mime_type), 'params' => $param_array)) + : htmlspecialchars($description); } elseif ($mask & self::SUMMARY_DESCRIP_NOLINK) { $part['description'] = htmlspecialchars($description); } /* Download column. */ - if (($mask & self::SUMMARY_DOWNLOAD) && + if ($is_atc && + ($mask & self::SUMMARY_DOWNLOAD) && (is_null($part['bytes']) || $part['bytes'])) { $part['download'] = $this->linkView($mime_part, 'download_attach', '', array('class' => 'downloadAtc', 'dload' => true, 'jstext' => sprintf(_("Download %s"), $description))); $info['has']['download'] = true; @@ -536,7 +523,8 @@ class IMP_Contents /* Display the compressed download link only if size is greater * than 200 KB. */ - if ($download_zip && + if ($is_atc && + $download_zip && ($part['bytes'] > 204800) && !in_array($mime_type, array('application/zip', 'application/x-zip-compressed'))) { $part['download_zip'] = $this->linkView($mime_part, 'download_attach', null, array('class' => 'downloadZipAtc', 'dload' => true, 'jstext' => sprintf(_("Download %s in .zip Format"), $mime_part->getDescription(true)), 'params' => array('zip' => 1))); @@ -563,10 +551,8 @@ class IMP_Contents $info['has']['strip'] = true; } - if ($mask && self::SUMMARY_DOWNLOAD_ALL) { - if ($download = $this->isAttachment($mime_part)) { - $info['download_all'][] = $mime_id; - } + if ($is_atc && ($mask && self::SUMMARY_DOWNLOAD_ALL)) { + $info['download_all'][] = $mime_id; } } @@ -681,19 +667,15 @@ class IMP_Contents */ public function isAttachment($mime_part) { - $type = $mime_part->getType(); - switch ($mime_part->getPrimaryType()) { case 'message': - return ($type == 'message/rfc822'); + return ($mime_part->getType() == 'message/rfc822'); case 'multipart': return false; default: - return (($type != 'application/applefile') && - ($type != 'application/x-pkcs7-signature') && - ($type != 'application/pkcs7-signature')); + return true; } } diff --git a/imp/lib/Mime/Viewer/alternative.php b/imp/lib/Mime/Viewer/alternative.php index 83844e809..eebc3f328 100644 --- a/imp/lib/Mime/Viewer/alternative.php +++ b/imp/lib/Mime/Viewer/alternative.php @@ -14,115 +14,81 @@ class IMP_Horde_Mime_Viewer_alternative extends Horde_Mime_Viewer_Driver { /** - * The content-type of the preferred part. - * Default: application/octet-stream + * Can this driver render various views? * - * @var string + * @var boolean */ - protected $_contentType = 'application/octet-stream'; + protected $_capability = array( + 'embedded' => false, + 'full' => false, + 'info' => false, + 'inline' => true, + ); /** - * Render out the currently set contents. + * Return the rendered inline version of the Horde_Mime_Part object. * - * @param array $params An array with a reference to a MIME_Contents - * object. - * - * @return string The rendered text in HTML. + * @return array See Horde_Mime_Viewer_Driver::render(). This driver + * returns an extra parameter: 'summary_id', which + * identifies the MIME ID that should be used for the + * summary information. */ - public function render($params) + protected function _renderInline() { - $contents = &$params[0]; - - $display_id = null; - $summaryList = array(); - $text = ''; - - /* Look for a displayable part. - * RFC 2046: We show the LAST choice that can be displayed inline. */ - $partList = $this->mime_part->getParts(); - foreach ($partList as $part) { - if ($contents->canDisplayInline($part)) { - $text = $contents->renderMIMEPart($part); - $this->_contentType = $part->getType(); - $display_id = $part->getMIMEId(); - } - } + $display_id = $last_id = null; - /* Show links to alternative parts. */ - if (($text === null) || (count($partList) > 1)) { - if ($text === null) { - $text = '' . _("There are no alternative parts that can be displayed.") . ''; - } + $subparts = $this->_mimepart->contentTypeMap(); + unset($subparts[key($subparts)]); - /* Generate the list of summaries to use. */ - foreach ($partList as $part) { - $id = $part->getMIMEId(); - if ($id && $id != $display_id) { - $summary = $contents->partSummary($part); - /* We don't want to show the MIME ID for alt parts. */ - if (!empty($summary)) { - array_splice($summary, 1, 1); - $summaryList[] = $summary; - } - } - } + /* Look for a displayable part. RFC 2046: show the LAST choice that + * can be displayed inline. */ + foreach ($subparts as $mime_id => $mime_type) { + if (is_null($last_id) || (strpos($mime_id, $last_id) !== 0)) { + $last_id = null; + $viewer = Horde_Mime_Viewer::factory($mime_type); - /* Make sure there is at least one summary before showing the - * alternative parts. */ - $alternative_display = $GLOBALS['prefs']->getValue('alternative_display'); - if (!empty($summaryList) && - !$this->viewAsAttachment() && - $alternative_display != 'none') { - $status_array = array(); - $status = _("Alternative parts for this section:"); - if ($contents->showSummaryLinks()) { - require_once 'Horde/Help.php'; - $status .= '  ' . Help::link('imp', 'alternative-msg'); - } - $status_array[] = $status; - $status = ''; - foreach ($summaryList as $summary) { - $status .= ''; - foreach ($summary as $val) { - if (!empty($val)) { - $status .= "\n"; - } + if ($viewer->canRender('inline')) { + $mime_part = $this->_params['contents']->getMIMEPart($mime_id, array('nocontents' => true, 'nodecode' => true)); + if ($mime_part->getDisposition() == 'inline') { + $display_id = $last_id = $mime_id; } - $status .= "\n"; - } - $status .= '
$val 
'; - $status_array[] = $status; - $status_msg = $this->formatStatusMsg($status_array, Horde::img('mime/binary.png', _("Multipart/alternative"), null, $GLOBALS['registry']->getImageDir('horde')), false); - switch ($alternative_display) { - case 'above': - $text = $status_msg . $text; - break; - - case 'below': - $text .= $status_msg; - break; } } } - /* Remove attachment information for the displayed part if we - * can. */ - if (is_callable(array($contents, 'removeAtcEntry'))) { - $contents->removeAtcEntry($this->mime_part->getMIMEId()); + if (is_null($display_id)) { + return array( + 'status' => array( + 'text' => _("There are no alternative parts that can be displayed inline."), + 'type' => 'info' + ) + ); } - return $text; - } + $render_data = $this->_params['contents']->renderMIMEPart($display_id, 'inline'); - /** - * Return the content-type. - * - * @return string The content-type of the message. - * Returns 'application/octet-stream' until actual - * content type of the message can be determined. - */ - public function getType() - { - return $this->_contentType; + /* Make sure there is at least one summary before showing the + * alternative parts. */ + $alt_display = $GLOBALS['prefs']->getValue('alternative_display'); + if ($alt_display != 'none') { + // TODO + //$icon = Horde::img('mime/binary.png', _("Multipart/alternative"), null, $GLOBALS['registry']->getImageDir('horde')); + switch ($alt_display) { + case 'above': + //$text = $status_msg . $text; + break; + + case 'below': + //$text .= $status_msg; + break; + } + } + + return array( + 'data' => $render_data['data'], + 'ids' => array_keys($subparts), + 'status' => array(), + 'summary_id' => isset($render_data['summary_id']) ? $render_data['summary_id'] : $display_id + ); } } diff --git a/imp/message.php b/imp/message.php index d6474684c..5e1b558cf 100644 --- a/imp/message.php +++ b/imp/message.php @@ -251,8 +251,7 @@ if (is_a($imp_contents, 'PEAR_Error')) { $contents_mask = IMP_Contents::SUMMARY_RENDER | IMP_Contents::SUMMARY_BYTES | IMP_Contents::SUMMARY_SIZE | - IMP_Contents::SUMMARY_ICON | - IMP_Contents::SUMMARY_TEXTBODY; + IMP_Contents::SUMMARY_ICON; if ($printer_friendly) { $contents_mask |= IMP_Contents::SUMMARY_DESCRIP_NOLINK; } else { @@ -651,19 +650,7 @@ foreach ($all_list_headers as $head => $val) { $hdrs[] = array('name' => $list_headers_lookup[$head], 'val' => $val, 'i' => (++$i % 2)); } -/* Show attachment information in headers? */ -$download_all = $show_atc = false; -reset($summary['parts']); -if (!empty($summary['parts']) && - ((count($summary['parts']) > 1) || - (key($summary['parts']) != $summary['info']['textbody']))) { - $atc_display = $prefs->getValue('attachment_display'); - $show_atc = (($atc_display == 'list') || ($atc_display == 'both')); - $download_all = (empty($summary['info']['download_all']) || !$printer_friendly) - ? false - : $imp_contents->urlView($imp_contents->getMIMEMessage(), 'download_all', array('params' => array('download_ids' => serialize($summary['info']['download_all'])))); -} - +/* Determine the fields that will appear in the MIME info entries. */ $part_info = array('icon', 'description', 'type', 'size'); foreach (array('download', 'download_zip', 'img_save', 'strip') as $val) { if (isset($summary['info']['has'][$val])) { @@ -671,19 +658,67 @@ foreach (array('download', 'download_zip', 'img_save', 'strip') as $val) { } } +/* Build body text. This needs to be done before we build the attachment list + * that lives in the header. */ +$display_ids = $inline_ids = array(); +$msgtext = ''; +foreach ($summary['info']['render'] as $mime_id => $type) { + if (in_array($mime_id, $inline_ids)) { + continue; + } + + $render_part = $imp_contents->renderMIMEPart($mime_id, $type); + $inline_ids = array_merge($inline_ids, $render_part['ids']); + + $summary_id = isset($render_part['summary_id']) + ? $render_part['summary_id'] + : $mime_id; + $display_ids[] = $summary_id; + + $ptr = $summary['parts'][$summary_id]; + $tmp_part = $tmp_status = array(); + + foreach ($part_info as $val) { + $tmp_part[] = $ptr[$val]; + } + + foreach ($render_part['status'] as $val) { + // TODO: status msgs. + $tmp_status[] = $render_part['status']['text']; + } + + $msgtext .= '' . + implode(' ', $tmp_part) . + '' . + implode(' ', $tmp_status) . + $render_part['data']; +} + +/* Show attachment information in headers? */ +$show_atc = false; +$atc_parts = array_diff($summary['info']['download_all'], $display_ids); +if (!empty($atc_parts)) { + $atc_display = $prefs->getValue('attachment_display'); + $show_atc = (($atc_display == 'list') || ($atc_display == 'both')); +} + +/* Show the download all link? */ +$download_all = (!$printer_friendly && (count($atc_parts) || (count($display_ids) > 2))) + ? $imp_contents->urlView($imp_contents->getMIMEMessage(), 'download_all', array('params' => array('download_ids' => serialize($summary['info']['download_all'])))) + : false; + if ($show_atc || $download_all) { $val = ''; if ($show_atc) { $tmp = array(); - foreach ($summary['parts'] as $key => $val) { - if ($key != $summary['info']['textbody']) { - $tmp[] = ''; - foreach ($part_info as $val2) { - $tmp[] = '' . $val[$val2] . ''; - } - $tmp[] = ''; + foreach ($atc_parts as $id) { + $tmp[] = ''; + $ptr = $summary['parts'][$id]; + foreach ($part_info as $val) { + $tmp[] = '' . $ptr[$val] . ''; } + $tmp[] = ''; } $val = '' . implode('', $tmp) . '
'; } @@ -704,31 +739,7 @@ if ($printer_friendly && !empty($conf['print']['add_printedby'])) { } $m_template->set('headers', $hdrs); - -/* Build body text. */ -$msgtext = ''; -foreach ($summary['info']['render'] as $mime_id => $type) { - $render_part = $imp_contents->renderMIMEPart($mime_id, $type); - $ptr = $summary['parts'][$mime_id]; - $tmp_part = $tmp_status = array(); - - foreach ($part_info as $val) { - $tmp[] = $ptr[$val]; - } - - foreach ($render_part['status'] as $val) { - // TODO: status msgs. - $tmp_status[] = $render_part['status']['text']; - } - - $msgtext .= '' . - implode(' ', $tmp) . - '' . - implode(' ', $tmp_status) . - $render_part['data']; -} $m_template->set('msgtext', $msgtext); - echo $m_template->fetch(IMP_TEMPLATES . '/message/message.html'); if (!$printer_friendly) { -- 2.11.0