<?php
/**
 * $Horde: imp/message.php,v 2.487 2003/08/06 21:35:52 slusarz Exp $
 *
 * Copyright 1999-2003 Charles J. Hagenbuch <chuck@horde.org>
 * Copyright 1999-2003 Jon Parise <jon@horde.org>
 *
 * See the enclosed file COPYING for license information (GPL).  If you
 * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
 */

/**
 * Set pertinent variables for the mailbox.php script.
 *
 * @param optional integer $startIndex  The start index to use.
 * @param optional string $actID        The action ID to use.
 */
function _returnToMailbox($startIndex = null, $actID = null)
{
    global $actionID, $from_message_page, $start;

    $actionID = null;
    $from_message_page = true;
    $start = null;

    if (!is_null($startIndex)) {
        $start = $startIndex;
    }
    if (!is_null($actID)) {
        $actionID = $actID;
    }
}

define('IMP_BASE', dirname(__FILE__));
require_once IMP_BASE . '/lib/base.php';
require_once IMP_BASE . '/lib/Contents.php';
require_once IMP_BASE . '/lib/Headers.php';
require_once IMP_BASE . '/lib/Mailbox.php';
require_once IMP_BASE . '/lib/Search.php';
require_once HORDE_BASE . '/lib/MIME.php';
require_once HORDE_BASE . '/lib/Identity.php';

/* Make sure we have a valid index. */
$imp_mailbox = &new IMP_Mailbox(Horde::getFormData('index'));
if (!$imp_mailbox->isValidIndex()) {
    _returnToMailbox(null, 'message_missing');
    require IMP_BASE . '/mailbox.php';
    exit;
}

/* Are we using printer-friendly formatting? */
$printer_friendly = false;

/* Set the current time zone. */
NLS::setTimeZone();

/* Initialize the user's identities */
$user_identity = &Identity::singleton(array('imp', 'imp'));

