From 150f95bf869362429ec12a10ff572a337407a92d Mon Sep 17 00:00:00 2001 From: Michael M Slusarz Date: Mon, 10 Nov 2008 20:42:57 -0700 Subject: [PATCH] Message display tweaking. IMP 5 now can successfully display simple messages containing text/plain and text/html data. Playing around with the formatting a bit, but my desire is to *always* show the Mime part summary for every part we can display inline and *never* show inline parts in the attachment list. This is important because there is no other way to strip/download/display in a new window the parts that are shown inline. This goes back to the way we used to display things long ago (IMP 3), but that is probably the better way to do this. However, this has much work that can be done to it - for now, just need to be able to display the parts so I can continue implementing other things. --- imp/lib/Contents.php | 80 +++++++++++++++++---------------- imp/message.php | 88 ++++++++++++++++++++++++++----------- imp/templates/message/message.html | 4 +- imp/themes/graphics/delete.png | Bin 0 -> 788 bytes imp/themes/graphics/download.png | Bin 0 -> 190 bytes imp/themes/graphics/gallery.png | Bin 0 -> 552 bytes imp/themes/screen.css | 53 ++++++++++++++++++++++ 7 files changed, 159 insertions(+), 66 deletions(-) create mode 100644 imp/themes/graphics/delete.png create mode 100644 imp/themes/graphics/download.png create mode 100644 imp/themes/graphics/gallery.png diff --git a/imp/lib/Contents.php b/imp/lib/Contents.php index d67299984..452953fec 100644 --- a/imp/lib/Contents.php +++ b/imp/lib/Contents.php @@ -25,6 +25,7 @@ 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. @@ -321,11 +322,11 @@ class IMP_Contents */ public function findBody($subtype = null) { - foreach ($this->_message->contentTypeMap() as $key => $val) { - if ((strpos($val, 'text/') === 0) && - (intval($key) == 1) && - (is_null($subtype) || (substr($val, 5) == $subtype))) { - return $key; + foreach ($this->_message->contentTypeMap() as $mime_id => $mime_type) { + if ((strpos($mime_type, 'text/') === 0) && + (intval($mime_id) == 1) && + (is_null($subtype) || (substr($mime_type, 5) == $subtype))) { + return $mime_id; } } @@ -410,6 +411,9 @@ 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,24 +425,15 @@ class IMP_Contents $info = array( 'download_all' => array(), 'has' => array(), - 'render' => array() + 'render' => array(), + 'textbody' => null ); $parts = array(); // Cache some settings before we enter the loop. $download_zip = (($mask & self::SUMMARY_DOWNLOAD_ZIP) && Util::extensionExists('zlib')); - if ($download_zip) { - $zip_img = Horde::img('compressed.png', _("Download in .zip Format"), null, $GLOBALS['registry']->getImageDir('horde') . '/mime'); - } - - if (($mask && self::SUMMARY_IMAGE_SAVE) && - $GLOBALS['registry']->hasMethod('images/selectGalleries') && - ($image_app = $GLOBALS['registry']->hasMethod('images/saveImage'))) { - $image_img = '' . _('; - } else { - $image_img = null; - } - + $img_save = (($mask && self::SUMMARY_IMAGE_SAVE) && + $GLOBALS['registry']->hasMethod('images/selectGalleries')); if ($mask && self::SUMMARY_STRIP_LINK) { $message_token = IMP::getRequestToken('imp.impcontents'); } @@ -454,10 +449,18 @@ class IMP_Contents 'render_info' => false, 'render_inline' => false, 'size' => null, - 'strip' => null + 'strip' => null, + 'textbody' => 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, @@ -510,7 +513,7 @@ class IMP_Contents } /* Get part's icon. */ - $part['icon'] = ($mask & self::SUMMARY_ICON) ? Horde::img(Horde_Mime_Viewer::getIcon($mime_type), '', array('title' => $mime_type)) : null; + $part['icon'] = ($mask & self::SUMMARY_ICON) ? Horde::img(Horde_Mime_Viewer::getIcon($mime_type), '', array('title' => $mime_type), '') : null; /* Get part's description. */ $description = $mime_part->getDescription(true); @@ -527,7 +530,7 @@ class IMP_Contents /* Download column. */ if (($mask & self::SUMMARY_DOWNLOAD) && (is_null($part['bytes']) || $part['bytes'])) { - $part['download'] = $this->linkView($mime_part, 'download_attach', '', array('class' => 'download', 'dload' => true, 'jstext' => sprintf(_("Download %s"), $description))); + $part['download'] = $this->linkView($mime_part, 'download_attach', '', array('class' => 'downloadAtc', 'dload' => true, 'jstext' => sprintf(_("Download %s"), $description))); $info['has']['download'] = true; } @@ -536,20 +539,19 @@ class IMP_Contents if ($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', $zip_img, array('dload' => true, 'jstext' => sprintf(_("Download %s in .zip Format"), $mime_part->getDescription(true)), 'params' => array('zip' => 1))); + $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))); $info['has']['download_zip'] = true; } /* Display the image save link if the required registry calls are * present. */ - if (!is_null($image_img) && - ($mime_part->getPrimaryType() == 'image')) { + if ($img_save && ($mime_part->getPrimaryType() == 'image')) { if (empty($info['has']['img_save'])) { Horde::addScriptFile('prototype.js', 'horde', true); Horde::addScriptFile('popup.js', 'imp', true); $info['has']['img_save'] = true; } - $part['img_save'] = Horde::link('#', _("Save Image in Gallery"), null, null, IMP::popupIMPString('saveimage.php', array('index' => ($this->_index . IMP::IDX_SEP . $this->_mailbox), 'id' => $mime_id), 450, 200) . "return false;") . $image_img . ''; + $part['img_save'] = Horde::link('#', _("Save Image in Gallery"), 'saveImgAtc', null, IMP::popupIMPString('saveimage.php', array('index' => ($this->_index . IMP::IDX_SEP . $this->_mailbox), 'id' => $mime_id), 450, 200) . "return false;") . ''; } /* Strip the Attachment? */ @@ -557,12 +559,12 @@ class IMP_Contents // TODO: No stripping of RFC 822 parts. $url = Util::removeParameter(Horde::selfUrl(true), array('actionID', 'imapid', 'index')); $url = Util::addParameter($url, array('actionID' => 'strip_attachment', 'imapid' => $mime_id, 'index' => $this->_index, 'message_token' => $message_token)); - $part['strip'] = Horde::link($url, _("Strip Attachment"), null, null, "return window.confirm('" . addslashes(_("Are you sure you wish to PERMANENTLY delete this attachment?")) . "');") . Horde::img('delete.png', _("Strip Attachment"), null, $GLOBALS['registry']->getImageDir('horde')) . ''; + $part['strip'] = Horde::link($url, _("Strip Attachment"), 'stripAtc', null, "return window.confirm('" . addslashes(_("Are you sure you wish to PERMANENTLY delete this attachment?")) . "');") . ''; $info['has']['strip'] = true; } if ($mask && self::SUMMARY_DOWNLOAD_ALL) { - if ($download = $this->isDownloadable($mime_part)) { + if ($download = $this->isAttachment($mime_part)) { $info['download_all'][] = $mime_id; } } @@ -668,27 +670,31 @@ class IMP_Contents } /** - * Determines if a MIME part is downloadable. + * Determines if a MIME part is an attachment. + * For IMP's purposes, an attachment is any MIME part that can be + * downloaded by itself (i.e. all the data needed to view the part is + * contained within the download data). * * @param Horde_Mime_Part $mime_part The MIME part object. * - * @return boolean True if downloadable. + * @return boolean True if an attachment. */ - public function isDownloadable($mime_part) + public function isAttachment($mime_part) { $type = $mime_part->getType(); - $ptype = $mime_part->getPrimaryType(); - if ($ptype == 'message') { + switch ($mime_part->getPrimaryType()) { + case 'message': return ($type == 'message/rfc822'); - } - return ((($mime_part->getDisposition() == 'attachment') || - $mime_part->getContentTypeParameter('name')) && - ($ptype != 'multipart') && - ($type != 'application/applefile') && + case 'multipart': + return false; + + default: + return (($type != 'application/applefile') && ($type != 'application/x-pkcs7-signature') && ($type != 'application/pkcs7-signature')); + } } /** diff --git a/imp/message.php b/imp/message.php index c63c00d00..d6474684c 100644 --- a/imp/message.php +++ b/imp/message.php @@ -251,7 +251,8 @@ 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_ICON | + IMP_Contents::SUMMARY_TEXTBODY; if ($printer_friendly) { $contents_mask |= IMP_Contents::SUMMARY_DESCRIP_NOLINK; } else { @@ -631,11 +632,6 @@ if (!$printer_friendly) { echo $a_template->fetch(IMP_TEMPLATES . '/message/navbar_actions.html'); } -$atc_display = $prefs->getValue('attachment_display'); -$show_parts = (($atc_display == 'list') || ($atc_display == 'both')); -$downloadall_link = empty($summary['info']['download_all']) - ? false - : $imp_contents->urlView($imp_contents->getMIMEMessage(), 'download_all', array('params' => array('download_ids' => serialize($summary['info']['download_all'])))); $hdrs = array(); $i = 1; @@ -655,35 +651,52 @@ 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']) && - ($show_parts || ($downloadall_link && !$printer_friendly))) { + ((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'])))); +} + +$part_info = array('icon', 'description', 'type', 'size'); +foreach (array('download', 'download_zip', 'img_save', 'strip') as $val) { + if (isset($summary['info']['has'][$val])) { + $part_info[] = $val; + } +} + +if ($show_atc || $download_all) { $val = ''; - if ($show_parts) { - $part_info = array('icon', 'id', 'description', 'type', 'size'); - foreach (array('download', 'download_zip', 'img_save', 'strip') as $val) { - if (isset($summary['info']['has'][$val])) { - $part_info[] = $val; - } - } - $tmp = array(''); + + if ($show_atc) { + $tmp = array(); foreach ($summary['parts'] as $key => $val) { - $tmp[] = ''; - foreach ($part_info as $val2) { - $tmp[] = ''; + if ($key != $summary['info']['textbody']) { + $tmp[] = ''; + foreach ($part_info as $val2) { + $tmp[] = ''; + } + $tmp[] = ''; } - $tmp[] = ''; } - $tmp[] = '
' . $val[$val2] . '
' . $val[$val2] . '
'; - $val = implode('', $tmp); + $val = '' . implode('', $tmp) . '
'; } - if ($downloadall_link && !$printer_friendly) { - $val .= Horde::link($downloadall_link, _("Download All Attachments (in .zip file)")) . _("Download All Attachments (in .zip file)") . ' ' . Horde::img('compressed.png', _("Download All Attachments (in .zip file)"), '', $registry->getImageDir('horde') . '/mime') . ''; + + if ($download_all) { + $val .= Horde::link($download_all, _("Download All Attachments (in .zip file)")) . _("Download All Attachments (in .zip file)") . ' ' . Horde::img('compressed.png', _("Download All Attachments (in .zip file)"), '', $registry->getImageDir('horde') . '/mime') . ''; if ($prefs->getValue('strip_attachments')) { $url = Util::addParameter(Util::removeParameter(Horde::selfUrl(true), array('actionID')), array('actionID' => 'strip_all', 'message_token' => $message_token)); $val .= '
' . Horde::link($url, _("Strip All Attachments"), null, null, "return window.confirm('" . addslashes(_("Are you sure you wish to PERMANENTLY delete all attachments?")) . "');") . _("Strip All Attachments") . ' ' . Horde::img('delete.png', _("Strip Attachments"), null, $registry->getImageDir('horde')) . ''; } } - $hdrs[] = array('name' => _("Part(s)"), 'val' => $val, 'i' => (++$i % 2)); + + $hdrs[] = array('name' => _("Attachment(s)"), 'val' => $val, 'i' => (++$i % 2)); } if ($printer_friendly && !empty($conf['print']['add_printedby'])) { @@ -691,8 +704,31 @@ if ($printer_friendly && !empty($conf['print']['add_printedby'])) { } $m_template->set('headers', $hdrs); -// TODO -//$m_template->set('msgtext', reset($inline_parts)); + +/* 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) { diff --git a/imp/templates/message/message.html b/imp/templates/message/message.html index fac4278f5..b2b641fad 100644 --- a/imp/templates/message/message.html +++ b/imp/templates/message/message.html @@ -10,7 +10,5 @@
- - -
+
diff --git a/imp/themes/graphics/delete.png b/imp/themes/graphics/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..f3076bc9f54f0458c717d8a190bb7d1ccc17ac4d GIT binary patch literal 788 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GXl47#jk7LR^7d4h{|h0U#2PkN_eH zMMWS|)YJqbO+!OXOG_YWXlV&VmQGHFPEM9yUO& z15q}ROwP_uE(W6Ff-9^YKH#|EiJ`8JwR05)6+6#O3R!%K-4p5&XlEd zdX_E)qA5$4&RM&5%G$Mawr-uXck7&`YnQHFyL9W;wR^V$$*p^j0pZeP$AD<fdF|f4d(WSrd;k30^XJ#z1JV0?-``*R{{G(k_s_q72cq}? zfoO1m)>tz@F4s^LbxQGm z8kBeV*`-CT0s8{tW4}%*F5C9MPXF9Z#=xM6#YZP-G^I5B;d!5^t-M)NQZQ73ci4W}GTz*w?k1u$}o_&R^|8lR133XIdzPoGdK6$r}&-7`l zV)8FcXOYsM7StdX-m20jDzU03Vdr$+oob;fvm7=Qo4O14>^gKW=&|%am}A vF!5vq3&ClhpGWv6s&<{3=grB?a8y3zfc3fui9h!Oy~E(?>gTe~DWM4fIt%bm literal 0 HcmV?d00001 diff --git a/imp/themes/graphics/download.png b/imp/themes/graphics/download.png new file mode 100644 index 0000000000000000000000000000000000000000..de62aaeb06f26c0ea59b589f831bb675353b9fbe GIT binary patch literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!bbwEYYXgwM!0?}ep}xNUz<~q* z|NmzI3jJpQGUk_T4FJkoR>|3vZpT?t*A-}YYX>L csh+9+c@oP>-Ph(Pfrc`8y85}Sb4q9e0BzVvKL7v# literal 0 HcmV?d00001 diff --git a/imp/themes/graphics/gallery.png b/imp/themes/graphics/gallery.png new file mode 100644 index 0000000000000000000000000000000000000000..f05b02958e982aa07e48ef3340d90859a9e970b6 GIT binary patch literal 552 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbMf{{Wv5S0Fuc(Y9I3w->d|2`Qgd zJZ)!c^P;+W`|`S$l}}vVyZU7R$|IB4oot-3Va}Gb^R}HUY?{1y*Tq%)uWUSWeaFe$ zY3<88mK|V&l?_n*I4J!hx1qS~XE?-%bn-M?z@%#8=QdHKScLc^QFQl=)Q zO-oLjnv^mrA*?hd0 zdLlD=VnRzjBddH<+QZVjBGcL^aZs`QR5@rW$)h%NPq$#cE+=t4rVo07WlohL_L zy+85#-El=l0d{t_fB)_~8gt6a2(>m8=&Ok6sw+6D@q6k^0zH1@>@7?E>T)29u_VYZ zn8D%MjWiG^$=lt9p@UV{1IXbl@Q5sCVBi)8VMc~ob0mO*>?NMQuIx8hSp^tW-Y(){ z1PU$kba4!kxSX8ezIP*6E>%i-#& ztH)h0U(lW*tnpy^`ekdAQkLcAtXnO9hFfIA){wAGTgmlPRrigCCVuN1$bs^A-C m;H$tmL5+8YTFyOZRtDu;+E)w1r*8$imci52&t;ucLK6UGIMu%Z literal 0 HcmV?d00001 diff --git a/imp/themes/screen.css b/imp/themes/screen.css index 89e21b7c9..6ccc0ff0f 100644 --- a/imp/themes/screen.css +++ b/imp/themes/screen.css @@ -129,6 +129,9 @@ ul.msgactions, ul.msgactions ul { background: #fff; padding: 8px; } +.messageBody div.fixed { + padding-top: 8px; +} /* Search page styling. */ form#search div { @@ -382,3 +385,53 @@ ul.nav-audio { .largeaddrlist:hover { text-decoration: underline; } + +/* MIME styles. */ +.mimeStatusMessage, .mimeStatusWarning, .mimeHeaders, .mimePartInfo { + padding: 1px; + margin-bottom: 2px; + font-size: 90%; +} +.mimeStatusMessage { + color: #000; + background: #ffc; + border: 1px solid #fff760; + width: 100%; +} +.mimeStatusWarning { + border: 1px solid #800; + background: #e81222; + color: #fff; + width: 100%; +} +.mimeHeaders { + border: 1px solid #ccc; + background: #f9f9f9; + width: 100%; + font-family: "Lucida Console",Courier,"Courier New"; +} +.mimePartInfo { + border: 1px solid #ccc; + background: #f9f9f9; + padding-top: 4px; + padding-bottom: 3px; +} +.mimePartInfo img { + vertical-align: bottom; +} +.downloadAtc { + padding: 2px 20px 2px 0; + background: transparent url("graphics/download.png") center right no-repeat; +} +.downloadZipAtc { + padding: 2px 20px 2px 0; + background: transparent url("graphics/mime/compressed.png") center right no-repeat; +} +.saveImgAtc { + padding: 2px 20px 2px 0; + background: transparent url("graphics/gallery.png") center right no-repeat; +} +.stripAtc { + padding: 2px 20px 2px 0; + background: transparent url("graphics/delete.png") center right no-repeat; +} -- 2.11.0