<?php
/**
 * $Horde: imp/mailbox.php,v 2.617.4.3 2005/01/26 09:23:01 jan Exp $
 *
 * Copyright 1999-2005 Charles J. Hagenbuch <chuck@horde.org>
 * Copyright 1999-2005 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.
 */

/**
 * Delete a list of messages.
 */
function _deleteMessages($indices)
{
    global $imp, $mailbox_url;

    if (!empty($indices)) {
        require_once IMP_BASE . '/lib/Message.php';
        $imp_message = &new IMP_Message();
        $imp_message->delete($indices);

        /* For POP3, redirect so that refreshing the page doesn't delete more
           messages accidentally. */
        if ($imp['base_protocol'] == 'pop3') {
            header('Location: ' . Horde::url($mailbox_url, true));
            exit;
        }

        return true;
    }

    return false;
}

/**
 * Stylize a string.
 */
function _stylize($string, $styles)
{
    if (!is_array($styles)) {
        return $string;
    }

    foreach ($styles as $style) {
        if (!empty($style)) {
            $string = '<' . $style . '>' . $string . '</' . $style . '>';
        }
    }

    return $string;
}

/**
 * Output the message summaries.
 */
function _outputSummaries($search_mbox, $msgs)
{
    $template = &new Horde_Template();
    $template->set('idx_separator', IMP_IDX_SEP);
    $template->set('search_mbox', $search_mbox, true);
    $template->set('messages', $msgs, true);

    // Some browsers have trouble with hidden overflow in table cells
    // but not in divs.
    if ($GLOBALS['browser']->hasQuirk('no_hidden_overflow_tables')) {
        $template->set('overflow_begin', '<div class="ohide">');
        $template->set('overflow_end', '</div>');
    } else {
        $template->set('overflow_begin', '');
        $template->set('overflow_end', '');
    }
    echo $template->fetch(IMP_TEMPLATES . '/mailbox/mailbox.html');
}

/**
 * Utility function to return a url for the various images.
 *
 * @param string $name  Image filename.
 *
 * @return string  Link to the folder image.
 */
function _image($name)
{
    global $graphicsdir;
    static $cache = array();

    if (!empty($cache[$name])) {
        return $cache[$name];
    }

    $cache[$name] = Horde::img('tree/' . $name, '', 'style="vertical-align:middle"', $graphicsdir);

    return $cache[$name];
}

$do_filter = false;
$open_compose_window = false;
$set = false;
if (isset($new_lang)) {
    $language = $new_lang;
    $set = true;
}

@define('IMP_BASE', dirname(__FILE__));
require_once IMP_BASE . '/lib/base.php';
require_once IMP_BASE . '/lib/Mailbox.php';
require_once IMP_BASE . '/lib/Search.php';
require_once 'Horde/MIME.php';
require_once 'Horde/Identity.php';
require_once 'Horde/Template.php';
require_once 'Horde/Text.php';

/* Call the mailbox redirection hook, if requested. */
if (!empty($conf['hooks']['mbox_redirect'])) {
    require_once HORDE_BASE . '/config/hooks.php';
    if (function_exists('_imp_hook_mbox_redirect')) {
        $redirect = call_user_func('_imp_hook_mbox_redirect', $imp['mailbox']);
        if (!empty($redirect)) {
            $redirect = Horde::applicationUrl($redirect, true);
            header("Location: " . $redirect);
            exit;
        }
    }
}

/* There is a chance that this page is loaded directly via
 * message.php. If so, don't re-include config files, and the
 * following variables will already be set: $actionID, $start. */
if (!isset($from_message_page)) {
    $actionID = Util::getFormData('actionID');
}

if ($actionID == 'login_compose') {
    $open_compose_window = IMP::openComposeWin();
}

/* Get form data and make sure it's the type that we're expecting. */
$targetMbox = Util::getFormData('targetMbox');
$newMbox = Util::getFormData('newMbox');
if (!is_array(($indices = Util::getFormData('indices')))) {
    $indices = array($indices);
}
$indices_mbox = array($imp['mailbox'] => $indices);

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

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

