<?php
/*
 * $Horde: imp/message.php,v 2.257.2.43 2003/06/18 01:29:16 jan 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.
 */

define('IMP_BASE', dirname(__FILE__));
require_once IMP_BASE . '/lib/base.php';
require_once IMP_BASE . '/lib/Message.php';
require_once HORDE_BASE . '/lib/MIME.php';
require_once HORDE_BASE . '/lib/MIME/Structure.php';
require_once HORDE_BASE . '/lib/MIME/Part.php';
require_once HORDE_BASE . '/lib/MIME/Viewer.php';
require_once HORDE_BASE . '/config/mime_drivers.php';
require_once HORDE_BASE . '/config/mime_mapping.php';
require_once IMP_BASE . '/config/mime_drivers.php';
require_once IMP_BASE . '/lib/Identity/IMP.php';

if (empty($notification)) {
    require_once HORDE_BASE . '/lib/Notification.php';
    $notification = &Notification::singleton();
    $notification->attach('status');
}
$show_whitelist = $registry->hasMethod('filter/whitelistFrom');

/**
 * Builds a string containing a list of addresses.  Each address is a link
 * to the compose function.
 *
 * @param array $array   Array of address objects.
 * @param boolean $icon  Show addressbook icon?
 *
 * @return string  String containing the formatted address list.
 */
function buildAddressLinks($array, $icon)
{
    global $imp, $registry, $prefs, $index, $array_index;

    $ret = '';

    /* Set up the add address icon link if contact manager is available. */
    if ($icon &&
        $registry->hasMethod('contacts/add') &&
        $prefs->getValue('add_source')) {
        $add_link = Horde::applicationUrl('message.php');
        $add_link = IMP::addParameter($add_link, 'index=' . $index);
        $add_link = IMP::addParameter($add_link, 'array_index=' . $array_index);
        $add_link = IMP::addParameter($add_link, 'actionID=' . ADD_ADDRESS);
        if ($imp['mailbox'] == '**search') {
            $add_link = IMP::addParameter($add_link, 'thismailbox=' . urlencode(IMP::getThisMailbox()));
        }
    }

    foreach ($array as $ob) {
        /* Ensure we're working with initialized values. */
        $ob->personal = isset($ob->personal) ? MIME::decode($ob->personal) : '';
        if (isset($ob->mailbox)) {
            if (stristr($ob->mailbox, 'UNEXPECTED_DATA_AFTER_ADDRESS')) {
                continue;
            }
        } else {
            $ob->mailbox = '';
        }
        if (!isset($ob->host)) {
            $ob->host = '';
        }

        /* Get full address ($addr) and the trimmed, bare address ($inner). */
        $addr = IMP::addrObject2String($ob, 'undisclosed-recipients@');
        $inner = Mime::trimEmailAddress(IMP::rfc822WriteAddress($ob->mailbox,
                    $ob->host, ''));

        /* Separate multiple addresses with a comma. */
        if (!empty($ret)) {
            $ret .= ', ';
        }

        if (!empty($addr) && !empty($inner)) {
            /* If this is an incomplete e-mail address, don't link anywhere. */
            if (stristr($ob->host, 'UNKNOWN')) {
                $ret .= $addr;
            } else {
                $ret .= Horde::link(IMP::composeLink(array('to' => $addr)), sprintf(_("Compose Message (%s)"), $inner));
                $ret .= htmlspecialchars($addr) . '</a>';

                /* Append the add address icon to every address if contact
                   manager is available. */
                if (isset($add_link)) {
                    $curr_link = IMP::addParameter($add_link, 'name=' . urlencode($ob->personal));
                    $curr_link = IMP::addParameter($curr_link, 'address=' . urlencode($inner));
                    $ret .= Horde::link($curr_link, sprintf(_("Add to Addressbook (%s)"), $inner));
                    $ret .= Horde::img('addressbook-blue.gif', 'hspace="2"') . '</a>';
                }
            }
        }
    }

    /*
     * If we're left with an empty address list ($ret), inform the user that
     * the recipient list is purposely "undisclosed".
     */
    if (empty($ret)) {
        $ret = _("Undisclosed Recipients");
    }

    return $ret;
}