/* Run through action handlers */
$actionID = Horde::getFormData('actionID');
switch ($actionID) {
case 'blacklist':
    require_once IMP_BASE . '/lib/Filter.php';
    IMP_Filter::blacklistMessage(array($imp_mailbox->getIndex()));
    break;

case 'whitelist':
    require_once IMP_BASE . '/lib/Filter.php';
    IMP_Filter::whitelistMessage(array($imp_mailbox->getIndex()));
    break;

case 'print_message':
    $printer_friendly = true;
    $imp_contents = &new IMP_Contents($imp_mailbox->getIndex());
    $imp_contents->setPrintMode(true);
    break;

case 'undelete_message':
    require_once IMP_BASE . '/lib/Message.php';
    $imp_message = &new IMP_Message();
    $imp_message->setMailboxObject($imp_mailbox);
    $imp_message->undelete();
    break;

case 'delete_message':
    require_once IMP_BASE . '/lib/Message.php';
    $imp_message = &new IMP_Message();
    $imp_message->setMailboxObject($imp_mailbox);
    $imp_message->delete();
    if ($prefs->getValue('mailbox_return')) {
        _returnToMailbox($imp_mailbox->getMessageIndex());
        require IMP_BASE . '/mailbox.php';
        exit;
    }
    break;

case 'move_message':
case 'copy_message':
    if (($targetMbox = Horde::getFormData('targetMbox')) !== null) {
        require_once IMP_BASE . '/lib/Message.php';
        $imp_message = &new IMP_Message();
        $imp_message->setMailboxObject($imp_mailbox);
        $action = ($actionID == 'move_message') ? IMP_MESSAGE_MOVE : IMP_MESSAGE_COPY;
        if (Horde::getFormData('newMbox', 0) == 1) {
            $new_mailbox = IMP::addPreambleString(String::convertCharset($targetMbox, NLS::getCharset(), 'UTF7-IMAP'));
            require_once IMP_BASE . '/lib/Folder.php';
            $imp_folder = &IMP_Folder::singleton();
            if ($imp_folder->create($imp['stream'], $new_mailbox, $prefs->getValue('subscribe'))) {
                $imp_message->copy($new_mailbox, $action);
            }
        } else {
            $imp_message->copy($targetMbox, $action);
        }
    }
    if ($prefs->getValue('mailbox_return')) {
        _returnToMailbox($imp_mailbox->getMessageIndex());
        require IMP_BASE . '/mailbox.php';
        exit;
    }
    break;

case 'spam_report':
    /* Abort immediately if spam reporting has not been enabled. */
    if (!$conf['spam']['reporting']) {
        break;
    }

    /* Fetch the raw message contents (headers and complete body). */
    $imp_contents = &new IMP_Contents($imp_mailbox->getIndex());
    $raw_msg = $imp_contents->fullMessageText();

    /* If a spam reporting program has been provided, use it. */
    if (!empty($conf['spam']['program'])) {
        /* Use a pipe to write the message contents. This should be secure. */
        $pipe = popen($conf['spam']['program'], 'w');
        fwrite($pipe, $raw_msg);
        pclose($pipe);

        $notification->push(_("This message has been reported as spam."), 'horde.message');
    }

    /* If a spam reporting email address has been provided, use it. */
    if (!empty($conf['spam']['email'])) {
        require_once IMP_BASE . '/lib/Compose.php';
        $imp_compose = &new IMP_Compose();
        $imp_compose->sendSpamReportMessage($raw_msg);
        $notification->push(_("This message has been reported as spam to your system administrator."), 'horde.message');
    }

    /* Delete Spam after report */
    if ($prefs->getValue('delete_spam_after_report')) {
        require_once IMP_BASE . '/lib/Message.php';
        $imp_message = &new IMP_Message();
        $imp_message->setMailboxObject($imp_mailbox);
        $imp_message->delete();
        unset($imp_contents);
        unset($raw_msg);
        $notification->push(_("The message has been deleted."), 'horde.message');
        if ($prefs->getValue('mailbox_return')) {
            _returnToMailbox($imp_mailbox->getMessageIndex());
            require IMP_BASE . '/mailbox.php';
            exit;
        }
    }
    break;

case 'flag_message':
    $flag = Horde::getFormData('flag');
    if (!empty($flag)) {
        if ($flag[0] == '0') {
            $_POST['flag'] = '\\' . substr($flag, 1);
            $set = false;
        } else {
            $_POST['flag'] = '\\' . $flag;
            $set = true;
        }
        require_once IMP_BASE . '/lib/Message.php';
        $imp_message = &new IMP_Message();
        $imp_message->setMailboxObject($imp_mailbox);
        $imp_message->flag($_POST['flag'], array($imp_mailbox->getIndex()), $set);
        if ($prefs->getValue('mailbox_return')) {
            _returnToMailbox($imp_mailbox->getMessageIndex());
            require IMP_BASE . '/mailbox.php';
            exit;
        }
        $imp_mailbox->moveNext();
    }
    break;

case 'add_address':
    $newAddress = Horde::getFormData('address');
    if (!($newName = Horde::getFormData('name'))) {
        $newName = $newAddress;
    }

    $res = $registry->call('contacts/add', array($newName, $newAddress, $prefs->getValue('add_source')));
    if (is_a($res, 'PEAR_Error')) {
        $notification->push($res, $res->getCode());
    } elseif (!$res) {
        $notification->push(_("An unknown error occured adding the new entry."), 'horde.error');
    } else {
        $notification->push(sprintf(_("Entry \"%s\" was successfully added to the address book"), $newName), 'horde.success');
    }
    break;

case 'strip_attachment':
    require_once IMP_BASE . '/lib/Message.php';

    $imp_message = &new IMP_Message();
    $imp_message->setMailboxObject($imp_mailbox);
    $res = $imp_message->stripPart($imp_mailbox->getIndex(), Horde::getFormData('imapid'));
    if (is_a($res, 'PEAR_Error')) {
        $notification->push($res, 'horde.error');
    }

    break;
}

if ($conf['user']['allow_folders']) {
    $options = IMP::flistSelect(_("This message to"), true, array($imp['mailbox']), null, true);
}

/* We may have done processing that has taken us past the end of the
   message array, so we will return to mailbox.php if that is the case. */
if (!$imp_mailbox->isValidIndex()) {
    _returnToMailbox($imp_mailbox->getMessageIndex());
    require IMP_BASE . '/mailbox.php';
    exit;
}

/* Now that we are done processing the messages, get the index and array
   index of the current message. */
$index = $imp_mailbox->getIndex();
$array_index = $imp_mailbox->getArrayIndex();

/* If we grab the headers before grabbing body parts, we'll see when a
   message is unread. */