/* Get the base URL for this page. */
if (isset($from_message_page)) {
    $mailbox_url = Horde::applicationURL('mailbox.php');
} else {
    $mailbox_url = Horde::selfURL();
}

/* Check for 'sortby' and 'sortdir' changes. */
if (($sortby = Util::getFormData('sortby')) !== null) {
    $prefs->setValue('sortby', $sortby);
}
if (($sortdir = Util::getFormData('sortdir')) !== null) {
    $prefs->setValue('sortdir', $sortdir);
}

/* Run through the action handlers */
switch ($actionID) {
case 'blacklist':
    require_once IMP_BASE . '/lib/Filter.php';
    IMP_Filter::blacklistMessage($indices);
    break;

case 'whitelist':
    require_once IMP_BASE . '/lib/Filter.php';
    IMP_Filter::whitelistMessage($indices);
    break;

case 'spam_report':
case 'notspam_report':
    $action = str_replace('_report', '', $actionID);
    require_once IMP_BASE . '/lib/Spam.php';
    $imp_spam = &new IMP_Spam();
    $imp_spam->reportSpam($indices, $action);

    /* Delete spam after report. */
    if (($action == 'spam') && $prefs->getValue('delete_spam_after_report')) {
        if (_deleteMessages($indices_mbox)) {
            $notification->push(sprintf(_("%d message(s) have been deleted."),
                                        count($indices)), 'horde.message');
        }
    }
    break;

case 'message_missing':
    $notification->push(_("Requested message not found."), 'horde.error');
    break;

case 'fwd_digest':
    $options['fwddigest'] = serialize($indices);
    $options['actionID'] = 'fwd_digest';
    $open_compose_window = IMP::openComposeWin($options);
    break;

case 'delete_messages':
    _deleteMessages($indices_mbox);
    break;

case 'undelete_messages':
    if (!empty($indices_mbox)) {
        require_once IMP_BASE . '/lib/Message.php';
        $imp_message = &new IMP_Message();
        $imp_message->undelete($indices_mbox);
    }
    break;

case 'move_messages':
case 'copy_messages':
    if (!empty($indices) && !empty($targetMbox)) {
        require_once IMP_BASE . '/lib/Message.php';
        $imp_message = &new IMP_Message();
        $action = ($actionID == 'move_messages') ? IMP_MESSAGE_MOVE : IMP_MESSAGE_COPY;

        if ($conf['tasklist']['use_tasklist'] &&
            (strpos($targetMbox, '_tasklist_') === 0)) {
            /* If the target is a tasklist, handle the move/copy specially. */
            $tasklist = str_replace('_tasklist_', '', $targetMbox);
            $imp_message->createTasks($tasklist, $action, $indices_mbox);
        } else {
            /* Otherwise, the target is a standard mailbox. */
            if (!empty($newMbox) && ($newMbox == 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, $indices_mbox);
                }
            } else {
                $imp_message->copy($targetMbox, $action, $indices_mbox);
            }
        }
    }
    break;

case 'flag_messages':
    $flag = Util::getPost('flag');
    if (!empty($indices) && !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->flag($_POST['flag'], $indices_mbox, $set);
    }
    break;

case 'hide_deleted':
    $prefs->setValue('delhide', !$prefs->getValue('delhide'));
    break;

case 'expunge_mailbox':
    require_once IMP_BASE . '/lib/Message.php';
    $imp_message = &new IMP_Message();
    $imp_message->expungeMailbox(array($imp['mailbox']));
    break;

case 'filter':
    $do_filter = true;
    break;

case 'empty_mailbox':
    require_once IMP_BASE . '/lib/Message.php';
    $mbox = Util::getFormData('thismailbox', $imp['mailbox']);
    $imp_message = &new IMP_Message();
    $imp_message->emptyMailbox(array($mbox));
    if ($url = Util::getFormData('return_url')) {
        header('Location: ' . str_replace('&amp;', '&', $url));
        exit;
    }
    break;
}