/**
 * Given two alternative parts, determine which one should be
 * displayed.
 *
 * Return true if $a is preferred to $b
 */
function selectAlternativePart($a, $b)
{
    // Prefer a richer type than text.
    return ($b->type == TYPETEXT && canDisplayInline($a));
}

/**
 * Return true if the encoding is 7bit, 8bit, qprint, or base64.
 */
function isValidEncoding($encoding)
{
    return ($encoding == ENC7BIT ||
            $encoding == ENC8BIT ||
            $encoding == ENCQUOTEDPRINTABLE ||
            $encoding == ENCBINARY ||
            $encoding == ENCBASE64);
}

/**
 * Determine if we can (and know how to) inline a mime part.
 */
function canDisplayInline(&$mime)
{
    /* Attach a mime_viewer object to this MIME entry */
    IMP::resolveMimeViewer($mime);

    /* Check to see if the MIME headers allow it to be inlined */
    if ((!$mime->header) &&
        ($mime->disposition == 'inline') &&
        isValidEncoding($mime->encoding)) {

        /* If the driver allows inline displaying of this type, then
         * return success */
        if (isset($mime->viewer->conf['inline']) && $mime->viewer->conf['inline']) {
            return true;
        }
    }

    /* This MIME type cannot be displayed inline */
    return false;
}

/**
 * Build the body of a message from a given part.
 */
function buildMessageBody(&$mime, $attachments)
{
    if (isset($mime->viewer)) {
        $mime->part->setContents(IMP::getDecodedPart($mime));
        return $mime->viewer->render($mime);
    } else {
        return false;
    }
}

function buildMessage($attachments, $msg)
{
    global $inline_parts, $atc, $index;

    // displayParts contains the parts that we should display, after filtering out alternative parts
    $displayParts = array();

    // determine which is the alternative parts to show
    foreach ($attachments as $ref => $mime) {
        if (!isset($displayParts[$mime->alternative]) || selectAlternativePart($mime, $displayParts[$mime->alternative])) {
            $displayParts[!empty($mime->alternative) ? $mime->alternative : $ref] = $mime;
        }
    }

    // now display the parts
    foreach ($displayParts as $ref => $mime) {
        if (!$mime->header) {
            if (canDisplayInline($mime)) {
                $body = buildMessageBody($mime, $attachments);
                if ($inline_parts > 0) {
                    $msg .= '</td></tr><tr><td align="left"><br /><table border="0">' . IMP::partSummary($mime, $index) . '</table></td></tr><tr><td class="text" align="left">' . $body;
                } elseif (!($mime->type == TYPETEXT && $mime->subtype == 'plain')) {
                    $msg = '<tr><td align="left"><table border="0">' . IMP::partSummary($mime, $index) . '</table></td></tr><tr><td class="text" align="left">' . $body;
                } else {
                    $msg = '<tr><td class="text" align="left">' . $body;
                }
                $inline_parts++;
            } else {
                // Not displaying inline; add to the attachments list.
                $atc .= IMP::partSummary($mime, $index);
            }
        }
    }
    return $msg;
}

IMP::checkAuthentication();

$index = Horde::getFormData('index');
if (array_key_exists('msgl', $imp)) {
    $sorted = explode(':', $imp['msgl']);
    if (!is_null($index)) {
        if ($imp['mailbox'] == '**search') {
            $folders = explode(':', $imp['messagefolders']);
            for ($i = 0; $i < count($sorted); $i++) {
                if ($sorted[$i] == $index && $folders[$i] == $imp['thismailbox']) {
                    $array_index = $i;
                    break;
                }
            }
        } else {
            $indices = array_flip($sorted);
            if (array_key_exists($index, $indices)) {
                $array_index = $indices[$index];
            }
        }
    }
}
if (!isset($array_index)) {
    header('Location: ' . Horde::applicationUrl('mailbox.php?actionID=' . MESSAGE_MISSING, true));
    exit;
}
$actionID = Horde::getFormData('actionID', NO_ACTION);