$imp_headers = &new IMP_Headers($index);
$imp_headers->buildHeaders();
$imp_headers->buildFlags();

/* Parse MIME info and create the body of the message. */
if (!isset($imp_contents)) {
    $imp_contents = &new IMP_Contents($index);
}

/* Determine if we should generate the attachment strip links or not. */
if ($prefs->getValue('strip_attachments')) {
    $imp_contents->setStripLink(true);
}

/* Don't show summary links if we are printing the message. */
$imp_contents->showSummaryLinks(!$printer_friendly);

if (!$imp_contents->buildMessage()) {
    _returnToMailbox(null, 'message_missing');
    require IMP_BASE . '/mailbox.php';
    exit;
}
$attachments = $imp_contents->getAttachments();
$msgText = $imp_contents->getMessage();

/* Develop the list of Headers to display now. We will deal with the 'basic'
   header information first since there are various manipulations we do to
   them. */
$basic_headers = array(
    'date'      =>  _("Date"),
    'from'      =>  _("From"),
    'to'        =>  _("To"),
    'cc'        =>  _("Cc"),
    'bcc'       =>  _("Bcc"),
    'reply-to'  =>  _("Reply-To"),
    'subject'   =>  _("Subject")
);
$msgAddresses = array();

$imp_headers->setValueByFunction('date', array('nl2br', 'htmlspecialchars'));

/* Get the title/mailbox label of the mailbox page. */
$page_label = IMP::getLabel();

/* Process the subject now. */
if (($subject = $imp_headers->getValue('subject'))) {
    /* Filter the subject text, if requested. */
    $subject = IMP::filterText($subject);

    require_once HORDE_BASE . '/lib/Text.php';
    $imp_headers->setValue('subject', Text::htmlSpaces($subject));

    /* Generate the shortened subject text. */
    $maxsubj = $prefs->getValue('max_subj_chars');
    if (String::length($subject) > $maxsubj) {
        $subject = String::substr($subject, 0, $maxsubj) . '...';
    }
    $title = sprintf(_("%s: %s"), $page_label, $subject);
    $shortsub = htmlspecialchars($subject);
} else {
    $shortsub = _("[No Subject]");
    $imp_headers->addHeader('Subject', $shortsub);
    $title = sprintf(_("%s: %s"), $page_label, $shortsub);
}

/* See if the 'X-Priority' header has been set. */
if (($priority = $imp_headers->getValue('x-priority'))) {
    if (preg_match("/\s*(\d+)\s*/", $priority, $matches)) {
        if (($matches[1] == '1') || ($matches[1] == '2')) {
            $imp_headers->addHeader('Priority', Horde::img('important.gif', _("High Priority"), 'align="absmiddle"') . '&nbsp;' . $priority);
        } elseif (($matches[1] == '4') || ($matches[1] == '5')) {
            $imp_headers->addHeader('Priority', Horde::img('non-important.gif', _("Low Priority"), 'align="absmiddle"') . '&nbsp;' . $priority);
        }
    }
}

/* Determine if all/list headers needed. */
$all_headers = Horde::getFormData('show_all_headers');
$list_headers = Horde::getFormData('show_list_headers');

/* Get the rest of the headers if all headers are requested. */
if ($all_headers) {
    $full_h = $imp_headers->getAllHeaders();
    foreach ($full_h as $head => $val) {
        /* Skip the X-Priority header if we have already dealt with it. */
        if (stristr($head, 'x-priority') &&
            $imp_headers->getValue('priority')) {
            unset($full_h[$head]);
        } elseif ($imp_headers->alteredHeader($head)) {
            $full_h[$head] = $imp_headers->getValue($head);
        } elseif (is_array($val)) {
            $val = array_map('htmlspecialchars', $val);
            $full_h[$head] = '<ul style="margin:0px;padding-left:15px"><li>' . implode("</li>\n<li>", $val) . '</li></ul>';
        } else {
            $full_h[$head] = htmlspecialchars($val);
        }
    }
    ksort($full_h);
}

/* For the self URL link, we can't trust the index in the query string as it
   may have changed if we deleted/copied/moved messages. We may need other
   stuff in the query string, so we need to do an add/remove of 'index'. */