/* Is this a search mailbox? */
$search_mbox = ($imp['mailbox'] == IMP_SEARCH_MBOX);

/* Deal with filter options. */
if ($imp['filteravail']) {
    /* Only allow filter on display for INBOX. */
    if (($imp['mailbox'] == 'INBOX') && $prefs->getValue('filter_on_display')) {
        $do_filter = true;
    } elseif (($imp['mailbox'] == 'INBOX') ||
              ($prefs->getValue('filter_any_mailbox') && !$search_mbox)) {
        $filter_url = Util::addParameter($mailbox_url, 'actionID', 'filter');
    }
}

/* Run filters now. */
if ($do_filter) {
    require_once IMP_BASE . '/lib/Filter.php';
    IMP_Filter::filter($imp['mailbox']);
}

/* Generate folder options list. */
if ($conf['user']['allow_folders']) {
    $folder_options = IMP::flistSelect(_("Messages to"), true, array(null, $imp['mailbox']), null, true, true);
}

/* Get the start index. It may already be set from message.php. */
if (!isset($from_message_page)) {
    $start = Util::getFormData('start');
}

/* Build the list of messages in the mailbox. */
if (!isset($imp_mailbox)) {
    $imp_mailbox = &new IMP_Mailbox();
}
$pageOb = $imp_mailbox->buildMailboxPage(Util::getFormData('page'), $start);

/* Cache this value since we use it alot on this page. */
$graphicsdir = $registry->getImageDir('horde');

/* Generate First/Previous page links. */
if ($pageOb->page == 1) {
    $pages_first = Horde::img('nav/first-grey.png', '', 'width="16" height="16" align="middle"', $graphicsdir);
    $pages_prev = Horde::img('nav/left-grey.png', '', 'width="16" height="16" align="middle"', $graphicsdir);
} else {
    $first_url = Util::addParameter($mailbox_url, 'page', 1);
    $pages_first = Horde::link($first_url, _("First Page")) . Horde::img('nav/first.png', '<<', array('title' => _("First Page"), 'width' => '16', 'height' => '16', 'align' => 'middle'), $graphicsdir) . '</a>';
    $prev_url = Util::addParameter($mailbox_url, 'page', $pageOb->page - 1);
    $pages_prev = Horde::link($prev_url, _("Previous Page"), '', '', '', '', '', array('id' => 'prev')) . Horde::img('nav/left.png', '<', array('title' => _("Previous Page"), 'width' => '16', 'height' => '16', 'align' => 'middle'), $graphicsdir) . '</a>';
}

/* Generate Next/Last page links. */
if ($pageOb->page == $pageOb->pagecount) {
    $pages_last = Horde::img('nav/last-grey.png', '', 'width="16" height="16" align="middle"', $graphicsdir);
    $pages_next = Horde::img('nav/right-grey.png', '', 'width="16" height="16" align="middle"', $graphicsdir);
} else {
    $next_url = Util::addParameter($mailbox_url, 'page', $pageOb->page + 1);
    $pages_next = Horde::link($next_url, _("Next Page"), '', '', '', '', '', array('id' => 'next')) . Horde::img('nav/right.png', '>', array('title' => _("Next Page"), 'width' => '16', 'height' => '16', 'align' => 'middle'), $graphicsdir) . '</a>';
    $last_url = Util::addParameter($mailbox_url, 'page', $pageOb->pagecount);
    $pages_last = Horde::link($last_url, _("Last Page")) . Horde::img('nav/last.png', '>>', array('title' => _("Last Page"), 'width' => '16', 'height' => '16', 'align' => 'middle'), $graphicsdir) . '</a>';
}