/* Update uidvalidity. */
$status = imap_status($imp['stream'], IMP::serverString() . $imp['mailbox'], SA_UIDVALIDITY);
$uidsvalid = true;
if (empty($imp['uidvalidity']) || $imp['uidvalidity'] != $status->uidvalidity) {
    $uidsvalid = false;
    $imp['uidvalidity'] = $status->uidvalidity;
}

if ($imp['mailbox'] != '**search') {
    if (!$uidsvalid ||
        $array_index == count($sorted) - 1 ||
        $array_index == 0 ||
        (($actionID == DELETE_MESSAGES || $actionID == MOVE_MESSAGES || $actionID == COPY_MESSAGES) &&
         ($array_index == count($sorted) - 2))) {

        if ($prefs->getValue('sortby') != SORTTHREAD) {
            if ($prefs->getValue('delhide')) {
                $sorted = imap_sort($imp['stream'], $prefs->getValue('sortby'),
                                    $prefs->getValue('sortdir'), SE_UID, 'UNDELETED');
            } else {
                $sorted = imap_sort($imp['stream'], $prefs->getValue('sortby'),
                                    $prefs->getValue('sortdir'), SE_UID);
            }
        } else {
            IMP_Message::threadSort();
        }

        $sorted = IMP_Message::range($sorted, $array_index + $imp['offset'] + 1,
                                     $imp['offset'], $array_index, $imp['msgcount']);
        $imp['msgl'] = implode(':', $sorted);
        $sorted = explode(':', $imp['msgl']);
        $indices = array_flip($sorted);
        $array_index = $indices[$index];
    }
}

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

/* Set the current time zone. */
if ($prefs->getValue('timezone') != '') {
    putenv('TZ=' . $prefs->getValue('timezone'));
}

/* Initialize the user's identities */
$user_identity = new Identity_IMP();