$selfURL = Horde::removeParameter(Horde::selfUrl(true), array('index', 'actionID'));
$selfURL = Horde::addParameter($selfURL, 'index', $index);
$headersURL = Horde::removeParameter($selfURL, array('show_all_headers', 'show_list_headers'));

/* Determine previous message index. */
if (($prev_msg = $imp_mailbox->messageIndices(-1))) {
    $prev_link = IMP_Search::generateSearchUrl('message.php', $prev_msg['thismailbox']);
    $prev_link = Horde::addParameter($prev_link, 'index', $prev_msg['index']);
}

/* Determine next message index. */
if (($next_msg = $imp_mailbox->messageIndices(1))) {
    $next_link = IMP_Search::generateSearchUrl('message.php', $next_msg['thismailbox']);
    $next_link = Horde::addParameter($next_link, 'index', $next_msg['index']);
}

/* Get the starting index for the current message and the message count. */
$msgindex = $imp_mailbox->getMessageIndex();
$msgcount = $imp_mailbox->getMessageCount();

/* Generate the mailbox link. */
$mailbox_link = Horde::addParameter(Horde::applicationUrl('mailbox.php'), 'start', $msgindex);

/* Get the current mailbox name. */
$mailbox_name = IMP::getThisMailbox($array_index);

/* Generate the view link. */
$view_link = IMP_Search::generateSearchUrl('view.php', $mailbox_name);
$view_link = Horde::addParameter($view_link, 'index', $index);

/* Generate the Save Message link. */
$search_params = IMP_Search::getSearchParameters($mailbox_name);
$save_link_array = array_merge(array('actionID' => 'save_message', 'index' => $index), $search_params);
$save_link = $browser->downloadUrl($subject, $save_link_array);

/* Generate the Message Source link. */
if ($conf['user']['allow_view_source']) {
    $base_part = $imp_contents->getMIMEMessage();
    $source_link = $imp_contents->linkViewJS($base_part, 'view_source', _("Message Source"), _("Message Source"), 'widget');
}

/* Generate the link to ourselves. */
$self_link = IMP_Search::generateSearchUrl('message.php', $mailbox_name);
$self_link = Horde::addParameter($self_link, array('index' => $index, 'start' => $msgindex));

/* Generate the print link. */
$print_link = '';
$print_params = array('actionID' => 'print_message', 'index' => $index);
foreach (array_merge($print_params, $search_params) as $key => $val) {
    $print_link = Horde::addParameter($print_link, $key, $val);
}
if (substr($print_link, 0, 1) == '?') {
    $print_link = substr($print_link, 1);
}
$print_link = $browser->escapeJSCode($print_link);

$delete_warning = '';
if ($imp['base_protocol'] == 'pop3') {
    $delete_warning = "return window.confirm('" . addslashes(_("Are you sure you wish to PERMANENTLY delete these messages?")) . "');";
}

require IMP_TEMPLATES . '/common-header.inc';

/* Check for the presence of mailing list information. */
$reply_author = array();
$reply_list = null;
if (($list_exists = $imp_headers->listHeadersExist())) {
    /* See if the List-Post header provides an e-mail address for the list. */
    if ($imp_headers->getValue('list-post')) {
        $reply_list = $imp_headers->parseListHeaders('list-post', true);
    }

    /* If the Reply-to: address is the same as the list address, use the
       user's from address for the "Reply" action. */
    if (!is_null($reply_list) &&
        IMP::bareAddress($reply_list) == IMP::bareAddress(MIME::addrArray2String($imp_headers->getOb('reply_to')))) {
        $reply_author = MIME::addrArray2String($imp_headers->getOb('from'));
    }

    /* See if the mailing list information has been requested to be
       displayed. */
    if ($list_headers || $all_headers) {
        $imp_headers->parseAllListHeaders();
    }
}

/* Build From address links. */
$imp_headers->buildAddressLinks('from', $self_link, true, !$printer_friendly);

/* Build To/Cc/Bcc links. */
$address_headers = array('to' => 'toaddress', 'cc' => 'ccaddress', 'bcc' => 'bccaddress');
foreach ($address_headers as $key => $val) {
    if ($imp_headers->buildAddressLinks($key, $self_link, true, !$printer_friendly)) {
        $msgAddresses[] = $imp_headers->getOb($val);
    }
}

