/** * Render out the currently set contents. * * @param boolean $inline Are we viewing inline? * * @return array See self::render(). */ protected function _IMPrender($inline) { $related_id = $this->_mimepart->getMimeId(); $used = array($related_id); if (!($id = $this->_init($inline))) { return array(); } $render = $this->getConfigParam('imp_contents')->renderMIMEPart($id, $inline ? IMP_Contents::RENDER_INLINE : IMP_Contents::RENDER_FULL); if (!$inline) { foreach (array_keys($render) as $key) { if (!is_null($render[$key])) { return array($related_id => $render[$key]); } } return null; } $data_id = null; $ret = array(); foreach ($this->_mimepart->partIterator(false) as $val) { $ret[$val->getMimeId()] = null; } foreach (array_keys($render) as $val) { $ret[$val] = $render[$val]; if ($ret[$val]) { $data_id = $val; } } if (!is_null($data_id)) { $this->_mimepart->setMetadata('viewable_part', $data_id); /* We want the inline display to show multipart/related vs. the * viewable MIME part. This is because a multipart/related part * is not downloadable and clicking on the MIME part may not * produce the desired result in the full display (i.e. HTML parts * with related images). */ if (strcmp($data_id, $related_id) !== 0) { $ret[$related_id] = $ret[$data_id]; $ret[$data_id] = null; } } /* Fix for broken messages that don't refer to a related CID part * within the base part. */ if ($cids_used = $this->_mimepart->getMetadata('related_cids_used')) { $used = array_merge($used, $cids_used); } $id_ob = new Horde_Mime_Id($id); foreach (array_diff(array_keys($ret), $used) as $val) { if (strcmp($val, $id) !== 0 && !$id_ob->isChild($val)) { $summary = $this->getConfigParam('imp_contents')->getSummary($val, IMP_Contents::SUMMARY_SIZE | IMP_Contents::SUMMARY_ICON | IMP_Contents::SUMMARY_DESCRIP_LINK | IMP_Contents::SUMMARY_DOWNLOAD); $status = new IMP_Mime_Status_RenderIssue($this->_mimepart, array(_("This part contains an attachment that can not be displayed within this part:"), implode(' ', array($summary['icon'], $summary['description'], $summary['size'], $summary['download'])))); $status->action($status::WARNING); if (isset($ret[$related_id]['status'])) { if (!is_array($ret[$related_id]['status'])) { $ret[$related_id]['status'] = array($ret[$related_id]['status']); } } else { $ret[$related_id]['status'] = array(); } $ret[$related_id]['status'][] = $status; } } return $ret; }
/** * Render out the currently set contents. * * @param boolean $inline Are we viewing inline? * * @return array Two elements: html and status. */ protected function _IMPrender($inline) { global $injector, $registry; $data = $this->_mimepart->getContents(); $view = $registry->getView(); $contents = $this->getConfigParam('imp_contents'); $convert_text = $injector->getInstance('Horde_Variables')->convert_text; /* Don't do IMP DOM processing if converting to text. */ $this->_imptmp = array(); if ($inline && !$convert_text) { $this->_imptmp += array('cid' => null, 'cid_used' => array(), 'cssblock' => false, 'cssbroken' => false, 'imgblock' => false, 'imgbroken' => false, 'inline' => $inline, 'style' => array()); } /* Search for inlined data that we can display (multipart/related * parts) - see RFC 2392. */ if ($related_part = $contents->findMimeType($this->_mimepart->getMimeId(), 'multipart/related')) { $this->_imptmp['cid'] = $related_part->getMetadata('related_ob'); } /* Sanitize the HTML. */ $data = $this->_cleanHTML($data, array('noprefetch' => $inline, 'phishing' => $inline)); if (!empty($this->_imptmp['style'])) { $this->_processDomDocument($data->dom); } if ($inline) { $charset = 'UTF-8'; $data = $data->returnHtml(array('charset' => $charset, 'metacharset' => true)); } else { $charset = $this->_mimepart->getCharset(); $data = $data->returnHtml(); } $status = array(); if ($this->_phishWarn) { $tmp = new IMP_Mime_Status($this->_mimepart, array(_("This message may not be from whom it claims to be."), _("Beware of following any links in it or of providing the sender with any personal information."), _("The links that caused this warning have this background color:") . ' <span style="' . $this->_phishCss . '">' . _("EXAMPLE LINK") . '</span>')); $tmp->action($tmp::WARNING); $status[] = $tmp; } /* We are done processing if converting to text. */ if ($convert_text) { $data = $this->_textFilter($data, 'Html2text', array('wrap' => false)); // Filter bad language. return array('data' => IMP::filterText($data), 'type' => 'text/plain; charset=' . $charset); } if ($inline) { switch ($view) { case $registry::VIEW_SMARTMOBILE: if ($this->_imptmp['imgblock']) { $tmp_txt = _("Show images..."); } elseif ($this->_imptmp['cssblock']) { $tmp_txt = _("Load message styling..."); } else { $tmp_txt = null; } if (!is_null($tmp_txt)) { $tmp = new IMP_Mime_Status($this->_mimepart, array('<a href="#unblock-image" data-role="button" data-theme="e">' . $tmp_txt . '</a>')); $tmp->views = array($view); $status[] = $tmp; } break; default: $attr = array('muid' => strval($contents->getIndicesOb())); if (!$injector->getInstance('IMP_Prefs_Special_ImageReplacement')->canAddToSafeAddrList() || ($from = $contents->getHeader()->getHeader('from')) && $injector->getInstance('IMP_Identity')->hasAddress($from->getAddressList(true))) { $attr['noUnblockImageAdd'] = 1; } $link = $text = null; if ($this->_imptmp['imgblock']) { $text = _("Images have been blocked in this message part."); $link = _("Show Images?"); } elseif ($this->_imptmp['cssblock']) { $text = _("Message styling has been suppressed in this message part since the style data lives on a remote server."); $link = _("Load Styling?"); } if (!is_null($link)) { $tmp = new IMP_Mime_Status($this->_mimepart, $text); $tmp->addMimeAction('unblockImageLink', $link, $attr); $tmp->icon('mime/image.png'); $status[] = $tmp; } if ($this->_imptmp['cssbroken']) { $tmp = new IMP_Mime_Status_RenderIssue($this->_mimepart, array(_("This message contains corrupt styling data so the message contents may not appear correctly below."), $contents->linkViewJS($this->_mimepart, 'view_attach', _("Click to view HTML data in new window; it is possible this will allow you to view the message correctly.")))); $tmp->icon('mime/image.png'); $status[] = $tmp; } if ($this->_imptmp['imgbroken']) { $tmp = new IMP_Mime_Status_RenderIssue($this->_mimepart, array(_("This message contains images that cannot be loaded."))); $tmp->icon('mime/image.png'); $status[] = $tmp; } break; } } /* Add used CID information. */ if ($inline && !empty($this->_imptmp['cid'])) { $related_part->setMetadata('related_cids_used', $this->_imptmp['cid_used']); } return array('data' => $data, 'status' => $status, 'type' => 'text/html; charset=' . $charset); }
/** * Render the object. * * @param boolean $inline Viewing inline? * * @return array See parent::render(). */ protected function _impRender($inline) { global $injector, $prefs, $registry; $contents = $this->getConfigParam('imp_contents'); $cache = $contents->getViewCache(); $mime_id = $this->_mimepart->getMimeId(); if (isset($cache->plain[$mime_id])) { return array($mime_id => null); } // Trim extra whitespace in the text. $charset = $this->_mimepart->getCharset(); $text = trim($this->_mimepart->getContents()); if ($text == '') { return array($mime_id => array('data' => '', 'type' => 'text/html; charset=' . $charset)); } // Convert to the local charset. if ($inline) { $text = Horde_String::convertCharset($text, $charset, 'UTF-8'); $charset = $this->getConfigParam('charset'); } $type = 'text/html; charset=' . $charset; // Check for 'flowed' text data. if ($this->_mimepart->getContentTypeParameter('format') == 'flowed') { $text = $this->_formatFlowed($text, $this->_mimepart->getContentTypeParameter('delsp')); } else { /* A "From" located at the beginning of a line in the body text * will be escaped with a '>' by the IMAP server. Remove this * escape character or else the line will display as being * quoted. Flowed conversion would have already taken care of this * for us. */ $text = preg_replace('/(\\n+)> ?From(\\s+)/', "\$1From\$2", $text); } $text = IMP::filterText($text); // Build filter stack. Starts with HTML markup and tab expansion. $filters = array('text2html' => array('charset' => $charset, 'parselevel' => $inline ? Horde_Text_Filter_Text2html::MICRO : Horde_Text_Filter_Text2html::MICRO_LINKURL), 'tabs2spaces' => array()); // Highlight quoted parts of an email. if ($prefs->getValue('highlight_text')) { $hideBlocks = $js_blocks = false; if ($registry->getView() !== $registry::VIEW_SMARTMOBILE) { $js_blocks = $inline; if ($inline) { $show = $prefs->getValue('show_quoteblocks'); $hideBlocks = $show == 'hidden' || $show == 'thread' && $injector->getInstance('Horde_Variables')->page == 'thread'; if (!$hideBlocks && in_array($show, array('list', 'listthread'))) { $list_info = $contents->getListInformation(); $hideBlocks = $list_info['exists']; } } } if ($js_blocks) { $filters['highlightquotes'] = array('hideBlocks' => $hideBlocks, 'noJS' => $registry->getView() == Horde_Registry::VIEW_DYNAMIC); } else { $filters['Horde_Text_Filter_Highlightquotes'] = array('hideBlocks' => $hideBlocks); } } // Highlight simple markup of an email. if ($prefs->getValue('highlight_simple_markup')) { $filters['simplemarkup'] = array('html' => true); } // Dim signatures. if ($prefs->getValue('dim_signature')) { $filters['dimsignature'] = array(); } if ($prefs->getValue('emoticons')) { $filters['emoticons'] = array('entities' => true); } // Run filters. $status = array(); $text = $this->_textFilter($text, array_keys($filters), array_values($filters)); if (strlen($text)) { // Wordwrap. $text = str_replace(array(' ', "\n "), array(' ', "\n "), $text); if (!strncmp($text, ' ', 1)) { $text = ' ' . substr($text, 1); } } else { $error = new IMP_Mime_Status_RenderIssue($this->_mimepart, array(_("Cannot display message text."), _("The message part may contain incorrect character set information preventing correct display."))); $error->action(IMP_Mime_Status::ERROR); $status[] = $error; } return array($mime_id => array('data' => "<div class=\"fixed leftAlign\">\n" . $text . '</div>', 'status' => $status, 'type' => $type)); }