Files
server/usr/share/psa-horde/imp/lib/Ajax/Application/ShowMessage.php
2026-01-07 20:52:11 +01:00

459 lines
16 KiB
PHP

<?php
/**
* Copyright 2005-2017 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (GPL). If you
* did not receive this file, see http://www.horde.org/licenses/gpl.
*
* @category Horde
* @copyright 2005-2017 Horde LLC
* @license http://www.horde.org/licenses/gpl GPL
* @package IMP
*/
/**
* Message viewing action for AJAX application handler.
*
* @author Michael Slusarz <slusarz@horde.org>
* @category Horde
* @copyright 2005-2017 Horde LLC
* @license http://www.horde.org/licenses/gpl GPL
* @package IMP
*/
class IMP_Ajax_Application_ShowMessage
{
/**
* Contents object.
*
* @var IMP_Contents
*/
protected $_contents;
/**
* Envelope object.
*
* @var Horde_Imap_Client_Data_Envelope
*/
protected $_envelope;
/**
* Indices object.
*
* @var IMP_Indices
*/
protected $_indices;
/**
* Don't seen seen flag?
*
* @var boolean
*/
protected $_peek;
/**
* Constructor.
*
* @param IMP_Indices $indices The index of the message.
* @param boolean $peek Don't set seen flag?
*/
public function __construct(IMP_Indices $indices, $peek = false)
{
global $injector;
/* Get envelope/header information. We don't use flags in this
* view. */
try {
list($mbox, $uid) = $indices->getSingle();
if (!$uid) {
throw new Exception();
}
$query = new Horde_Imap_Client_Fetch_Query();
$query->envelope();
$imp_imap = $mbox->imp_imap;
$imp_imap->openMailbox($mbox, Horde_Imap_Client::OPEN_READWRITE);
$ret = $imp_imap->fetch($mbox, $query, array(
'ids' => $imp_imap->getIdsOb($uid)
));
if (!($ob = $ret->first())) {
throw new Exception();
}
$imp_contents = $injector->getInstance('IMP_Factory_Contents')->create($indices);
} catch (Exception $e) {
throw new IMP_Exception(_("Requested message not found."));
}
$this->_contents = $imp_contents;
$this->_envelope = $ob->getEnvelope();
$this->_indices = $indices;
$this->_peek = $peek;
}
/**
* 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
* - 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
* - 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(
'js' => array()
);
/* Set the current time zone. */
$registry->setTimeZone();
$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. */
$val = htmlspecialchars($imp_ui->getLocalTime($this->_envelope->date));
if ($preview) {
$result['localdate'] = $val;
}
} 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['js'] = array_merge($result['js'], $inlineout['js_onload']);
$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;
}
list($bmbox, $buid) = ($this->_indices instanceof IMP_Indices_Mailbox)
? $this->_indices->buids->getSingle()
: $this->_indices->getSingle();
$result['save_as'] = IMP_Contents_View::downloadUrl(
htmlspecialchars_decode($result['subject']),
array_merge(
array('actionID' => 'save_message'),
$bmbox->urlParams($buid)
)
);
if ($preview) {
/* Need to grab cached inline scripts. */
Horde::startBuffer();
$page_output->outputInlineScript(true);
if ($js_inline = Horde::endBuffer()) {
$result['js'][] = $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;
}
}
if (empty($result['js'])) {
unset($result['js']);
}
/* 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 $result;
}
/**
* Return data to build an address header.
*
* @param string $header The address header.
* @param integer $limit Limit display to this many addresses. If null,
* shows all addresses.
*
* @return array An array with the following entries:
* - addr: (array) List of addresses/groups.
* Group keys: 'a' (list of addresses); 'g' (group name)
* Address keys: 'b' (bare address); 'p' (personal part)
* - limit: (integer) If limit was reached, the number of total
* addresses.
* - raw: (string) A raw string to display instead of addresses.
*/
public function getAddressHeader($header, $limit = 50)
{
$addrlist = ($header == 'reply-to')
? $this->_envelope->reply_to
: $this->_envelope->$header;
$addr_array = $out = array();
$count = 0;
$addrlist->unique();
foreach ($addrlist->base_addresses as $ob) {
if ($ob instanceof Horde_Mail_Rfc822_Group) {
$ob->addresses->unique();
$tmp = array(
'a' => array(),
'g' => $ob->groupname
);
foreach ($ob->addresses as $val) {
$tmp['a'][] = array_filter(array(
'b' => $val->bare_address,
'p' => $val->personal
));
if (!is_null($limit) && ($count++ > $limit)) {
break;
}
}
} else {
$tmp = array_filter(array(
'b' => $ob->bare_address,
'p' => $ob->personal
));
++$count;
}
$addr_array[] = $tmp;
if (!is_null($limit) && ($count > $limit)) {
$out['limit'] = count($addrlist);
break;
}
}
if (!empty($addr_array)) {
$out['addr'] = $addr_array;
} elseif ($header == 'to') {
$out['raw'] = _("Undisclosed Recipients");
}
return $out;
}
}