/* Determine if we are going to show the Hide/Purge Deleted Message links. */
$showdelete = $imp_mailbox->showDeleteLinks();
if ($showdelete && !$prefs->isLocked('delhide')) {
    if ($prefs->getValue('delhide')) {
        $deleted_prompt = _("Show Deleted");
    } else {
        $deleted_prompt = _("Hide Deleted");
    }
}

/* Generate mailbox summary string. */
if (!empty($pageOb->end)) {
    $msg_count = sprintf(_("%d to %d of %d Messages"), $pageOb->begin, $pageOb->end, $pageOb->msgcount);
} else {
    $msg_count = sprintf(_("No Messages"));
}

/* If user wants the mailbox to be refreshed, set time here. */
$refresh_time = $prefs->getValue('refresh_time');
$refresh_url = Util::addParameter($mailbox_url, 'page', $pageOb->page);
if (isset($filter_url)) {
    $filter_url = Util::addParameter($filter_url, 'page', $pageOb->page);
}

/* Set the folder for the sort links. */
$sortdir = $prefs->getValue('sortdir');
$sort_url = Util::addParameter($mailbox_url, 'sortdir', ($sortdir) ? 0 : 1);

/* Determine if we are showing previews. */
$show_preview = $imp_mailbox->showPreviews();
$preview_tooltip = ($show_preview) ? $prefs->getValue('preview_show_tooltip') : false;
if ($preview_tooltip) {
    Horde::addScriptFile('tooltip.js', 'horde', true);
} else {
    $strip_preview = $prefs->getValue('preview_strip_nl');
}

$unread = $imp_mailbox->unseenMessageCount();
$title = IMP::getLabel();
$refresh_title = sprintf(_("_Refresh %s"), $title);
$refresh_ak = Horde::getAccessKey($refresh_title);
$refresh_title = Horde::stripAccessKey($refresh_title);
if (!empty($refresh_ak)) {
    $refresh_title .= sprintf(_(" (Accesskey %s)"), $refresh_ak);
}
if ($unread) {
    $title .= ' (' . $unread . ')';
}
Horde::addScriptFile('keybindings.js', 'horde');
require IMP_TEMPLATES . '/common-header.inc';
require IMP_TEMPLATES . '/menu.inc';
if ($browser->hasFeature('javascript')) {
    require IMP_TEMPLATES . '/mailbox/javascript.inc';
}
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) {
        $quota = $quotaDriver->getQuota();
        require IMP_TEMPLATES . '/quota/quota.inc';
    }
}

/* Build the array of message information. */
$mailboxOverview = $imp_mailbox->buildMailboxArray($pageOb->begin, $pageOb->index, $pageOb->end, $imp_mailbox->getSorted(), $imp_mailbox->getSortedMbox());

/* Are we currently in the trash mailbox? */
$preamble = IMP::preambleString();
$use_trash = $prefs->getValue('use_trash');
$trashMbox = ($use_trash && ($imp['mailbox'] == ($preamble . $prefs->getValue('trash_folder'))));

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

require IMP_TEMPLATES . '/mailbox/header.inc';

/* If no messages, exit immediately. */
if (empty($pageOb->end)) {
    if ($pageOb->anymsg && isset($deleted_prompt)) {
        /* Show 'Show Deleted' prompt if mailbox has no viewable message but
           has hidden, deleted messages. */
        require IMP_TEMPLATES . '/mailbox/actions_deleted.inc';
    }
    require IMP_TEMPLATES . '/mailbox/empty_mailbox.inc';
    require IMP_TEMPLATES . '/mailbox/footer.inc';
    require $registry->get('templates', 'horde') . '/common-footer.inc';
    exit;
}

/* If there is more than 15 messages , cache the actions output. */
if ($pageOb->msgcount != 0) {
    $navform = 1;
    require IMP_TEMPLATES . '/mailbox/navbar.inc';
    if ($pageOb->msgcount > 15) {
        ob_start();
        require IMP_TEMPLATES . '/mailbox/actions.inc';
        $actions_output = ob_get_contents();
        ob_end_clean();
        echo $actions_output;
    } else {
        require IMP_TEMPLATES . '/mailbox/actions.inc';
    }
}