/* Run through action handlers */
switch ($actionID) {
 case NO_ACTION:
     break;

 case IMP_BLACKLIST:
     if ($registry->hasMethod('filter/blacklistFrom')) {
         $addresses = array();
         $h = @imap_header($imp['stream'], imap_msgno($imp['stream'], $index));
         if (isset($h->from[0])) {
             $ob = $h->from[0];
             $addr = Mime::trimEmailAddress(IMP::rfc822WriteAddress($ob->mailbox, $ob->host, ''));
             $addresses[] = trim($addr);
             $registry->call('filter/blacklistFrom', array($addresses));
         }
     } else {
         $filters = @unserialize($prefs->getValue('filters'));
         $h = @imap_header($imp['stream'], imap_msgno($imp['stream'], $index));
         if (isset($h->from[0])) {
             $ob = $h->from[0];
             $addr = Mime::trimEmailAddress(IMP::rfc822WriteAddress($ob->mailbox, $ob->host, ''));
             $filters[] = array('fields' => array('from'), 'text' => trim($addr), 'action' => 'delete');
         }
         $prefs->setValue('filters', serialize($filters));
         $prefs->store();
         header('Location: ' . Horde::applicationUrl('filters.php'));
         exit;
     }
     break;

 case IMP_WHITELIST:
     if ($show_whitelist) {
         $addresses = array();
         $h = @imap_header($imp['stream'], imap_msgno($imp['stream'], $index));
         if (isset($h->from[0])) {
             $ob = $h->from[0];
             $addr = Mime::trimEmailAddress(IMP::rfc822WriteAddress($ob->mailbox, $ob->host, ''));
             $addresses[] = trim($addr);
             $registry->call('filter/whitelistFrom', array($addresses));
         }
     }
     break;

 case PRINT_MESSAGE:
     $printer_friendly = true;
     break;

 case UNDELETE_MESSAGES:
     IMP_Message::undelete($index);
     $array_index++;
     $index = $sorted[$array_index];
     break;

 case DELETE_MESSAGES:
     if (!IMP_Message::delete($index)) {
         $array_index++;
         $index = $sorted[$array_index];
     } else {
         if ($prefs->getValue('use_trash')) {
             /* Nuke the message we've just deleted from the
                message array. */
             $sorted = array_merge(array_slice($sorted, 0, $array_index),
                                   array_slice($sorted, $array_index + 1));
             $imp['msgl'] = implode(':', $sorted);
             $imp['msgcount']--;
             $index = $sorted[$array_index];
         } elseif (strstr($imp['protocol'], 'pop3')) {
             /* IMP_Message::delete() takes care of expunging the
                mailbox to make the delete stick; now we just need
                to recalculate the message list. */
             if ($prefs->getValue('sortby') != SORTTHREAD) {
                 $sorted = imap_sort($imp['stream'], $prefs->getValue('sortby'), $prefs->getValue('sortdir'), SE_UID);
             } else {
                 IMP_Message::threadSort();
             }
             $sorted = IMP_Message::range($sorted, $array_index + $imp['offset'] + 1,
                                          $imp['offset'], $array_index, $imp['msgcount']);
             $imp['msgl'] = implode(':', $sorted);
             $index = $sorted[$array_index];
         } elseif ($prefs->getValue('delhide')) {
             if ($prefs->getValue('sortby') != SORTTHREAD) {
                 $sorted = imap_sort($imp['stream'], $prefs->getValue('sortby'),
                                     $prefs->getValue('sortdir'), SE_UID, 'UNDELETED');
             } else {
                 IMP_Message::threadSort();
             }
             $sorted = IMP_Message::range($sorted, $array_index + $imp['offset'] + 1,
                                          $imp['offset'], $array_index, $imp['msgcount']);
             $imp['msgl'] = implode(':', $sorted);
             $index = $sorted[$array_index];
         } else {
             $array_index++;
             $index = $sorted[$array_index];
         }
     }
     if ($prefs->getValue('mailbox_return')) {
         header('Location: ' . Horde::applicationUrl('mailbox.php?start=' . ($array_index + $imp['offset'] + 1), true));
         exit;
     }
     break;

 case MOVE_MESSAGES:
 case COPY_MESSAGES:
     if (($targetMbox = Horde::getFormData('targetMbox')) !== null) {
         if (Horde::getFormData('newMbox', 0) == 1) {
             $new_mailbox = IMP::addPreambleString(IMP::utf7Encode($targetMbox));

             include_once IMP_BASE . '/lib/Folder.php';
             if (IMP_Folder::create($imp['stream'],
                                    $new_mailbox,
                                    $prefs->getValue('subscribe'))) {
                 unset($imp['imaptree']);
                 IMP_Message::copy($new_mailbox, array($index), $actionID);
             }
         } else {
             IMP_Message::copy($targetMbox, array($index), $actionID);
         }
         if ($actionID == MOVE_MESSAGES && $prefs->getValue('delhide')) {
             if ($prefs->getValue('sortby') != SORTTHREAD) {
                 $sorted = imap_sort($imp['stream'], $prefs->getValue('sortby'),
                                     $prefs->getValue('sortdir'), SE_UID, 'UNDELETED');
             } else {
                 IMP_Message::threadSort();
             }
             $sorted = IMP_Message::range($sorted, $array_index + $imp['offset'] + 1,
                                          $imp['offset'], $array_index, $imp['msgcount']);
             $imp['msgl'] = implode(':', $sorted);
             $index = $sorted[$array_index];
         } elseif ($actionID == MOVE_MESSAGES && $prefs->getValue('use_trash')) {
             $sorted = array_merge(array_slice($sorted, 0, $array_index),
                                   array_slice($sorted, $array_index + 1));
             $imp['msgl'] = implode(':', $sorted);
             $imp['msgcount']--;
             $index = $sorted[$array_index];
         } else {
             $array_index++;
             $index = $sorted[$array_index];
         }
     }

     if ($prefs->getValue('mailbox_return')) {
         header('Location: ' . Horde::applicationUrl('mailbox.php?start=' . ($array_index + $imp['offset'] + 1), true));
         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). */
     $raw_msg = imap_fetchheader($imp['stream'], $index, FT_UID) . "\n" . imap_body($imp['stream'], $index, FT_UID);

     /* 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);

         Horde::raiseMessage(_("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'])) {
         include_once HORDE_BASE . '/lib/MIME/Message.php';
         include_once HORDE_BASE . '/lib/MIME/Part.php';
         include_once 'Mail.php';

         /* Build the MIME structure. */
         $mime = &new MIME_Message();
         $mime->addPart(new MIME_Part('text/plain', $raw_msg));

         $header['Message-ID'] = '<' . uniqid(time() . '.') . '@' . $_SERVER['SERVER_NAME'] . '>';
         $header['Date'] = date('r');
         $header['To'] = $conf['spam']['email'];
         $header['From'] = $user_identity->getFromLine();
         $header['Subject'] = _("Spam Report from") . ' ' . $imp['user'];
         $header = $mime->header($header);
         IMP::addSiteHeaders($header);

         /* Send the message. */
         $mailer = &Mail::factory($conf['mailer']['type'], IMP::prepareMailerParams());
         $mailer->send($conf['spam']['email'], $mime->encode($header), $mime->toString());

         Horde::raiseMessage(_("This message has been reported as spam to your system administrator."), HORDE_MESSAGE);
     }

     break;

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

     $res = $registry->call('contacts/add', array($newName, $newAddress, $prefs->getValue('add_source')));
     if (PEAR::isError($res)) {
         Horde::raiseMessage($res->getMessage(), $res->getCode());
     } elseif (!$res) {
         Horde::raiseMessage(_("An unknown error occured adding the new entry."), HORDE_ERROR);
     } else {
         Horde::raiseMessage(sprintf(_("Entry \"%s\" was successfully added to the addressbook"), $newName), HORDE_SUCCESS);
     }
     break;
}

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

