Filters a string, if requested.
public static filterText ( string $text ) : string | ||
$text | string | The text to filter. |
return | string | The filtered text (if requested). |
/** * Format output text with IMP additions. * * @param string $text The HTML text. * * @return string The text with extra IMP formatting applied. */ protected function _IMPformat($text) { // Highlight quoted parts of an email. if ($GLOBALS['prefs']->getValue('highlight_text')) { $text = implode("\n", preg_replace('|^(\\s*>.+)$|', '<span class="quoted1">\\1</span>', explode("\n", $text))); $indent = 1; while (preg_match('|>(\\s?>){' . $indent . '}|', $text)) { $text = implode("\n", preg_replace('|^<span class="quoted' . (($indent - 1) % 5 + 1) . '">(\\s*>(\\s?>){' . $indent . '}.+)$|', '<span class="quoted' . ($indent % 5 + 1) . '">\\1', explode("\n", $text))); ++$indent; } } // Dim signatures. if ($GLOBALS['prefs']->getValue('dim_signature')) { $parts = preg_split('|(\\n--\\s*\\n)|', $text, 2, PREG_SPLIT_DELIM_CAPTURE); $text = array_shift($parts); if (count($parts)) { $text .= '<span class="signature">' . $parts[0] . preg_replace('|class="[^"]+"|', 'class="signature-fixed"', $parts[1]) . '</span>'; } } // Filter bad language. return IMP::filterText($text); }
/** */ protected function _node($doc, $node) { parent::_node($doc, $node); if (empty($this->_imptmp) || !$node instanceof DOMElement) { if ($node instanceof DOMText && $node->length > 1) { /* Filter bad language. */ $text = IMP::filterText($node->data); if ($node->data != $text) { $node->replaceData(0, $node->length, $text); } } return; } $tag = Horde_String::lower($node->tagName); /* Remove 'height' styles from HTML messages, because it can break * sizing of IFRAME. */ foreach ($node->attributes as $key => $val) { if ($key == 'style') { /* Do simplistic style parsing here. */ $parts = array_filter(explode(';', $val->value)); foreach ($parts as $k2 => $v2) { if (preg_match("/^\\s*height:\\s*/i", $v2)) { unset($parts[$k2]); } } $val->value = implode(';', $parts); } } switch ($tag) { case 'a': case 'area': /* Convert links to open in new windows. Ignore mailto: links and * links that already have a target. */ if ($node->hasAttribute('href')) { $url = parse_url($node->getAttribute('href')); if (isset($url['scheme']) && $url['scheme'] == 'mailto') { /* We don't include HordePopup in IFRAME, so need to use * 'simple' links. */ $clink = new IMP_Compose_Link($node->getAttribute('href')); $node->setAttribute('href', $clink->link(true)); $node->removeAttribute('target'); } elseif (!empty($this->_imptmp['inline']) && isset($url['fragment']) && empty($url['path']) && $GLOBALS['browser']->isBrowser('mozilla')) { /* See Bug #8695: internal anchors are broken in * Mozilla. */ $node->removeAttribute('href'); } elseif (empty($url)) { /* Empty URL - remove href/target so the link is not * clickable. */ $node->removeAttribute('href'); $node->removeAttribute('target'); } else { $node->setAttribute('target', strval(new Horde_Support_Randomid())); } } break; case 'body': $style = $node->hasAttribute('style') ? rtrim($node->getAttribute('style'), ';') . ';' : ''; $node->setAttribute('style', $style . 'width:auto !important'); break; case 'img': case 'input': if ($node->hasAttribute('src')) { $val = $node->getAttribute('src'); /* Multipart/related. */ if ($tag == 'img' && ($id = $this->_cidSearch($val))) { $val = $this->getConfigParam('imp_contents')->urlView(null, 'view_attach', array('params' => array('ctype' => 'image/*', 'id' => $id, 'imp_img_view' => 'data'))); } /* Block images.*/ if ($this->_imgBlock()) { if (Horde_Url_Data::isData($val)) { $url = new Horde_Url_Data($val); } else { /* Check for relative URLs. These won't be loaded and * will cause unnecessary 404 hits to the local web * server. */ $parsed_url = parse_url($val); if (isset($parsed_url['host'])) { $url = new Horde_Url($val); $url->setScheme(); } else { $url = null; } } if ($url) { $node->setAttribute(self::IMGBLOCK, $url); $node->setAttribute('src', $this->_imgBlockImg()); $this->_imptmp['imgblock'] = true; } else { $node->parentNode->removeChild($node); $this->_imptmp['imgbroken'] = true; } } else { $node->removeAttribute('src'); $node->setAttribute('data-src', $val); } } /* IMG only */ if ($tag == 'img' && $this->_imgBlock() && $node->hasAttribute('srcset')) { $node->setAttribute(self::SRCSETBLOCK, $node->getAttribute('srcset')); $node->setAttribute('srcset', ''); $this->_imptmp['imgblock'] = true; } break; case 'link': /* Block all link tags that reference foreign URLs, other than * CSS. There's no inherently wrong with linking to a foreign * CSS file other than privacy concerns. Therefore, block * linking until requested by the user. */ $delete_link = true; switch (Horde_String::lower($node->getAttribute('type'))) { case 'text/css': if ($node->hasAttribute('href')) { $tmp = $node->getAttribute('href'); if ($id = $this->_cidSearch($tmp, false)) { $this->_imptmp['style'][] = $this->getConfigParam('imp_contents')->getMIMEPart($id)->getContents(); } elseif ($this->_imgBlock()) { $node->setAttribute(self::CSSBLOCK, $node->getAttribute('href')); $node->removeAttribute('href'); $this->_imptmp['cssblock'] = true; $delete_link = false; } } break; } if ($delete_link && $node->hasAttribute('href') && $node->parentNode) { $node->parentNode->removeChild($node); } break; case 'style': switch (Horde_String::lower($node->getAttribute('type'))) { case 'text/css': $this->_imptmp['style'][] = str_replace(array('<!--', '-->'), '', $node->nodeValue); $node->parentNode->removeChild($node); break; } break; case 'table': /* If displaying inline (in IFRAME), tables with 100% height seems * to confuse many browsers re: the IFRAME internal height. */ if (!empty($this->_imptmp['inline']) && $node->hasAttribute('height') && $node->getAttribute('height') == '100%') { $node->removeAttribute('height'); } // Fall-through // Fall-through case 'body': case 'td': if ($node->hasAttribute('background')) { $val = $node->getAttribute('background'); /* Multipart/related. */ if ($id = $this->_cidSearch($val)) { $val = $this->getConfigParam('imp_contents')->urlView(null, 'view_attach', array('params' => array('id' => $id, 'imp_img_view' => 'data'))); $node->setAttribute('background', $val); } /* Block images.*/ if ($this->_imgBlock()) { $node->setAttribute(self::IMGBLOCK, $val); $node->setAttribute('background', $this->_imgBlockImg()); $this->_imptmp['imgblock'] = true; } } break; } $remove = array(); foreach ($node->attributes as $val) { /* Catch random mailto: strings in attributes that will cause * problems with e-mail linking. */ if (stripos($val->value, 'mailto:') === 0) { $remove[] = $val->name; } } foreach ($remove as $val) { $node->removeAttribute($val); } if ($node->hasAttribute('style')) { if (strpos($node->getAttribute('style'), 'content:') !== false) { // TODO: Figure out way to unblock? $node->removeAttribute('style'); } elseif (!empty($this->_imptmp['cid']) || $this->_imgBlock()) { $this->_imptmp['node'] = $node; $style = preg_replace_callback(self::CSS_BG_PREG, array($this, '_styleCallback'), $node->getAttribute('style'), -1, $matches); if ($matches) { $node->setAttribute('style', $style); } } } }
/** * Formats the subject header. * * @param string $subject The subject header. * @param string $htmlspaces HTML-ize spaces? * * @return string The formatted subject header. */ public function getSubject($subject, $htmlspaces = false) { if (!strlen($subject)) { return _("[No Subject]"); } $new_subject = $subject = IMP::filterText(preg_replace("/\\s+/", ' ', $subject)); if ($htmlspaces) { $new_subject = $GLOBALS['injector']->getInstance('Horde_Core_Factory_TextFilter')->filter($subject, 'space2html', array('encode' => true)); if (empty($new_subject)) { $new_subject = htmlspecialchars($subject); } } return empty($new_subject) ? $subject : $new_subject; }
/** * Render the object. * * @param boolean $inline Viewing inline? * * @return array See parent::render(). */ protected function _impRender($inline) { global $injector, $prefs, $registry; $cache = $this->getConfigParam('imp_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); /* Done processing if in minimal mode. */ if ($registry->getView() == Horde_Registry::VIEW_MINIMAL) { $filters = array('text2html' => array('charset' => $charset, 'parselevel' => Horde_Text_Filter_Text2html::NOHTML_NOBREAK)); $text = $this->_textFilter($text, array_keys($filters), array_values($filters)); return array($mime_id => array('data' => $text, 'type' => $type)); } // 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'))) { $header = $this->getConfigParam('imp_contents')->getHeader(); $list_info = $injector->getInstance('IMP_Message_Ui')->getListInformation($header); $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(); } // 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(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)); }
/** * Return subject header data. * * @return array Array with these possible keys: * <pre> * - subject: (string) The subject. * - subjectlink: (string) The subject with linked URLs/email addresses * (if not present, is same as 'subject'). * - title: (string) The title of the page derived from the subject. * </pre> */ public function getSubject() { global $injector; if (!isset($this->_cache['subject'])) { $out = array(); if (strlen($subject = $this->_envelope->subject)) { $text_filter = $injector->getInstance('Horde_Core_Factory_TextFilter'); $filtered_subject = preg_replace("/\\b\\s+\\b/", ' ', IMP::filterText($subject)); $out['subject'] = $text_filter->filter($filtered_subject, 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::NOHTML)); $subjectlink = $text_filter->filter($filtered_subject, 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO)); if ($subjectlink != $out['subject']) { $out['subjectlink'] = $subjectlink; } $out['title'] = $subject; } else { $out['subject'] = $out['title'] = _("[No Subject]"); } $this->_cache['subject'] = $out; } return $this->_cache['subject']; }
/** * URL Parameters: * a: (string) Action ID. * allto: (boolean) View all To addresses? * buid: (string) Browser UID. * t: (string) Token. */ protected function _init() { global $injector, $notification, $page_output, $prefs, $session; $imp_mailbox = $this->indices->mailbox->list_ob; $imp_mailbox->setIndex($this->indices); $mailbox_url = IMP_Minimal_Mailbox::url(array('mailbox' => $this->indices->mailbox)); /* Make sure we have a valid index. */ if (!$imp_mailbox->isValidIndex()) { $mailbox_url->add('a', 'm')->redirect(); } $imp_ui = $injector->getInstance('IMP_Message_Ui'); /* Run through action handlers */ $msg_delete = false; switch ($this->vars->a) { // 'd' = delete message case 'd': $old_index = $imp_mailbox->getIndex(); try { $session->checkToken($this->vars->t); $msg_delete = (bool) $injector->getInstance('IMP_Message')->delete($this->indices, array('mailboxob' => $imp_mailbox)); } catch (Horde_Exception $e) { $notification->push($e); } break; // 'u' = undelete message // 'u' = undelete message case 'u': $old_index = $imp_mailbox->getIndex(); $injector->getInstance('IMP_Message')->undelete($this->indices); break; // 'rs' = report spam // 'ri' = report innocent // 'rs' = report spam // 'ri' = report innocent case 'rs': case 'ri': $old_index = $imp_mailbox->getIndex(); $msg_delete = $injector->getInstance('IMP_Factory_Spam')->create($this->vars->a == 'rs' ? IMP_Spam::SPAM : IMP_Spam::INNOCENT)->report($this->indices, array('mailboxob' => $imp_mailbox)) === 1; break; } if ($msg_delete && $imp_ui->moveAfterAction($this->indices->mailbox)) { $imp_mailbox->setIndex(1); } /* We may have done processing that has taken us past the end of the * message array, so we will return to the mailbox. */ if (!$imp_mailbox->isValidIndex() || $msg_delete && $prefs->getValue('mailbox_return')) { $mailbox_url->add('s', $old_index)->redirect(); } /* Now that we are done processing, get the index and array index of * the current message. */ $msg_index = $imp_mailbox[$imp_mailbox->getIndex()]; $mailbox = $msg_index['m']; $uid = $msg_index['u']; $buid = $imp_mailbox->getBuid($mailbox, $uid); /* Get envelope/flag/header information. */ try { $imp_imap = $mailbox->imp_imap; /* Need to fetch flags before HEADERTEXT, because SEEN flag might * be set before we can grab it. */ $query = new Horde_Imap_Client_Fetch_Query(); $query->flags(); $flags_ret = $imp_imap->fetch($mailbox, $query, array('ids' => $imp_imap->getIdsOb($uid))); $query = new Horde_Imap_Client_Fetch_Query(); $query->envelope(); $fetch_ret = $imp_imap->fetch($mailbox, $query, array('ids' => $imp_imap->getIdsOb($uid))); } catch (IMP_Imap_Exception $e) { $mailbox_url->add('a', 'm')->redirect(); } $envelope = $fetch_ret->first()->getEnvelope(); $flags = $flags_ret->first()->getFlags(); /* Parse the message. */ try { $imp_contents = $injector->getInstance('IMP_Factory_Contents')->create(new IMP_Indices($imp_mailbox)); $mime_headers = $imp_contents->getHeaderAndMarkAsSeen(); } catch (IMP_Exception $e) { $mailbox_url->add('a', 'm')->redirect(); } /* Get the starting index for the current message and the message * count. */ $msgindex = $imp_mailbox->getIndex(); $msgcount = count($imp_mailbox); /* Generate the mailbox link. */ $mailbox_link = $mailbox_url->add('s', $msgindex); $self_link = self::url(array('buid' => $buid, 'mailbox' => $this->indices->mailbox)); /* Create the Identity object. */ $user_identity = $injector->getInstance('IMP_Identity'); /* Develop the list of headers to display. */ $basic_headers = $imp_ui->basicHeaders(); $display_headers = $msgAddresses = array(); if ($subject = $mime_headers->getValue('subject')) { /* Filter the subject text, if requested. */ $subject = Horde_String::truncate(IMP::filterText($subject), 50); } else { $subject = _("[No Subject]"); } $display_headers['subject'] = $subject; $format_date = $imp_ui->getLocalTime($envelope->date); if (!empty($format_date)) { $display_headers['date'] = $format_date; } /* Build From address links. */ $display_headers['from'] = $imp_ui->buildAddressLinks($envelope->from, null, false); /* Build To/Cc/Bcc links. */ foreach (array('to', 'cc', 'bcc') as $val) { $msgAddresses[] = $mime_headers->getValue($val); $addr_val = $imp_ui->buildAddressLinks($envelope->{$val}, null, false); if (!empty($addr_val)) { $display_headers[$val] = $addr_val; } } /* Check for the presence of mailing list information. */ $list_info = $imp_ui->getListInformation($mime_headers); /* See if the priority has been set. */ switch ($priority = $injector->getInstance('IMP_Mime_Headers')->getPriority($mime_headers)) { case 'high': case 'low': $basic_headers['priority'] = _("Priority"); $display_headers['priority'] = Horde_String::ucfirst($priority); break; } /* Set the status information of the message. */ $status = ''; $match_identity = $identity = null; if (!empty($msgAddresses)) { $match_identity = $identity = $user_identity->getMatchingIdentity($msgAddresses); if (is_null($identity)) { $identity = $user_identity->getDefault(); } } $flag_parse = $injector->getInstance('IMP_Flags')->parse(array('flags' => $flags, 'personal' => $match_identity)); foreach ($flag_parse as $val) { if ($abbrev = $val->abbreviation) { $status .= $abbrev; } elseif ($val instanceof IMP_Flag_User) { $status .= ' *' . Horde_String::truncate($val->label, 8) . '*'; } } /* Create the body of the message. */ $inlineout = $imp_contents->getInlineOutput(array('display_mask' => IMP_Contents::RENDER_INLINE, 'no_inline_all' => true)); $msg_text = $inlineout['msgtext']; $this->view->msg = nl2br($injector->getInstance('Horde_Core_Factory_TextFilter')->filter($msg_text, 'space2html')); $menu = array(); if ($this->indices->mailbox->access_deletemsgs) { $menu[] = in_array(Horde_Imap_Client::FLAG_DELETED, $flags) ? array(_("Undelete"), $self_link->copy()->add('a', 'u')) : array(_("Delete"), $self_link->copy()->add(array('a' => 'd', 't' => $session->getToken()))); } /* Add compose actions (Reply, Reply List, Reply All, Forward, * Redirect, Edit as New). */ if (IMP_Compose::canCompose()) { $clink_ob = new IMP_Compose_Link(); $clink_ob->args['buid'] = $buid; $clink_ob->args['mailbox'] = $this->indices->mailbox; $clink = $clink_ob->link()->add(array('identity' => $identity)); $menu[] = array(_("Reply"), $clink->copy()->add(array('a' => 'r'))); if ($list_info['reply_list']) { $menu[] = array(_("Reply to List"), $clink->copy()->add(array('a' => 'rl'))); } $addr_ob = clone $envelope->to; $addr_ob->add($envelope->cc); $addr_ob->setIteratorFilter(0, $user_identity->getAllFromAddresses()); if (count($addr_ob)) { $menu[] = array(_("Reply All"), $clink->copy()->add(array('a' => 'ra'))); } $menu[] = array(_("Forward"), $clink->copy()->add(array('a' => 'f'))); $menu[] = array(_("Redirect"), $clink->copy()->add(array('a' => 'rc'))); $menu[] = array(_("Edit as New"), $clink->copy()->add(array('a' => 'en'))); } /* Generate previous/next links. */ if ($prev_msg = $imp_mailbox[$imp_mailbox->getIndex() - 1]) { $menu[] = array(_("Previous Message"), self::url(array('buid' => $imp_mailbox->getBuid($prev_msg['m'], $prev_msg['u']), 'mailbox' => $this->indices->mailbox))); } if ($next_msg = $imp_mailbox[$imp_mailbox->getIndex() + 1]) { $menu[] = array(_("Next Message"), self::url(array('buid' => $imp_mailbox->getBuid($next_msg['m'], $next_msg['u']), 'mailbox' => $this->indices->mailbox))); } $menu[] = array(sprintf(_("To %s"), $this->indices->mailbox->label), $mailbox_link); if ($mailbox->spam_show) { $menu[] = array(_("Report as Spam"), $self_link->copy()->add(array('a' => 'rs', 't' => $session->getToken()))); } if ($mailbox->innocent_show) { $menu[] = array(_("Report as Innocent"), $self_link->copy()->add(array('a' => 'ri', 't' => $session->getToken()))); } $this->view->menu = $this->getMenu('message', $menu); $hdrs = array(); foreach ($display_headers as $head => $val) { $tmp = array('label' => $basic_headers[$head]); if (Horde_String::lower($head) == 'to' && !isset($this->vars->allto) && ($pos = strpos($val, ',')) !== false) { $val = Horde_String::substr($val, 0, $pos); $tmp['all_to'] = $self_link->copy()->add('allto', 1); } $tmp['val'] = $val; $hdrs[] = $tmp; } $this->view->hdrs = $hdrs; $atc = array(); foreach ($inlineout['atc_parts'] as $key) { $summary = $imp_contents->getSummary($key, IMP_Contents::SUMMARY_BYTES | IMP_Contents::SUMMARY_SIZE | IMP_Contents::SUMMARY_DESCRIP | IMP_Contents::SUMMARY_DOWNLOAD); $tmp = array('descrip' => $summary['description_raw'], 'size' => $summary['size'], 'type' => $summary['type']); if (!empty($summary['download'])) { /* Preference: if set, only show download confirmation screen * if attachment over a certain size. */ $tmp['download'] = IMP_Minimal_Messagepart::url(array('buid' => $buid, 'mailbox' => $this->indices->mailbox))->add('atc', $key); } if ($imp_contents->canDisplay($key, IMP_Contents::RENDER_INLINE)) { $tmp['view'] = IMP_Minimal_Messagepart::url(array('buid' => $buid, 'mailbox' => $this->indices->mailbox))->add('id', $key); } $atc[] = $tmp; } $this->view->atc = $atc; $this->title = $display_headers['subject']; $this->view->title = ($status ? $status . ' ' : '') . sprintf(_("(Message %d of %d)"), $msgindex, $msgcount); $page_output->noDnsPrefetch(); $this->_pages[] = 'message'; $this->_pages[] = 'menu'; }
/** * Create the object used to display the message. * * @param array $args Configuration parameters: * - headers: (array) The headers desired in the returned headers array * (only used with non-preview view). * - preview: (boolean) Is this the preview view? * * @return array Array with the following keys: * - atc_download: The download all link * - atc_label: The label to use for Attachments * - atc_list: The list (HTML code) of attachments * - bcc (FULL): The Bcc addresses * - cc: The CC addresses * - fulldate (FULL): The full canonical date. * - from: The From addresses * - headers (FULL): An array of headers (not including basic headers) * - js: Javascript code to run on display * - list_info (FULL): List information. * - localdate (PREVIEW): The date formatted to the user's timezone * - md: Metadata * - msgtext: The text of the message * - onepart: True if message only contains one part. * - replyTo (FULL): The Reply-to addresses * - save_as: The save link * - subject: The subject * - subjectlink: The subject with linked URLs/email addresses (defaults * to 'subject') * - title (FULL): The title of the page * - to: The To addresses * * @throws IMP_Exception */ public function showMessage($args) { global $injector, $page_output, $prefs, $registry, $session; $preview = !empty($args['preview']); $result = array(); $mime_headers = $this->_peek ? $this->_contents->getHeader() : $this->_contents->getHeaderAndMarkAsSeen(); $headers = array(); $imp_ui = $injector->getInstance('IMP_Message_Ui'); /* Develop the list of Headers to display now. Deal with the 'basic' * header information first since there are various manipulations * done to them. */ $basic_headers = $imp_ui->basicHeaders(); if (empty($args['headers'])) { $args['headers'] = array('from', 'date', 'to', 'cc', 'bcc'); } $headers_list = array_intersect_key($basic_headers, array_flip($args['headers'])); /* Build From/To/Cc/Bcc/Reply-To links. */ foreach (array('from', 'to', 'cc', 'bcc', 'reply-to') as $val) { if (isset($headers_list[$val]) && (!$preview || $val != 'reply-to')) { if ($tmp = $this->getAddressHeader($val)) { $result[$val] = $tmp; } if ($preview) { unset($headers_list[$val]); } } } /* Build the rest of the headers. */ foreach ($headers_list as $head => $str) { if ($val = $mime_headers->getValue($head)) { if ($head == 'date') { /* Add local time to date header. */ $date_ob = new IMP_Message_Date($this->_envelope->date); $val = htmlspecialchars($date_ob->format($date_ob::DATE_LOCAL)); if ($preview) { $result['localdate'] = $val; } else { $result['fulldate'] = $date_ob->format($date_ob::DATE_FORCE); } } elseif (!$preview) { $val = htmlspecialchars($val); } if (!$preview) { $headers[$head] = array('id' => Horde_String::ucfirst($head), 'name' => $str, 'value' => $val); } } } if (empty($result['reply-to']) || $result['from']['addr'][0]->b == $result['reply-to']['addr'][0]->b) { unset($result['reply-to'], $headers['reply-to']); } /* JS requires camelized name for reply-to. */ if (!$preview && isset($headers['reply-to'])) { $result['replyTo'] = $result['reply-to']; $headers['reply-to']['id'] = 'ReplyTo'; unset($result['reply-to']); } /* Maillog information. */ $ajax_queue = $injector->getInstance('IMP_Ajax_Queue'); $ajax_queue->maillog($this->_indices); if (!$preview) { /* Display the user-specified headers for the current identity. */ $user_hdrs = $imp_ui->getUserHeaders(); foreach ($user_hdrs as $user_hdr) { $user_val = $mime_headers->getValue($user_hdr); if (!empty($user_val)) { if (!is_array($user_val)) { $user_val = array($user_val); } foreach ($user_val as $val) { $headers[] = array('name' => $user_hdr, 'value' => htmlspecialchars($val)); } } } $result['headers'] = array_values($headers); } /* Process the subject. */ $subject = $mime_headers->getValue('subject'); if ($subject) { $text_filter = $injector->getInstance('Horde_Core_Factory_TextFilter'); $filtered_subject = preg_replace("/\\b\\s+\\b/", ' ', IMP::filterText($subject)); $result['subject'] = $text_filter->filter($filtered_subject, 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::NOHTML)); $subjectlink = $text_filter->filter($filtered_subject, 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO)); if ($subjectlink != $result['subject']) { $result['subjectlink'] = $subjectlink; } if (!$preview) { $result['title'] = $subject; } } else { $result['subject'] = _("[No Subject]"); if (!$preview) { $result['title'] = _("[No Subject]"); } } // Create message text and attachment list. $result['msgtext'] = ''; $show_parts = $prefs->getValue('parts_display'); switch ($registry->getView()) { case $registry::VIEW_SMARTMOBILE: $contents_mask = 0; break; default: $contents_mask = IMP_Contents::SUMMARY_BYTES | IMP_Contents::SUMMARY_SIZE | IMP_Contents::SUMMARY_ICON | IMP_Contents::SUMMARY_DESCRIP_LINK | IMP_Contents::SUMMARY_DOWNLOAD | IMP_Contents::SUMMARY_DOWNLOAD_ZIP | IMP_Contents::SUMMARY_PRINT_STUB; break; } $part_info = $part_info_display = array('icon', 'description', 'size', 'download', 'download_zip'); $part_info_display[] = 'print'; list($mbox, $uid) = $this->_indices->getSingle(); /* Do MDN processing now. */ switch ($registry->getView()) { case $registry::VIEW_DYNAMIC: if ($imp_ui->MDNCheck(new IMP_Indices($mbox, $uid), $mime_headers)) { $status = new IMP_Mime_Status(array(_("The sender of this message is requesting notification from you when you have read this message."), sprintf(_("Click %s to send the notification message."), Horde::link('#', '', '', '', '', '', '', array('id' => 'send_mdn_link')) . _("HERE") . '</a>'))); $status->domid('sendMdnMessage'); $result['msgtext'] .= strval($status); } } /* Build body text. This needs to be done before we build the * attachment list. */ $session->close(); $inlineout = $this->_contents->getInlineOutput(array('mask' => $contents_mask, 'part_info_display' => $part_info_display, 'show_parts' => $show_parts)); $session->start(); $result['md'] = $inlineout['metadata']; $result['msgtext'] .= $inlineout['msgtext']; if ($inlineout['one_part']) { $result['onepart'] = true; } if (count($inlineout['atc_parts']) || $show_parts == 'all' && count($inlineout['display_ids']) > 2) { $result['atc_label'] = $show_parts == 'all' ? _("Parts") : sprintf(ngettext("%d Attachment", "%d Attachments", count($inlineout['atc_parts'])), count($inlineout['atc_parts'])); if (count($inlineout['atc_parts']) > 2) { $result['atc_download'] = Horde::link($this->_contents->urlView($this->_contents->getMIMEMessage(), 'download_all')) . '[' . _("Save All") . ']</a>'; } } /* Show attachment information in headers? */ if (!empty($inlineout['atc_parts'])) { $partlist = array(); if ($show_parts == 'all') { array_unshift($part_info, 'id'); } foreach ($inlineout['atc_parts'] as $id) { $contents_mask |= IMP_Contents::SUMMARY_DESCRIP | IMP_Contents::SUMMARY_DOWNLOAD | IMP_Contents::SUMMARY_ICON | IMP_Contents::SUMMARY_SIZE; $part_info[] = 'description_raw'; $part_info[] = 'download_url'; $summary = $this->_contents->getSummary($id, $contents_mask); $tmp = array(); foreach ($part_info as $val) { if (isset($summary[$val])) { $tmp[$val] = $summary[$val] instanceof Horde_Url ? strval($summary[$val]->setRaw(true)) : $summary[$val]; } } $partlist[] = array_filter($tmp); } $result['atc_list'] = $partlist; } $result['save_as'] = IMP_Contents_View::downloadUrl(htmlspecialchars_decode($result['subject']), array_merge(array('actionID' => 'save_message'), $mbox->urlParams($uid))); if ($preview) { /* Need to grab cached inline scripts. */ Horde::startBuffer(); $page_output->outputInlineScript(true); if ($js_inline = Horde::endBuffer()) { $result['js'] = array($js_inline); } $result['save_as'] = strval($result['save_as']->setRaw(true)); } else { $list_info = $imp_ui->getListInformation($mime_headers); if (!empty($list_info['exists'])) { $result['list_info'] = $list_info; } } /* Add changed flag information. */ if (!$this->_peek && $mbox->is_imap) { $status = $mbox->imp_imap->status($mbox, Horde_Imap_Client::STATUS_PERMFLAGS); if (in_array(Horde_Imap_Client::FLAG_SEEN, $status['permflags'])) { $ajax_queue->flag(array(Horde_Imap_Client::FLAG_SEEN), true, $this->_indices); } } return array_filter($result); }