/* Build Reply-To address links. */
if (($reply_to = $imp_headers->buildAddressLinks('reply_to', $self_link, false, !$printer_friendly))) {
    if (!($from = $imp_headers->getValue('from')) || ($from != $reply_to)) {
        $imp_headers->setValue('Reply-to', $reply_to);
    } else {
        $imp_headers->removeHeader('reply-to');
    }
}

/* Set the status information of the message. */
$addresses = array_keys($user_identity->getAllFromAddresses(true));
$identity = null;
$status = '';
if ($imp['base_protocol'] != 'pop3') {
    if (count($msgAddresses)) {
        $identity = $user_identity->getMatchingIdentity($msgAddresses);
        if ($identity !== null) {
            $status .= Horde::img('personal.gif', _("Personal"));
            $identity = (int)$identity;
        }
    }

    /* Set status flags. */
    $flag_array = array('unseen'    => _("Unread"),
                        'answered'  => _("Answered"),
                        'draft'     => _("Draft"),
                        'important' => _("Important"),
                        'deleted'   => _("Deleted"));
    foreach ($flag_array as $flag => $desc) {
        if ($imp_headers->getFlag($flag)) {
            $status .= Horde::img($flag . '.gif', $desc);
        }
    }
}

/* Generate the spam link. */
if ($conf['spam']['reporting']) {
    $spam_link = Horde::addParameter($self_link, array('actionID' => 'spam_report', 'identity' => $identity));
}

/* Show the [black|white]list link if we have functionality enabled. */
$show_blacklist_link = false;
$show_whitelist_link = false;
if ($registry->hasMethod('mail/blacklistFrom')) {
    $show_blacklist_link = true;
}
if ($registry->hasMethod('mail/whitelistFrom')) {
    $show_whitelist_link = true;
}

/* Determine if we need to show the Reply to All link. */
$show_reply_all = true;
if (!MIME::addrArray2String(array_merge($imp_headers->getOb('to'), $imp_headers->getOb('cc')), $addresses)) {
    $show_reply_all = false;
}

if (!$printer_friendly) {
    IMP::menu();
    IMP::status();

    /* Print quota information. */
    if (isset($imp['quota']) && is_array($imp['quota'])) {
        require_once IMP_BASE . '/lib/Quota.php';
        $quotaDriver = &IMP_Quota::singleton($imp['quota']['driver'], $imp['quota']['params']);
        if ($quotaDriver !== false) {
            $quotaDriver->quotaHTML();
        }
    }

    if ($browser->hasFeature('javascript')) {
        require_once IMP_TEMPLATES . '/javascript/open_print_win.js';
    }

    require IMP_TEMPLATES . '/message/navbar_top.inc';
    $nav_id = 1;
    require IMP_TEMPLATES . '/message/navbar_navigate.inc';

    /* Cache the results of the navbar_charset.inc require. */
    ob_start();
    require IMP_TEMPLATES . '/message/navbar_charset.inc';
    $charset_output = ob_get_contents();
    ob_end_clean();
    echo $charset_output;

    /* Cache the results of the navbar_actions.inc require. */
    ob_start();
    require IMP_TEMPLATES . '/message/navbar_actions.inc';
    $actions_output = ob_get_contents();
    ob_end_clean();
    echo $actions_output;

    echo '</table>';
}

/* Generate some variables needed for the templates. */
$downloadall_link = $imp_contents->getDownloadAllLink();
$atc_display = $prefs->getValue('attachment_display');
$show_parts = (!empty($attachments) && (($atc_display == 'list') || ($atc_display == 'both')));

require IMP_TEMPLATES . '/message/headers.inc';
require IMP_TEMPLATES . '/message/message.inc';

if (!$printer_friendly) {
    echo '<table border="0" align="center" width="100%" cellspacing="0" cellpadding="2">';
    echo $actions_output;
    echo $charset_output;
    $nav_id = 2;
    require IMP_TEMPLATES . '/message/navbar_navigate.inc';
    echo '</table></form>';
}
if ($browser->hasFeature('javascript')) {
    require_once IMP_TEMPLATES . '/message/javascript.inc';
    require_once $registry->getParam('templates', 'horde') . '/contents/open_view_win.js';
    if ($printer_friendly) {
        require IMP_TEMPLATES . '/message/print.inc';
    }
}

require IMP_TEMPLATES . '/common-footer.inc';

/* Catch error messages from c-client. */
imap_errors();