/* If we grab the headers before grabbing body parts, we'll see when a message is unread */
$h = @imap_header($imp['stream'], imap_msgno($imp['stream'], $index));

/* parse MIME info */
if ($structure = @imap_fetchstructure($imp['stream'], $index, FT_UID)) {
    $bodypart = 1;
    $inline_parts = 0;
    $atc = '';
    $msg = '&nbsp;';
    $attachments = MIME_Structure::parse($structure, $index, $MimeID);
    $msg = buildMessage($attachments, $msg);
    if ($msg == '&nbsp;') {
        $msg = '<tr><td class="text">' . $msg;
    }
} else {
    header('Location: ' . Horde::applicationUrl('mailbox.php?actionID=' . MESSAGE_MISSING, true));
    exit;
}

if ($conf['compress_pages'] && (!$printer_friendly || !$browser->isBrowser('mozilla'))) {
    ob_start('ob_gzhandler');
}

/* Don't show addressbook icon on print screen. */
$showIcon = !$printer_friendly;

if (isset($h->date))     $dat = htmlspecialchars(MIME::decode($h->date));
if (isset($h->to))       $to  = buildAddressLinks($h->to, $showIcon);
if (isset($h->from))     $frm = buildAddressLinks($h->from, $showIcon);
if (isset($h->cc))       $cc  = buildAddressLinks($h->cc, $showIcon);
if (isset($h->bcc))      $bcc = buildAddressLinks($h->bcc, $showIcon);
if (isset($h->reply_to)) $rep = buildAddressLinks($h->reply_to, $showIcon);

if ((isset($h->subject)) && (strlen($h->subject) != 0)) {
    $sub = MIME::decode($h->subject);

    /* filter the subject text, if requested */
    if ($prefs->getValue('filtering')) {
        include_once HORDE_BASE . '/lib/Text.php';
        $sub = Text::filter($sub, $conf['msg']['filtering']['words'],
                            $conf['msg']['filtering']['replacement']);
    }

    if (strlen($sub) > $conf['mailbox']['max_subj_chars']) {
        $shortsub = substr($sub, 0, $conf['mailbox']['max_subj_chars']) . '...';
    } else {
        $shortsub = $sub;
    }
    $shortsub = htmlspecialchars($shortsub);
} else {
    $sub = $shortsub = _("[No Subject]");
}