/* Define some variables now so we don't have to keep redefining in the
   foreach() loop or the templates. */
$curr_time = time();
$curr_time -= $curr_time % 60;
$drafts_sm_folder = $imp_mailbox->isSpecialFolder();
$lastMbox = '';
$messages = array();
$threadlevel = array();

/* Determine sorting preferences. */
$sortby = $imp_mailbox->sortby();
$thread_sort = ($sortby == SORTTHREAD);
$sortlimit = $imp_mailbox->aboveSortLimit();

/* Get thread object, if necessary. */
if ($thread_sort) {
    $threadob = $imp_mailbox->getThreadOb();
    $last_level = $last_thread = null;
}

/* Don't show header row if this is a search mailbox or if no messages in the
   current mailbox. */
if (!$search_mbox && ($pageOb->msgcount != 0)) {
    require IMP_TEMPLATES . '/mailbox/message_headers.inc';
}

/* Cache some repetitively used variables. */
$datefmt = $prefs->getValue('date_format');
$timefmt = $prefs->getValue('time_format');
$fromlinkstyle = $prefs->getValue('from_link');
$localeinfo = NLS::getLocaleInfo();

/* Display message information. */
$msgs = array();
foreach ($mailboxOverview as $msgIndex => $message) {
    if ($search_mbox) {
        if (empty($lastMbox) || ($message['mbox'] != $lastMbox)) {
            if (!empty($lastMbox)) {
                _outputSummaries($search_mbox, $msgs);
                $msgs = array();
            }
            $folder_link = Horde::url(Util::addParameter('mailbox.php', 'mailbox', $message['mbox']));
            $folder_link = Horde::link($folder_link, sprintf(_("View messages in %s"), IMP::displayFolder($message['mbox'])), 'smallheader') . IMP::displayFolder($message['mbox']) . '</a>';
            require IMP_TEMPLATES . '/mailbox/searchfolder.inc';
            require IMP_TEMPLATES . '/mailbox/message_headers.inc';
        }
        $lastMbox = $message['mbox'];
    }

    /* Initialize the header fields. */
    $msg = array(
        'color' => (isset($message['color'])) ? $message['color'] : '',
        'date' => '&nbsp;',
        'from' => '&nbsp;',
        'mbox' => $message['mbox'],
        'preview' => '',
        'size' => '?',
        'subject' => _("[No Subject]")
    );

    /* Initialize some other variables. */
    $attachment = false;
    $from_adr = null;
    $mailto_link = false;
    $showfromlink = true;

    /* Now pull the IMAP header values into them, decoding them at
       the same time. */
    $h = $message['header'];
    $messages[] = $h->uid;

    /* Formats the header date string nicely. */
    if (empty($h->date) || (($udate = strtotime($h->date, $curr_time)) == -1)) {
        $msg['date'] = _("Unknown Date");
    } else {
        if ((date('Y') != @date('Y', $udate)) ||
            (date('M') != @date('M', $udate)) ||
            (date('d') != @date('d', $udate))) {
            /* Not today, use the date. */
            $msg['date'] = strftime($datefmt, $udate);
        } else {
            /* Else, it's today, use the time. */
            $msg['date'] = strftime($timefmt, $udate);
        }
    }

    /* Format the from header. */
    if (isset($h->from)) {
        $from_adr = IMP::bareAddress($h->from);
        $from_ob = array_shift(imap_rfc822_parse_adrlist($h->from, ''));
        if (is_null($from_adr)) {
            $msg['from'] = _("Invalid Address");
            $showfromlink = false;
        } elseif ($identity->hasAddress($from_adr)) {
            if (isset($h->to)) {
                if (strstr($h->to, 'undisclosed-recipients:')) {
                    $msg['from'] = _("Undisclosed Recipients");
                    $showfromlink = false;
                } else {
                    $tmp = array_shift(imap_rfc822_parse_adrlist($h->to, ''));
                    if (isset($tmp->personal)) {
                        $msg['from'] = MIME::decode($tmp->personal, NLS::getCharset());
                    } else {
                        $msg['from'] = IMP::bareAddress($h->to);
                    }
                    $msg['fullfrom'] = MIME::decode($h->to, NLS::getCharset());
                }
            } else {
                $msg['from'] = _("Undisclosed Recipients");
                $showfromlink = false;
            }
            if (!$drafts_sm_folder) {
                $msg['from'] = _("To") . ': ' . $msg['from'];
            }
            $mailto_link = true;
        } elseif (isset($from_ob->personal)) {
            $msg['from'] = trim(MIME::decode($from_ob->personal, NLS::getCharset()), '"');
            if (!trim($msg['from'], chr(160) . ' ')) {
                $msg['from'] = $from_adr;
            }
            $msg['fullfrom'] = MIME::decode($h->from, NLS::getCharset());
        } else {
            if (!isset($from_ob->host) ||
                (strstr($from_ob->host, 'SYNTAX-ERROR') !== false)) {
                $msg['from'] = (!empty($from_adr)) ? $from_adr : _("Unknown Recipient");
                $showfromlink = false;
            } else {
                $msg['from'] = $from_adr;
                $msg['fullfrom'] = MIME::decode($h->from, NLS::getCharset());
            }
        }
    } else {
        $msg['from'] = _("Invalid Address");
        $showfromlink = false;
    }

    if (!empty($h->subject)) {
        $msg['subject'] = strtr(MIME::decode($h->subject, NLS::getCharset()), "\t", ' ');
    }
    $msg['fullsubject'] = $msg['subject'];

    if (isset($h->size)) {
        $msg['size'] = ($h->size > 1024)
            ? sprintf(_("%s KB"), number_format($h->size / 1024, 0, $localeinfo['decimal_point'], $localeinfo['thousands_sep']))
            : $h->size;
    }

    /* Filter the subject text, if requested. */
    $msg['subject'] = IMP::filterText($msg['subject']);
    $msg['fullsubject'] = IMP::filterText($msg['fullsubject']);

    if (isset($message['structure'])) {
        if (!empty($message['structure']->subtype)) {
            if (String::lower($message['structure']->subtype) == 'signed' ||
                String::lower($message['structure']->subtype) == 'encrypted') {
                $attachment = 'signed';
            } elseif (String::lower($message['structure']->subtype) == 'alternative') {
                /* Treat this as no attachments. */
            } elseif (isset($message['structure']->parts) &&
                      is_array($message['structure']->parts) &&
                      count($message['structure']->parts) > 0) {
                $attachment = 'attachment';
            } elseif ((!empty($message['structure']->type) &&
                       $message['structure']->type != TYPETEXT) ||
                      !empty($message['structure']->subtype) &&
                      String::lower($message['structure']->subtype) != 'plain') {
                $attachment = 'attachment';
            }
        }
    }

    /* Generate the target link. */
    $msgMbox = isset($message['mbox']) ? $message['mbox'] : '';
    $target = IMP_Search::generateSearchUrl('message.php', $msgMbox);
    $target = Util::addParameter($target, 'index', $h->uid);

    /* Get all the flag information. */
    $msg['bg'] = 'seen';
    $msg['status'] = '';
    $flagbits = 0;
    $style = array();
    $xprio = false;

    /* Check for X-Priority information. */
    if ($conf['mailbox']['show_xpriority']) {
        require_once IMP_BASE . '/lib/MIME/Headers.php';
        $imp_headers = &new IMP_Headers($h->uid);
        $imp_headers->buildHeaders();
        $imp_headers->buildFlags();
        if (($priority = $imp_headers->getValue('x-priority'))) {
            if (preg_match('/\s*(\d+)\s*/', $priority, $matches)) {
                if (($matches[1] == '1') || ($matches[1] == '2')) {
                    $xprio = 'high';
                } elseif (($matches[1] == '4') || ($matches[1] == '5')) {
                    $xprio = 'low';
                }
            }
        }
    }

    if ($imp['base_protocol'] != 'pop3') {
        if (!empty($h->to) && $identity->hasAddress(IMP::bareAddress($h->to))) {
            $msg['status'] .= Horde::img('mail_personal.png', _("Personal"));
            $flagbits |= IMP_PERSONAL;
        }
        if (!$h->seen || $h->recent) {
            $flagbits |= IMP_UNSEEN;
            $msg['status'] .= Horde::img('mail_unseen.png', _("Unseen"));
            $style[] = 'b';
            $msg['bg'] = 'unseen';
        }
        if ($h->answered) {
            $flagbits |= IMP_ANSWERED;
            $msg['status'] .= Horde::img('mail_answered.png', _("Answered"));
            $msg['bg'] = 'answered';
        }
        if ($h->draft) {
            $flagbits |= IMP_DRAFT;
            $msg['status'] .= Horde::img('mail_draft.png', _("Draft"));
            $target = IMP::composeLink(array(), array('actionID' => 'draft', 'mailbox' => $imp['mailbox'], 'index' => $h->uid));
        }
        if ($xprio == 'high') {
            $flagbits |= IMP_FLAGGED;
            $msg['status'] .= Horde::img('mail_priority_high.png', _("High Priority"));
            $msg['bg'] = 'important';
        } elseif ($xprio == 'low') {
            $msg['status'] .= Horde::img('mail_priority_low.png', _("Low Priority"));
            $style[] = 'i';
        }
        if ($h->flagged) {
            $flagbits |= IMP_FLAGGED;
            $msg['status'] .= Horde::img('mail_flagged.png', _("Important"));
            $style[] = 'i';
            $msg['bg'] = 'important';
        }
        if ($h->deleted) {
            $flagbits |= IMP_DELETED;
            $msg['status'] .= Horde::img('mail_deleted.png', _("Deleted"));
            $style[] = 'strike';
            $msg['bg'] = 'deleted';
        }
        $flags[] = $flagbits;
    } else {
        $flags[] = 0;
    }

    if ($conf['mailbox']['show_attachments'] && $attachment) {
        $msg['status'] .= Horde::img($attachment . '.png', _("Attachment"));
    }


    /* Set the message number. */
    $msg['number'] = $h->msgno;

    /* Show message preview? */
    if ($show_preview) {
        $msg['preview'] = $message['preview'];
        if (!$preview_tooltip) {
            if (!$strip_preview) {
                $msg['preview'] = str_replace(' ', '&nbsp;', $msg['preview']);
            }
            $msg['preview'] = nl2br($msg['preview']);
        }
    }

    /* Format the Date: Header. */
    $msg['date'] = _stylize($msg['date'], $style);

    /* Format the From: Header. */
    $msg['from'] = _stylize(htmlspecialchars($msg['from']), $style);
    if ($showfromlink) {
        switch ($fromlinkstyle) {
        case 0:
            $extra = array('actionID' => 'mailto', 'mailbox' => $imp['mailbox'], 'index' => $h->uid, 'mailto' => $mailto_link);
            if ($search_mbox) {
                $extra['thismailbox'] = $mailboxOverview[$msgIndex]['mbox'];
            }
            $msg['from'] = Horde::link(IMP::composeLink(array(), $extra), sprintf(_("Compose Message (%s)"), $msg['fullfrom'])) . $msg['from'] . '</a>';
            break;

        case 1:
            $from_uri = IMP_Search::generateSearchUrl('message.php', $msgMbox);
            $from_uri = Util::addParameter($from_uri, 'index', $h->uid);
            $msg['from'] = Horde::link($from_uri, $msg['fullfrom']) . $msg['from'] . '</a>';
            break;
        }
    }

    /* Format the Subject: Header. */
    $msg['subject'] = _stylize(Text::htmlSpaces($msg['subject']), $style);
    if ($preview_tooltip) {
        $msg['subject'] = substr(Horde::linkTooltip($target, $msg['fullsubject'], '', '', '', $msg['preview']), 0, -1) . ' id="subject' . $h->uid . '">' . $msg['subject'] . '</a>';
    } else {
        $msg['subject'] = substr(Horde::link($target, $msg['fullsubject']), 0, -1) . ' id="subject' . $h->uid . '">' . $msg['subject'] . '</a>' . (!empty($msg['preview']) ? '<br /><small>' . $msg['preview'] . '</small>' : '');
    }

    /* Set up threading tree now. */
    if ($thread_sort && !$search_mbox) {
        $indentBase = $threadob->getThreadBase($h->uid);
        if (!empty($indentBase)) {
            $indentLevel = $threadob->getThreadIndent($h->uid);
            if ($indentLevel > 1) {
                $lines = '';
                $lastinlevel = $threadob->lastInLevel($h->uid);
                if ($sortdir) {
                    if ($indentBase != $last_thread) {
                        $threadLevel = array();
                        $last_thread = $indentBase;
                        for ($i = 1; $i <= $indentLevel; $i++) {
                            $threadLevel[$i] = true;
                        }
                    } elseif ($indentLevel > $last_level) {
                        $threadLevel[$last_level] = false;
                        for ($i = ($last_level + 1); $i <= $indentLevel; $i++) {
                            $threadLevel[$i] = true;
                        }
                    }
                    $last_level = $indentLevel;
                    $lastinlevel = !$lastinlevel;
                    $join_img = ($lastinlevel) ? 'join.png' : 'joinbottom-down.png';
                } else {
                    $join_img = ($lastinlevel) ? 'joinbottom.png' : 'join.png';
                }
                $threadLevel[$indentLevel] = $lastinlevel;
                for ($i = 2; $i < $indentLevel; $i++) {
                    $lines .= _image(!isset($threadLevel[$i]) || ($threadLevel[$i]) ? 'blank.png' : 'line.png');
                }
                $msg['subject'] = $lines . _image($join_img) . ' ' . $msg['subject'];
            }
        }
    }

    /* We need the uid so the checkboxes will work. */
    $msg['uid'] = $h->uid;

    $msgs[] = $msg;
}