/* Set the status information of the message */
$msgindex = $array_index + $imp['offset'] + 1;
$status = '';
$identity = null;
if (!strstr($imp['protocol'], 'pop3')) {
    if (!empty($h->toaddress)) {
        $head_addresses = $h->toaddress;
        if (!empty($h->ccaddress)) {
            $head_addresses .= $h->ccaddress;
        }
        if (!empty($h->bccaddress)) {
            $head_addresses .= $h->bccaddress;
        }
        $addresses = $user_identity->getAllFromAddresses();

        $default = $user_identity->getDefault();
        if (isset($addresses[$default]) && strstr(strtolower($head_addresses), strtolower($addresses[$default]))) {
            $status .= $conf['mailbox']['personal_flag'];
            $identity = $default;
        } else {
            unset($addresses[$default]);
            foreach ($addresses as $id => $address) {
                if (strstr(strtolower($head_addresses), strtolower($address))) {
                    $status .= $conf['mailbox']['personal_flag'];
                    $identity = $id;
                    break;
                }
            }
        }
    }
    if ($h->Unseen == 'U' || $h->Recent == 'N') $status .= $conf['mailbox']['unseen_flag'];
    if ($h->Answered == 'A') $status .= $conf['mailbox']['answered_flag'];
    if (isset($h->Draft) && $h->Draft == 'X') $status .= $conf['mailbox']['draft_flag'];
    if ($h->Flagged == 'F') $status .= $conf['mailbox']['important_flag'];
    if ($h->Deleted == 'D') {
        $status .= $conf['mailbox']['deleted_flag'];
    }
}

$title = $imp['label'] . ": $sub";
$sub = htmlspecialchars($sub);
$js_onLoad = null;
require IMP_TEMPLATES . '/common-header.inc';

if (!$printer_friendly) {
    include IMP_BASE . '/menu.php';
    include IMP_BASE . '/status.php';
}
$notification->notify();

if (!empty($conf['hooks']['quota']) && function_exists($conf['hooks']['quota'])) {
    echo call_user_func($conf['hooks']['quota'], $imp);
}

$prev_index = $array_index - 1;
$next_index = $array_index + 1;
if ($array_index != 0) {
    if ($imp['mailbox'] == '**search') {
        $tmp = explode(':', $imp['messagefolders']);
        $prev_link = Horde::url('message.php?index=' . $sorted[$prev_index] . '&thismailbox=' . $tmp[$prev_index]);
    } else {
        $prev_link = Horde::url('message.php?index=' . $sorted[$prev_index]);
    }
}
if ($array_index != count($sorted) - 1) {
    if ($imp['mailbox'] == '**search') {
        $tmp = explode(':', $imp['messagefolders']);
        $next_link = Horde::url('message.php?index=' . $sorted[$next_index] . '&thismailbox=' . $tmp[$next_index]);
    } else {
        $next_link = Horde::url('message.php?index=' . $sorted[$next_index]);
    }
}
$mailbox_link = Horde::url('mailbox.php?start=' . $msgindex);

$form_index = $index;
if (($array_index + 1) != count($sorted)) {
    $form_target = 'message.php';
    $form_ident  = 'index';
    $form_method = 'get';
    $form_link = "$form_target?$form_ident=$form_index&start=$msgindex&thismailbox=" . urlencode($imp['thismailbox']);

} else {
    $form_target = 'mailbox.php';
    $form_ident  = 'indices';
    $form_method = 'post';
    if ($imp['mailbox'] == '**search') {
        $form_index = $index . ':' . Horde::getFormData('thismailbox');
    }
    $form_link = "$form_target?$form_ident=$form_index&start=$msgindex";
}

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

if (!$printer_friendly) {
    if ($browser->hasFeature('javascript')) {
        include IMP_TEMPLATES . '/javascript/open_print_win.js';
    }
    include IMP_TEMPLATES . '/message/navbar_aux_top.inc';
    include IMP_TEMPLATES . '/message/navbar.inc';
}
require IMP_TEMPLATES . '/message/headers.inc';
require IMP_TEMPLATES . '/message/message.inc';
if (!$printer_friendly) {
    include IMP_TEMPLATES . '/message/navbar.inc';
    include IMP_TEMPLATES . '/message/navbar_aux_bottom.inc';
}
if ($browser->hasFeature('javascript')) {
    require IMP_TEMPLATES . '/message/javascript.inc';
    if ($printer_friendly) {
        require IMP_TEMPLATES . '/message/print.inc';
    }
}

$registry->shutdown();

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

$prefs->store();

// catch error messages from c-client
imap_errors();