_outputSummaries($search_mbox, $msgs);
require IMP_TEMPLATES . '/mailbox/message_footers.inc';

if ($prefs->getValue('show_legend') && ($imp['base_protocol'] != 'pop3')) {
    require IMP_TEMPLATES . '/mailbox/legend.inc';
}

/* If there are 15 messages or less, don't show the actions/navbar
 * again. */
if (isset($actions_output)) {
    echo $actions_output;
    $navform = 2;
    require IMP_TEMPLATES . '/mailbox/navbar.inc';
} else {
    echo '<tr><td class="control" colspan="6"></td></tr>';
}

require IMP_TEMPLATES . '/mailbox/footer.inc';

if ($prefs->getValue('nav_popup') &&
    ($newmsgs = $imp_mailbox->newMessageCount())
    && ($newmsgs > 0) &&
    !Util::getFormData('no_newmail_popup')) {
    require IMP_TEMPLATES . '/mailbox/alert.inc';
}

if (!empty($open_compose_window)) {
    $args = 'popup=1';
    if (isset($options)) {
        foreach ($options as $arg => $value) {
            $args .= !empty($value) ? '&' . $arg . '=' . urlencode($value) : '';
        }
    }
    foreach (IMP::getComposeArgs() as $arg => $value) {
        $args .= !empty($value) ? '&' . $arg . '=' . urlencode($value) : '';
    }
    echo "<script language='JavaScript' type='text/javascript'>open_compose_win('" . addslashes($args) . "'); focus_compose_win();</script>";
}

require $registry->get('templates', 'horde') . '/common-footer.inc';
