git-svn-id: https://svn.code.sf.net/p/squirrelmail/code/trunk/squirrelmail@13443...
[squirrelmail.git] / src / read_body.php
index 7b89b2bc61be7cb2776b176fcd5e76b91fb1b18e..f8fde2ed85dc07339cffc41cb4d721df315eee6f 100644 (file)
@@ -3,33 +3,34 @@
 /**
  * read_body.php
  *
- * Copyright (c) 1999-2004 The SquirrelMail Project Team
- * Licensed under the GNU GPL. For full terms see the file COPYING.
- *
  * This file is used for reading the msgs array and displaying
  * the resulting emails in the right frame.
  *
+ * @copyright © 1999-2007 The SquirrelMail Project Team
+ * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  * @version $Id$
  * @package squirrelmail
  */
 
+/** This is the read_body page */
+define('PAGE_NAME', 'read_body');
+
 /**
- * Path for SquirrelMail required files.
- * @ignore
+ * Include the SquirrelMail initialization file.
  */
-define('SM_PATH','../');
+require('../include/init.php');
 
 /* SquirrelMail required files. */
-require_once(SM_PATH . 'include/validate.php');
-require_once(SM_PATH . 'functions/global.php');
 require_once(SM_PATH . 'functions/imap.php');
+require_once(SM_PATH . 'functions/imap_asearch.php'); // => move to mailbox_display
 require_once(SM_PATH . 'functions/mime.php');
 require_once(SM_PATH . 'functions/date.php');
 require_once(SM_PATH . 'functions/url_parser.php');
-require_once(SM_PATH . 'functions/html.php');
-require_once(SM_PATH . 'functions/global.php');
 require_once(SM_PATH . 'functions/identity.php');
 require_once(SM_PATH . 'functions/mailbox_display.php');
+require_once(SM_PATH . 'functions/forms.php');
+require_once(SM_PATH . 'functions/attachment_common.php');
+require_once(SM_PATH . 'functions/compose.php');
 
 /**
  * Given an IMAP message id number, this will look it up in the cached
@@ -45,18 +46,12 @@ function findNextMessage($uidset,$passed_id='backwards') {
     if ($passed_id=='backwards' || !is_array($uidset)) { // check for backwards compattibilty gpg plugin
         $passed_id = $uidset;
     }
-    $result = -1;
-    $count = count($uidset) - 1;
-    foreach($uidset as $key=>$value) {
-        if ($passed_id == $value) {
-            if ($key == $count) {
-                break;
-            }
-            $result = $uidset[$key + 1];
-            break;
-        }
+    $result = sqm_array_get_value_by_offset($uidset,$passed_id,1);
+    if ($result === false) {
+        return -1;
+    } else {
+        return $result;
     }
-    return $result;
 }
 
 /**
@@ -71,51 +66,59 @@ function findPreviousMessage($uidset, $passed_id) {
     if (!is_array($uidset)) {
         return -1;
     }
-    $result = -1;
-    foreach($uidset as $key=>$value) {
-        if ($passed_id == $value) {
-            if ($key != 0) {
-                $result = $uidset[$key - 1];
-            }
-            break;
-        }
+    $result = sqm_array_get_value_by_offset($uidset,$passed_id,-1);
+    if ($result === false) {
+        return -1;
+    } else {
+        return $result;
     }
-
-    return $result;
 }
 
-/**
- * Displays a link to a page where the message is displayed more
- * "printer friendly".
- * @param string $mailbox Name of current mailbox
- * @param int $passed_id
- */
-function printer_friendly_link($mailbox, $passed_id, $passed_ent_id) {
-    global $javascript_on, $color;
-
-    $params = '?passed_ent_id=' . urlencode($passed_ent_id) .
-              '&mailbox=' . urlencode($mailbox) .
-              '&passed_id=' . urlencode($passed_id);
-
-    $print_text = _("View Printable Version");
-
-    $result = '';
-    /* Output the link. */
-    if ($javascript_on) {
-        $result = '<script language="javascript" type="text/javascript">' . "\n" .
-                  '<!--' . "\n" .
-                  "  function printFormat() {\n" .
-                  '    window.open("../src/printer_friendly_main.php' .
-                  $params . '","Print","width=800,height=600");' . "\n".
-                  "  }\n" .
-                  "// -->\n" .
-                  "</script>\n" .
-                  "<a href=\"javascript:printFormat();\">$print_text</a>\n";
+function html_toggle_href ($mailbox, $passed_id, $passed_ent_id, $message) {
+    global $base_uri, $show_html_default;
+
+    $has_html = false;
+    if ($message->header->type0 == 'message' && $message->header->type1 == 'rfc822') {
+        $type0 = $message->rfc822_header->content_type->type0;
+        $type1 = $message->rfc822_header->content_type->type1;
     } else {
-        $result = '<a target="_blank" href="../src/printer_friendly_bottom.php' .
-                  "$params\">$print_text</a>\n";
+        $type0 = $message->header->type0;
+        $type1 = $message->header->type1;
+    }
+    if($type0 == 'multipart' &&
+       ($type1 == 'alternative' || $type1 == 'mixed' || $type1 == 'related' || $type1=='signed')) {
+        if ($message->findDisplayEntity(array(), array('text/html'), true)) {
+            $has_html = true;
+        }
+    }
+    /*
+     * Normal single part message so check its type.
+     */
+    else {
+        if($type0 == 'text' && $type1 == 'html') {
+            $has_html = true;
+        }
+    }
+    if($has_html == true) {
+        $vars = array('passed_ent_id', 'show_more', 'show_more_cc', 'override_type0', 'override_type1', 'startMessage','where', 'what');
+
+        $new_link = $base_uri . 'src/read_body.php?passed_id=' . urlencode($passed_id) .
+                    '&amp;passed_ent_id=' . urlencode($passed_ent_id) .
+                    '&amp;mailbox=' . urlencode($mailbox);
+        foreach($vars as $var) {
+            if(sqgetGlobalVar($var, $temp)) {
+                $new_link .= '&amp;' . $var . '=' . urlencode($temp);
+            }
+        }
+
+        if($show_html_default == 1) {
+            $new_link .= '&amp;show_html_default=0';
+        } else {
+            $new_link .= '&amp;show_html_default=1';
+        }
+        return $new_link;
     }
-    return $result;
+    return '';
 }
 
 function ServerMDNSupport($aFlags) {
@@ -124,16 +127,14 @@ function ServerMDNSupport($aFlags) {
              in_array('\\*',$aFlags,true) ) ;
 }
 
-function SendMDN ( $mailbox, $passed_id, $sender, $message, $imapConnection) {
-    global $username, $attachment_dir,
-           $version, $attachments, $squirrelmail_language, $default_charset,
-           $languages, $useSendmail, $domain, $sent_folder,
-           $popuser, $data_dir, $username;
+function SendMDN ( $mailbox, $passed_id, $message, $imapConnection) {
+    global $squirrelmail_language, $default_charset, $default_move_to_sent,
+           $languages, $useSendmail, $domain, $sent_folder, $username,
+           $data_dir;
 
     sqgetGlobalVar('SERVER_NAME', $SERVER_NAME, SQ_SERVER);
 
     $header = $message->rfc822_header;
-    $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
 
     $rfc822_header = new Rfc822Header();
     $content_type  = new ContentType('multipart/report');
@@ -145,38 +146,29 @@ function SendMDN ( $mailbox, $passed_id, $sender, $message, $imapConnection) {
     }
     $rfc822_header->content_type = $content_type;
     $rfc822_header->to[] = $header->dnt;
-    $rfc822_header->subject = _("Read:") . ' ' . encodeHeader($header->subject);
-
-    // Patch #793504 Return Receipt Failing with <@> from Tim Craig (burny_md)
-    // This merely comes from compose.php and only happens when there is no
-    // email_addr specified in user's identity (which is the startup config)
-    if (ereg("^([^@%/]+)[@%/](.+)$", $username, $usernamedata)) {
-       $popuser = $usernamedata[1];
-       $domain  = $usernamedata[2];
-       unset($usernamedata);
-    } else {
-       $popuser = $username;
-    }
-
-    $reply_to = '';
-    $ident = get_identities();
-    if(!isset($identity)) $identity = 0;
-    $full_name = $ident[$identity]['full_name'];
-    $from_mail = $ident[$identity]['email_address'];
-    $from_addr = '"'.$full_name.'" <'.$from_mail.'>';
-    $reply_to  = $ident[$identity]['reply_to'];
+    $rfc822_header->subject = _("Read:") . ' ' . decodeHeader($header->subject,true,false);
 
-    if (!$from_mail) {
-       $from_mail = "$popuser@$domain";
-       $from_addr = $from_mail;
+    $idents = get_identities();
+    $needles = array();
+    if ($header->to) {
+        foreach ($header->to as $message_to) {
+             $needles[] = $message_to->mailbox.'@'.$message_to->host;
+        }
     }
+    $identity = find_identity($needles);
+    $from_addr = build_from_header($identity);
+    $reply_to = isset($idents[$identity]['reply_to']) ? $idents[$identity]['reply_to'] : '';
+    // FIXME: this must actually be the envelope address of the orginal message,
+    // but do we have that information? For now the first identity is our best guess.
+    $final_recipient = $idents[0]['email_address'];
+
     $rfc822_header->from = $rfc822_header->parseAddress($from_addr,true);
     if ($reply_to) {
        $rfc822_header->reply_to = $rfc822_header->parseAddress($reply_to,true);
     }
 
     // part 1 (RFC2298)
-    $senton = getLongDateString( $header->date );
+    $senton = getLongDateString( $header->date, $header->date_unparsed );
     $to_array = $header->to;
     $to = '';
     foreach ($to_array as $line) {
@@ -203,6 +195,8 @@ function SendMDN ( $mailbox, $passed_id, $sender, $message, $imapConnection) {
                 $special_encoding = '7bit';
             }
         }
+    } elseif (sq_is8bit($body)) {
+        $special_encoding = '8bit';
     }
     $part1 = new Message();
     $part1->setBody($body);
@@ -223,11 +217,10 @@ function SendMDN ( $mailbox, $passed_id, $sender, $message, $imapConnection) {
     $original_recipient  = $to;
     $original_message_id = $header->message_id;
 
-    $report = "Reporting-UA : $SERVER_NAME ; SquirrelMail (version $version) \r\n";
+    $report = "Reporting-UA : $SERVER_NAME ; SquirrelMail (version " . SM_VERSION . ") \r\n";
     if ($original_recipient != '') {
         $report .= "Original-Recipient : $original_recipient\r\n";
     }
-    $final_recipient = $sender;
     $report .= "Final-Recipient: rfc822; $final_recipient\r\n" .
               "Original-Message-ID : $original_message_id\r\n" .
               "Disposition: manual-action/MDN-sent-manually; displayed\r\n";
@@ -248,37 +241,74 @@ function SendMDN ( $mailbox, $passed_id, $sender, $message, $imapConnection) {
 
     if ($useSendmail) {
         require_once(SM_PATH . 'class/deliver/Deliver_SendMail.class.php');
-        global $sendmail_path;
-        $deliver = new Deliver_SendMail();
+        global $sendmail_path, $sendmail_args;
+        // Check for outdated configuration
+        if (!isset($sendmail_args)) {
+            if ($sendmail_path=='/var/qmail/bin/qmail-inject') {
+                $sendmail_args = '';
+            } else {
+                $sendmail_args = '-i -t';
+            }
+        }
+        $deliver = new Deliver_SendMail(array('sendmail_args'=>$sendmail_args));
         $stream = $deliver->initStream($composeMessage,$sendmail_path);
     } else {
         require_once(SM_PATH . 'class/deliver/Deliver_SMTP.class.php');
         $deliver = new Deliver_SMTP();
-        global $smtpServerAddress, $smtpPort, $smtp_auth_mech, $pop_before_smtp;
+        global $smtpServerAddress, $smtpPort, $pop_before_smtp, $pop_before_smtp_host;
         $authPop = (isset($pop_before_smtp) && $pop_before_smtp) ? true : false;
+        if (empty($pop_before_smtp_host)) $pop_before_smtp_host = $smtpServerAddress;
         get_smtp_user($user, $pass);
         $stream = $deliver->initStream($composeMessage,$domain,0,
-                                       $smtpServerAddress, $smtpPort, $user, $pass, $authPop);
+                                       $smtpServerAddress, $smtpPort, $user, $pass, $authPop, $pop_before_smtp_host);
     }
     $success = false;
     if ($stream) {
-        $length  = $deliver->mail($composeMessage, $stream);
+        $deliver->mail($composeMessage, $stream);
         $success = $deliver->finalizeStream($stream);
     }
     if (!$success) {
-        $msg  = $deliver->dlv_msg . '<br />' .
-                _("Server replied: ") . $deliver->dlv_ret_nr . ' '.
-                $deliver->dlv_server_msg;
-        require_once(SM_PATH . 'functions/display_messages.php');
-        plain_error_message($msg, $color);
+        $msg = _("Message not sent.") . "\n" .
+            $deliver->dlv_msg;
+        if (! empty($deliver->dlv_server_msg)) {
+            $msg.= "\n" .
+                _("Server replied:") . ' ' . $deliver->dlv_ret_nr . ' ' .
+                nl2br(htmlspecialchars($deliver->dlv_server_msg));
+        }
+        plain_error_message($msg);
     } else {
         unset ($deliver);
-        if (sqimap_mailbox_exists ($imapConnection, $sent_folder)) {
-            sqimap_append ($imapConnection, $sent_folder, $length);
+
+        // move to sent folder
+        //
+        $move_to_sent = getPref($data_dir,$username,'move_to_sent');
+        if (isset($default_move_to_sent) && ($default_move_to_sent != 0)) {
+            $svr_allow_sent = true;
+        } else {
+            $svr_allow_sent = false;
+        }
+
+        if (isset($sent_folder) && (($sent_folder != '') || ($sent_folder != 'none'))
+                && sqimap_mailbox_exists( $imapConnection, $sent_folder)) {
+            $fld_sent = true;
+        } else {
+            $fld_sent = false;
+        }
+
+        if ((isset($move_to_sent) && ($move_to_sent != 0)) || (!isset($move_to_sent))) {
+            $lcl_allow_sent = true;
+        } else {
+            $lcl_allow_sent = false;
+        }
+
+        if (($fld_sent && $svr_allow_sent && !$lcl_allow_sent) || ($fld_sent && $lcl_allow_sent)) {
+            $save_reply_with_orig=getPref($data_dir,$username,'save_reply_with_orig');
+            if ($save_reply_with_orig) {
+                $sent_folder = $mailbox;
+            }
             require_once(SM_PATH . 'class/deliver/Deliver_IMAP.class.php');
             $imap_deliver = new Deliver_IMAP();
-            $imap_deliver->mail($composeMessage, $imapConnection);
-            sqimap_append_done ($imapConnection);
+            $imap_deliver->mail($composeMessage, $imapConnection, 0, 0, $imapConnection, $sent_folder);
             unset ($imap_deliver);
         }
     }
@@ -292,30 +322,9 @@ function ToggleMDNflag ($set ,$imapConnection, $mailbox, $passed_id) {
                                 $readmessage, TRUE);
 }
 
-function ClearAttachments() {
-    global $username, $attachments, $attachment_dir;
-
-    $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
-
-    $rem_attachments = array();
-    if (isset($attachments)) {
-        foreach ($attachments as $info) {
-            if ($info['session'] == -1) {
-                $attached_file = "$hashed_attachment_dir/$info[localfilename]";
-                if (file_exists($attached_file)) {
-                    unlink($attached_file);
-                }
-            } else {
-                $rem_attachments[] = $info;
-            }
-        }
-    }
-    $attachments = $rem_attachments;
-}
-
 function formatRecipientString($recipients, $item ) {
-    global $show_more_cc, $show_more, $show_more_bcc,
-           $PHP_SELF;
+    global $show_more, $show_more_cc, $show_more_bcc,
+           $PHP_SELF, $oTemplate;
 
     $string = '';
     if ((is_array($recipients)) && (isset($recipients[0]))) {
@@ -344,33 +353,31 @@ function formatRecipientString($recipients, $item ) {
             }
         }
 
-        $cnt = count($recipients);
-        foreach($recipients as $r) {
-            $add = decodeHeader($r->getAddress(true));
-            if ($string) {
-                $string .= '<br />' . $add;
-            } else {
-                $string = $add;
-                if ($cnt > 1) {
-                    $string .= '&nbsp;(<a href="'.$url;
-                    if ($show) {
-                       $string .= '">'._("less").'</a>)';
-                    } else {
-                       $string .= '">'._("more").'</a>)';
-                       break;
-                    }
-                }
-            }
+        $a = array();
+        foreach ($recipients as $r) {
+            $a[] = array(
+                            // note: decodeHeader is htmlsafe by default
+                            'Name'  => decodeHeader($r->getAddress(false)),
+                            'Email' => htmlspecialchars($r->getEmail()),
+                            'Full'  => decodeHeader($r->getAddress(true))
+                        );
         }
+
+        $oTemplate->assign('which_field', $item);
+        $oTemplate->assign('recipients', $a);
+        $oTemplate->assign('more_less_toggle_href', $url);
+        $oTemplate->assign('show_more', $show);
+
+        $string = $oTemplate->fetch('read_recipient_list.tpl');
     }
     return $string;
 }
 
 function formatEnvheader($aMailbox, $passed_id, $passed_ent_id, $message,
                          $color, $FirstTimeSee) {
-    global $msn_user_support, $default_use_mdn, $default_use_priority,
-           $show_xmailer_default, $mdn_user_support, $PHP_SELF, $javascript_on,
-           $squirrelmail_language;
+    global $default_use_mdn, $default_use_priority,
+           $show_xmailer_default, $mdn_user_support, $PHP_SELF,
+           $squirrelmail_language, $oTemplate;
 
     $mailbox = $aMailbox['NAME'];
 
@@ -385,99 +392,104 @@ function formatEnvheader($aMailbox, $passed_id, $passed_ent_id, $message,
         $env[_("From")] = _("Unknown sender");
     else
         $env[_("From")] = decodeHeader($from_name);
-    $env[_("Date")] = getLongDateString($header->date);
+    $env[_("Date")] = getLongDateString($header->date, $header->date_unparsed);
     $env[_("To")] = formatRecipientString($header->to, "to");
     $env[_("Cc")] = formatRecipientString($header->cc, "cc");
     $env[_("Bcc")] = formatRecipientString($header->bcc, "bcc");
     if ($default_use_priority) {
-        $env[_("Priority")] = htmlspecialchars(getPriorityStr($header->priority));
+        $oTemplate->assign('message_priority', $header->priority);
+        $env[_("Priority")] = $oTemplate->fetch('read_message_priority.tpl');
     }
     if ($show_xmailer_default) {
-        $env[_("Mailer")] = decodeHeader($header->xmailer);
+        $oTemplate->assign('xmailer', decodeHeader($header->xmailer));
+        $env[_("Mailer")] = $oTemplate->fetch('read_xmailer.tpl');
     }
+
+    // this is used for both mdn and also general use for plugins, etc
+    $oTemplate->assign('first_time_reading', $FirstTimeSee);
+
     if ($default_use_mdn) {
         if ($mdn_user_support) {
             if ($header->dnt) {
-                if ($message->is_mdnsent) {
-                    $env[_("Read receipt")] = _("sent");
-                } else {
-                    $env[_("Read receipt")] = _("requested");
-                    if (!(handleAsSent($mailbox) ||
-                          $message->is_deleted ||
-                          $passed_ent_id)) {
-                        $mdn_url = $PHP_SELF . '&sendreceipt=1';
-                        if ($FirstTimeSee && $javascript_on) {
-                            $script  = '<script language="JavaScript" type="text/javascript">' . "\n";
-                            $script .= '<!--'. "\n";
-                            $script .= 'if(window.confirm("' .
-                                       _("The message sender has requested a response to indicate that you have read this message. Would you like to send a receipt?") .
-                                       '")) {  '."\n" .
-                                       '    sendMDN()'.
-                                       '}' . "\n";
-                            $script .= '// -->'. "\n";
-                            $script .= '</script>'. "\n";
-                            echo $script;
-                        }
-                        $env[_("Read receipt")] .= '&nbsp;<a href="' . $mdn_url . '">[' .
-                                                   _("Send read receipt now") . ']</a>';
-                    }
-                }
+                $mdn_url = $PHP_SELF;
+                $mdn_url = set_url_var($mdn_url, 'mailbox', urlencode($mailbox));
+                $mdn_url = set_url_var($mdn_url, 'passed_id', $passed_id);
+                $mdn_url = set_url_var($mdn_url, 'passed_ent_id', $passed_ent_id);
+                $mdn_url = set_url_var($mdn_url, 'sendreceipt', 1);
+
+                $oTemplate->assign('read_receipt_sent', $message->is_mdnsent);
+                $oTemplate->assign('send_receipt_href', $mdn_url);
+
+                $env[_("Read Receipt")] = $oTemplate->fetch('read_handle_receipt.tpl');
             }
         }
     }
 
-    $s  = '<table width="100%" cellpadding="0" cellspacing="2" border="0"';
-    $s .= ' align="center" bgcolor="'.$color[0].'">';
-    foreach ($env as $key => $val) {
-        if ($val) {
-            $s .= '<tr>';
-            $s .= html_tag('td', '<b>' . $key . ':&nbsp;&nbsp;</b>', 'right', '', 'valign="top" width="20%"') . "\n";
-            $s .= html_tag('td', $val, 'left', '', 'valign="top" width="80%"') . "\n";
-            $s .= '</tr>';
+    $statuses = array();
+    if (isset($aMailbox['MSG_HEADERS'][$passed_id]['FLAGS'])) {
+        if (isset($aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\deleted']) &&
+                  $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\deleted'] === true) {
+            $statuses[] = _("deleted");
+        }
+        if (isset($aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\answered']) &&
+                  $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\answered'] === true) {
+            $statuses[] = _("answered");
+        }
+        if (isset($aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\draft']) &&
+                  $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\draft'] === true) {
+            $statuses[] = _("draft");
+        }
+        if (isset($aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\flagged']) &&
+                  $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\flagged'] === true) {
+            $statuses[] = _("flagged");
+        }
+        if ( count($statuses) ) {
+            $env[_("Status")] = implode(', ', $statuses);
         }
     }
-    echo '<table bgcolor="'.$color[9].'" width="100%" cellpadding="1"'.
-         ' cellspacing="0" border="0" align="center">'."\n";
-    echo '<tr><td height="5" colspan="2" bgcolor="'.
-          $color[4].'"></td></tr><tr><td align="center">'."\n";
-    echo $s;
-    do_hook('read_body_header');
-    formatToolbar($mailbox, $passed_id, $passed_ent_id, $message, $color);
-    echo '</table>';
-    echo '</td></tr><tr><td height="5" colspan="2" bgcolor="'.$color[4].'"></td></tr>'."\n";
-    echo '</table>';
+
+    $env[_("Options")] = formatToolbar($mailbox, $passed_id, $passed_ent_id, $message, $color);
+
+
+    $oTemplate->assign('headers_to_display', $env);
+
+    $oTemplate->display('read_headers.tpl');
 }
 
 /**
  * Format message toolbar
  *
- * @param string $mailbox Name of current mailbox
- * @param int $passed_id UID of current message
- * @param int $passed_ent_id Id of entity within message
- * @param object $message Current message object
- * @param object $mbx_response
+ * @param array   $aMailbox      Current mailbox information array
+ * @param int     $passed_id     UID of current message
+ * @param int     $passed_ent_id Id of entity within message
+ * @param object  $message       Current message object
+ * @param void    $removedVar    This parameter is no longer used, but remains
+ *                               so as not to break this function's prototype
+ *                               (OPTIONAL)
+ * @param boolean $nav_on_top    When TRUE, the menubar is being constructed
+ *                               for use at the top of the page, otherwise it
+ *                               will be used for page bottom (OPTIONAL;
+ *                               default = TRUE)
  */
-function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message, $removedVar, $nav_on_top = TRUE) {
-    global $base_uri, $draft_folder, $where, $what, $color, $sort,
+function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message,
+                       $removedVar=FALSE, $nav_on_top=TRUE) {
+
+    global $base_uri, $draft_folder, $where, $what, $sort,
            $startMessage, $PHP_SELF, $save_as_draft,
            $enable_forward_as_attachment, $imapConnection, $lastTargetMailbox,
-           $data_dir, $username, $delete_prev_next_display,
-           $compose_new_win, $javascript_on;
+           $delete_prev_next_display, $show_copy_buttons,
+           $compose_new_win, $compose_width, $compose_height,
+           $oTemplate;
 
     //FIXME cleanup argument list, use $aMailbox where possible
     $mailbox = $aMailbox['NAME'];
 
-    $topbar_delimiter = '&nbsp;|&nbsp;';
-    $double_delimiter = '&nbsp;&nbsp;&nbsp;&nbsp;';
     $urlMailbox = urlencode($mailbox);
 
-    $msgs_url = $base_uri . 'src/';
-
-    // BEGIN NAV ROW - PREV/NEXT, DEL PREV/NEXT, LINKS TO INDEX, etc.
-    $nav_row = '<tr><td align="left" colspan="2" style="border: 1px solid '.$color[9].';"><small>';
-
     // Create Prev & Next links
     // Handle nested entities first (i.e. Mime Attach parts)
+    $prev_href = $next_href = $up_href = $del_href = $del_prev_href = $del_next_href = '';
+    $msg_list_href = $search_href = $view_msg_href = '';
     if (isset($passed_ent_id) && $passed_ent_id) {
         // code for navigating through attached message/rfc822 messages
         $url = set_url_var($PHP_SELF, 'passed_ent_id',0);
@@ -487,117 +499,80 @@ function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message, $removed
 
         foreach($message->parent->entities as $ent) {
             if ($ent->type0 == 'message' && $ent->type1 == 'rfc822') {
+
                 $c++;
                 $entity_count[$c] = $ent->entity_id;
                 $entities[$ent->entity_id] = $c;
             }
         }
 
-        $prev_link = _("Previous");
-        if($entities[$passed_ent_id] > 1) {
+        if(isset($entities[$passed_ent_id]) && $entities[$passed_ent_id] > 1) {
             $prev_ent_id = $entity_count[$entities[$passed_ent_id] - 1];
-            $prev_link   = '<a href="'
-                         . set_url_var($PHP_SELF, 'passed_ent_id', $prev_ent_id)
-                         . '">' . $prev_link . '</a>';
+            $prev_href = set_url_var($PHP_SELF, 'passed_ent_id', $prev_ent_id);
         }
 
-        $next_link = _("Next");
-        if($entities[$passed_ent_id] < $c) {
+        if(isset($entities[$passed_ent_id]) && $entities[$passed_ent_id] < $c) {
             $next_ent_id = $entity_count[$entities[$passed_ent_id] + 1];
-            $next_link   = '<a href="'
-                         . set_url_var($PHP_SELF, 'passed_ent_id', $next_ent_id)
-                         . '">' . $next_link . '</a>';
+            $next_href = set_url_var($PHP_SELF, 'passed_ent_id', $next_ent_id);
         }
 
         $par_ent_id = $message->parent->entity_id;
-        $up_link = '';
         if ($par_ent_id) {
             $par_ent_id = substr($par_ent_id,0,-2);
             if ( $par_ent_id != 0 ) {
-                $up_link = $topbar_delimiter;
-                $url = set_url_var($PHP_SELF, 'passed_ent_id',$par_ent_id);
-                $up_link .= '<a href="'.$url.'">'._("Up").'</a>';
+                $up_href = set_url_var($PHP_SELF, 'passed_ent_id',$par_ent_id);
             }
         }
 
-        $nav_row .= $prev_link . $up_link . $topbar_delimiter . $next_link;
-        $nav_row .= $double_delimiter . '[<a href="'.$url.'">'._("View Message").'</a>]';
+        $view_msg_href = $url;
 
     // Prev/Next links for regular messages
     } else if ( true ) { //!(isset($where) && isset($what)) ) {
-        /**
-         * Check if cache is still valid
-         */
-        if (!is_array($aMailbox['UIDSET'][$what])) {
-            fetchMessageHeaders($imapConnection, $aMailbox);
-        }
         $prev = findPreviousMessage($aMailbox['UIDSET'][$what], $passed_id);
         $next = findNextMessage($aMailbox['UIDSET'][$what],$passed_id);
 
-        $prev_link = _("Previous");
         if ($prev >= 0) {
-            $uri = $base_uri . 'src/read_body.php?passed_id='.$prev.
+            $prev_href = $base_uri . 'src/read_body.php?passed_id='.$prev.
                    '&amp;mailbox='.$urlMailbox.'&amp;sort='.$sort.
                    "&amp;where=$where&amp;what=$what" .
                    '&amp;startMessage='.$startMessage.'&amp;show_more=0';
-            $prev_link = '<a href="'.$uri.'">'.$prev_link.'</a>';
         }
 
-        $next_link = _("Next");
         if ($next >= 0) {
-            $uri = $base_uri . 'src/read_body.php?passed_id='.$next.
+            $next_href = $base_uri . 'src/read_body.php?passed_id='.$next.
                    '&amp;mailbox='.$urlMailbox.'&amp;sort='.$sort.
                    "&amp;where=$where&amp;what=$what" .
                    '&amp;startMessage='.$startMessage.'&amp;show_more=0';
-            $next_link = '<a href="'.$uri.'">'.$next_link.'</a>';
         }
 
         // Only bother with Delete & Prev and Delete & Next IF
         // top display is enabled.
         if ( $delete_prev_next_display == 1 &&
                in_array('\\deleted', $aMailbox['PERMANENTFLAGS'],true) ) {
-            $del_prev_link = _("Delete & Prev");
             if ($prev >= 0) {
-                $uri = $base_uri . 'src/read_body.php?passed_id='.$prev.
+                $del_prev_href = $base_uri . 'src/read_body.php?passed_id='.$prev.
                        '&amp;mailbox='.$urlMailbox.'&amp;sort='.$sort.
                        '&amp;startMessage='.$startMessage.'&amp;show_more=0'.
                        "&amp;where=$where&amp;what=$what" .
                        '&amp;delete_id='.$passed_id;
-                $del_prev_link = '<a href="'.$uri.'">'.$del_prev_link.'</a>';
             }
 
-            $del_next_link = _("Delete & Next");
             if ($next >= 0) {
-                $uri = $base_uri . 'src/read_body.php?passed_id='.$next.
+                $del_next_href = $base_uri . 'src/read_body.php?passed_id='.$next.
                        '&amp;mailbox='.$urlMailbox.'&amp;sort='.$sort.
                        '&amp;startMessage='.$startMessage.'&amp;show_more=0'.
                        "&amp;where=$where&amp;what=$what" .
                        '&amp;delete_id='.$passed_id;
-                $del_next_link = '<a href="'.$uri.'">'.$del_next_link.'</a>';
             }
         }
-
-        $nav_row .= '['.$prev_link.$topbar_delimiter.$next_link.']';
-        if ( isset($del_prev_link) && isset($del_next_link) )
-            $nav_row .= $double_delimiter.'['.$del_prev_link.$topbar_delimiter.$del_next_link.']';
     }
 
-    // Start with Search Results or Message List link.
-    $msgs_url .= "$where?where=read_body.php&amp;what=$what&amp;mailbox=" . $urlMailbox.
-                 "&amp;startMessage=$startMessage";
-    if ($where == 'search.php') {
-        $msgs_str  = _("Search Results");
-    } else {
-        $msgs_str  = _("Message List");
-    }
-    $nav_row .= $double_delimiter .
-                '[<a href="' . $msgs_url . '">' . $msgs_str . '</a>]';
-
-    $nav_row .= '</small></td></tr>';
-
+    $msg_list_href = get_message_list_uri($aMailbox['NAME'], $startMessage, $what);
+    if ($where == 'search.php')
+        $search_href = str_replace('read_body.php', 'search.php', $msg_list_href);
+    else
+        $search_href = '';
 
-    // BEGIN MENU ROW - DELETE/REPLY/FORWARD/MOVE/etc.
-    $menu_row = '<tr bgcolor="'.$color[0].'"><td><small>';
     $comp_uri = $base_uri.'src/compose.php' .
                 '?passed_id=' . $passed_id .
                 '&amp;mailbox=' . $urlMailbox .
@@ -607,130 +582,196 @@ function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message, $removed
     // Start form for reply/reply all/forward..
     $target = '';
     $on_click='';
-    $method='method="post" ';
+    $method='post';
+    $onsubmit='';
     if ($compose_new_win == '1') {
-        if ( $javascript_on ) {
-          $on_click=' onclick="comp_in_new_form(\''.$comp_uri.'\', this, this.form)"';
+        if (!preg_match("/^[0-9]{3,4}$/", $compose_width)) {
+            $compose_width = '640';
+        }
+        if (!preg_match("/^[0-9]{3,4}$/", $compose_height)) {
+            $compose_height = '550';
+        }
+        if ( checkForJavascript() ) {
+          $on_click='comp_in_new_form(\''.$comp_uri.'\', this, this.form,'. $compose_width .',' . $compose_height .')';
           $comp_uri = 'javascript:void(0)';
-          $method='method="get" ';
+          $method='get';
+          $onsubmit = 'return false';
         } else {
-          $target = 'target="_blank"';
+          $target = '_blank';
         }
     }
 
-    $menu_row .= "\n".'<form name="composeForm" action="'.$comp_uri.'" '.$method.$target.' style="display: inline">'."\n";
+    $oTemplate->assign('nav_on_top', $nav_on_top);
+
+    $oTemplate->assign('prev_href', $prev_href);
+    $oTemplate->assign('up_href', $up_href);
+    $oTemplate->assign('next_href', $next_href);
+    $oTemplate->assign('del_prev_href', $del_prev_href);
+    $oTemplate->assign('del_next_href', $del_next_href);
+    $oTemplate->assign('view_msg_href', $view_msg_href);
+
+    $oTemplate->assign('message_list_href', $msg_list_href);
+    $oTemplate->assign('search_href', $search_href);
+
+    $oTemplate->assign('form_extra', '');
+    $oTemplate->assign('form_method', $method);
+    $oTemplate->assign('form_target', $target);
+    $oTemplate->assign('form_onsubmit', $onsubmit);
+    $oTemplate->assign('compose_href', $comp_uri);
+    $oTemplate->assign('button_onclick', $on_click);
+    $oTemplate->assign('forward_as_attachment_enabled', $enable_forward_as_attachment==1);
+
+    //FIXME: I am surprised these aren't already given to the template; probably needs to be given at a higher level, so I have NO IDEA if this is the right place to do this...  adding them so template can construct its own API calls... we can build those herein too if preferrable
+    $oTemplate->assign('mailbox', $aMailbox['NAME']);
+    $oTemplate->assign('passed_id', $passed_id);
+    $oTemplate->assign('what', $what);
 
     // If Draft folder - create Resume link
+    $resume_draft = $edit_as_new = false;
     if (($mailbox == $draft_folder) && ($save_as_draft)) {
-        $new_button = 'smaction_draft';
-        $comp_alt_string = _("Resume Draft");
+        $resume_draft = true; 'smaction_draft';
     } else if (handleAsSent($mailbox)) {
-    // If in Sent folder, edit as new
-        $new_button = 'smaction_edit_new';
-        $comp_alt_string = _("Edit Message as New");
+        $edit_as_new = true;
     }
-    // Show Alt URI for Draft/Sent
-    if (isset($comp_alt_string))
-        $menu_row .= getButton('submit', $new_button, $comp_alt_string, $on_click) . "\n";
-
-    $menu_row .= getButton('submit', 'smaction_reply', _("Reply"), $on_click) . "\n";
-    $menu_row .= getButton('submit', 'smaction_reply_all', _("Reply All"), $on_click) ."\n";
-    $menu_row .= getButton('submit', 'smaction_forward', _("Forward"), $on_click);
-    if ($enable_forward_as_attachment)
-        $menu_row .= '<input type="checkbox" name="smaction_attache" />' . _("As Attachment") .'&nbsp;&nbsp;'."\n";
-
-    $menu_row .= '</form>&nbsp;';
+    $oTemplate->assign('can_resume_draft', $resume_draft);
+    $oTemplate->assign('can_edit_as_new', $edit_as_new);
 
-    if ( in_array('\\deleted', $aMailbox['PERMANENTFLAGS'],true) ) {
-    // Form for deletion. Form is handled by the originating display in $where. This is right_main.php or search.php
+    $oTemplate->assign('mailboxes', sqimap_mailbox_option_array($imapConnection));
+    if (in_array('\\deleted', $aMailbox['PERMANENTFLAGS'],true)) {
         $delete_url = $base_uri . "src/$where";
-        $menu_row .= '<form name="deleteMessageForm" action="'.$delete_url.'" method="post" style="display: inline">';
-
+        $oTemplate->assign('can_be_deleted', true);
+        $oTemplate->assign('move_delete_form_action', $base_uri.'src/'.$where);
+        $oTemplate->assign('delete_form_extra', addHidden('mailbox', $aMailbox['NAME'])."\n" .
+                                                addHidden('msg[0]', $passed_id)."\n" .
+                                                addHidden('startMessage', $startMessage)."\n" );
         if (!(isset($passed_ent_id) && $passed_ent_id)) {
-            $menu_row .= addHidden('mailbox', $aMailbox['NAME']);
-            $menu_row .= addHidden('msg[0]', $passed_id);
-            $menu_row .= addHidden('startMessage', $startMessage);
-            $menu_row .= getButton('submit', 'delete', _("Delete"));
-            $menu_row .= '<input type="checkbox" name="bypass_trash" />' . _("Bypass Trash");
+            $oTemplate->assign('can_be_moved', true);
+            $oTemplate->assign('move_form_extra', addHidden('mailbox', $aMailbox['NAME'])."\n" .
+                                                  addHidden('msg[0]', $passed_id)."\n" );
+            $oTemplate->assign('last_move_target', isset($lastTargetMailbox) && !empty($lastTargetMailbox) ? $lastTargetMailbox : '');
+            $oTemplate->assign('can_be_copied', $show_copy_buttons==1);
         } else {
-            $menu_row .= getButton('submit', 'delete', _("Delete"), '', FALSE) . "\n"; // delete button is disabled
+            $oTemplate->assign('can_be_moved', false);
+            $oTemplate->assign('move_form_extra', '');
+            $oTemplate->assign('last_move_target', '');
+            $oTemplate->assign('can_be_copied', false);
         }
-
-        $menu_row .= '</form>';
+    } else {
+        $oTemplate->assign('can_be_deleted', false);
+        $oTemplate->assign('move_delete_form_action', '');
+        $oTemplate->assign('delete_form_extra', '');
+        $oTemplate->assign('can_be_moved', false);
+        $oTemplate->assign('move_form_extra', '');
+        $oTemplate->assign('last_move_target', '');
+        $oTemplate->assign('can_be_copied', false);
     }
 
-    // Add top move link
-    $menu_row .= '</small></td><td align="right">';
-    if ( !(isset($passed_ent_id) && $passed_ent_id) &&
-        in_array('\\deleted', $aMailbox['PERMANENTFLAGS'],true) ) {
-
-        $menu_row .= '<form name="moveMessageForm" action="'.$base_uri.'src/'.$where.'?'.'" method="post" style="display: inline">'.
-              '<small>'.
-
-          addHidden('mailbox',$aMailbox['NAME']) .
-          addHidden('msg[0]', $passed_id) . _("Move to:") .
-              '<select name="targetMailbox" style="padding: 0px; margin: 0px">';
-
-        if (isset($lastTargetMailbox) && !empty($lastTargetMailbox)) {
-            $menu_row .= sqimap_mailbox_option_list($imapConnection, array(strtolower($lastTargetMailbox)));
-        } else {
-            $menu_row .= sqimap_mailbox_option_list($imapConnection);
-        }
-        $menu_row .= '</select> ';
-
-        $menu_row .= getButton('submit', 'moveButton',_("Move")) . "\n" . '</form>';
+    // access keys... only add to the bottom menubar, because adding
+    // them twice makes them less functional (press access key, *then*
+    // press <enter> to make it work), and we always have a bottom
+    // menubar, even on the non-JavaScript printable screen
+    //
+    // the one exception we'll make to this is the "move to" (folder
+    // selection) since the user can get confused if the focus for
+    // that access key does not land in the folder select widget at
+    // the top of the page
+    //
+    // FIXME: this also can be confusing for the "as attachment" and "bypass trash" checkboxes, but they are not being excepted like "move to" because pressing their access keys will only focus on them and not check them, which might be even more confusing to naive users or those that can't see the focus indication on the checkbox - this is a compromise, the best I can think of at this time
+    //
+    global $accesskey_read_msg_move_to;
+    if (!$nav_on_top) {
+        global $accesskey_read_msg_reply, $accesskey_read_msg_reply_all,
+               $accesskey_read_msg_forward, $accesskey_read_msg_as_attach,
+               $accesskey_read_msg_delete, $accesskey_read_msg_bypass_trash,
+               $accesskey_read_msg_move;
+    } else {
+        $accesskey_read_msg_reply = $accesskey_read_msg_reply_all =
+        $accesskey_read_msg_forward = $accesskey_read_msg_as_attach =
+        $accesskey_read_msg_delete = $accesskey_read_msg_bypass_trash =
+        $accesskey_read_msg_move = 'NONE';
     }
-    $menu_row .= '</td></tr>';
-
-    // echo rows, with hooks
-    $ret = do_hook_function('read_body_menu_top', array($nav_row, $menu_row));
-    if (is_array($ret)) {
-        if (isset($ret[0]) && !empty($ret[0])) {
-            $nav_row = $ret[0];
-        }
-        if (isset($ret[1]) && !empty($ret[1])) {
-            $menu_row = $ret[1];
-        }
+    $oTemplate->assign('accesskey_read_msg_reply', $accesskey_read_msg_reply);
+    $oTemplate->assign('accesskey_read_msg_reply_all', $accesskey_read_msg_reply_all);
+    $oTemplate->assign('accesskey_read_msg_forward', $accesskey_read_msg_forward);
+    $oTemplate->assign('accesskey_read_msg_as_attach', $accesskey_read_msg_as_attach);
+    $oTemplate->assign('accesskey_read_msg_delete', $accesskey_read_msg_delete);
+    $oTemplate->assign('accesskey_read_msg_bypass_trash', $accesskey_read_msg_bypass_trash);
+    $oTemplate->assign('accesskey_read_msg_move_to', $accesskey_read_msg_move_to);
+    $oTemplate->assign('accesskey_read_msg_move', $accesskey_read_msg_move);
+
+    global $null;
+    do_hook('read_body_menu', $null);
+
+    if ($nav_on_top) {
+        $oTemplate->display('read_menubar_nav.tpl');
+        $oTemplate->display('read_menubar_buttons.tpl');
+    } else {
+        $oTemplate->display('read_menubar_buttons.tpl');
+        $oTemplate->display('read_menubar_nav.tpl');
     }
-    echo '<table width="100%" cellpadding="3" cellspacing="0" align="center" border="0">';
-    echo $nav_on_top ? $nav_row . $menu_row : $menu_row . $nav_row;
-    echo '</table>'."\n";
-    do_hook('read_body_menu_bottom');
+
 }
 
 function formatToolbar($mailbox, $passed_id, $passed_ent_id, $message, $color) {
-    global $base_uri, $where, $what;
+    global $base_uri, $where, $what, $show_html_default,
+           $oTemplate, $download_href, $PHP_SELF,
+           $unsafe_image_toggle_href, $unsafe_image_toggle_text;
 
     $urlMailbox = urlencode($mailbox);
     $urlPassed_id = urlencode($passed_id);
     $urlPassed_ent_id = urlencode($passed_ent_id);
 
     $query_string = 'mailbox=' . $urlMailbox . '&amp;passed_id=' . $urlPassed_id . '&amp;passed_ent_id=' . $urlPassed_ent_id;
-
     if (!empty($where)) {
         $query_string .= '&amp;where=' . urlencode($where);
     }
-
     if (!empty($what)) {
         $query_string .= '&amp;what=' . urlencode($what);
     }
-
     $url = $base_uri.'src/view_header.php?'.$query_string;
 
-    $s  = "<tr>\n" .
-          html_tag( 'td', '', 'right', '', 'valign="middle" width="20%"' ) . '<b>' . _("Options") . ":&nbsp;&nbsp;</b></td>\n" .
-          html_tag( 'td', '', 'left', '', 'valign="middle" width="80%"' ) . '<small>' .
-          '<a href="'.$url.'">'._("View Full Header").'</a>';
+    $links = array();
+    $links[] = array (
+                        'URL'   => $url,
+                        'Text'  => _("View Full Header")
+                     );
+
+    if ( checkForJavaScript() ) { 
+        $links[] = array (
+                        'URL'   => 'javascript:printThis();',
+                        'Text'  => _("Print"),
+                     );
+    } else {
+        $links[] = array (
+                        'URL'   => set_url_var($PHP_SELF, 'print', '1'),
+                        'Text'  => _("Print"),
+                        'Target' => '_blank'
+                     );
+    }
+
+    $links[] = array (
+                        'URL'   => $download_href,
+                        'Text'  => _("Download this as a file")
+                     );
+    $toggle = html_toggle_href($mailbox, $passed_id, $passed_ent_id, $message);
+    if (!empty($toggle)) {
+        $links[] = array (
+                            'URL'   => $toggle,
+                            'Text'  => $show_html_default==1 ? _("View as plain text") : _("View as HTML")
+                         );
+    }
+    if (!empty($unsafe_image_toggle_href)) {
+        $links[] = array (
+                            'URL'   => $unsafe_image_toggle_href,
+                            'Text'  => $unsafe_image_toggle_text
+                         );
+    }
+
+    do_hook('read_body_header_right', $links);
 
-    /* Output the printer friendly link if we are in subtle mode. */
-    $s .= '&nbsp;|&nbsp;' .
-          printer_friendly_link($mailbox, $passed_id, $passed_ent_id);
-    echo $s;
-    do_hook("read_body_header_right");
-    $s = "</small></td>\n" .
-         "</tr>\n";
-    echo $s;
+    $oTemplate->assign('links', $links);
 
+    return $oTemplate->fetch('read_toolbar.tpl');
 }
 
 /***************************/
@@ -739,21 +780,25 @@ function formatToolbar($mailbox, $passed_id, $passed_ent_id, $message, $color) {
 
 /* get the globals we may need */
 
-sqgetGlobalVar('key',       $key,           SQ_COOKIE);
-sqgetGlobalVar('username',  $username,      SQ_SESSION);
-sqgetGlobalVar('onetimepad',$onetimepad,    SQ_SESSION);
 sqgetGlobalVar('delimiter', $delimiter,     SQ_SESSION);
-sqgetGlobalVar('base_uri',  $base_uri,      SQ_SESSION);
 sqgetGlobalVar('lastTargetMailbox', $lastTargetMailbox, SQ_SESSION);
 if (!sqgetGlobalVar('messages', $messages, SQ_SESSION) ) {
     $messages = array();
 }
-
+sqgetGlobalVar('delayed_errors',  $delayed_errors,  SQ_SESSION);
+if (is_array($delayed_errors)) {
+    $oErrorHandler->AssignDelayedErrors($delayed_errors);
+    sqsession_unregister("delayed_errors");
+}
 /** GET VARS */
 sqgetGlobalVar('sendreceipt',   $sendreceipt,   SQ_GET);
 if (!sqgetGlobalVar('where',         $where,         SQ_GET) ) {
     $where = 'right_main.php';
 }
+/*
+ * Used as entry key to the list of uid's cached in the mailbox cache
+ * we use the cached uid's to get the next and prev  message.
+ */
 if (!sqgetGlobalVar('what',          $what,          SQ_GET) ){
     $what = 0;
 }
@@ -770,13 +815,17 @@ if ( sqgetGlobalVar('view_hdr', $temp,  SQ_GET) ) {
     $view_hdr = (int) $temp;
 }
 
+if ( sqgetGlobalVar('account', $temp,  SQ_GET) ) {
+    $iAccount = (int) $temp;
+} else {
+    $iAccount = 0;
+}
+
 /** GET/POST VARS */
+sqgetGlobalVar('passed_id',     $passed_id, SQ_INORDER, NULL, SQ_TYPE_BIGINT);
 sqgetGlobalVar('passed_ent_id', $passed_ent_id);
 sqgetGlobalVar('mailbox',       $mailbox);
 
-if ( sqgetGlobalVar('passed_id', $temp) ) {
-    $passed_id = (int) $temp;
-}
 if ( sqgetGlobalVar('sort', $temp) ) {
     $sort = (int) $temp;
 }
@@ -785,16 +834,88 @@ if ( sqgetGlobalVar('startMessage', $temp) ) {
 } else {
     $startMessage = 1;
 }
+if(sqgetGlobalVar('show_html_default', $temp)) {
+    $show_html_default = (int) $temp;
+}
+
+if(sqgetGlobalVar('view_unsafe_images', $temp)) {
+    $view_unsafe_images = (int) $temp;
+    if($view_unsafe_images == 1) {
+        $show_html_default = 1;
+    }
+} else {
+    $view_unsafe_images = 0;
+}
+
 /**
  * Retrieve mailbox cache
  */
 sqgetGlobalVar('mailbox_cache',$mailbox_cache,SQ_SESSION);
 
 /* end of get globals */
-global $sqimap_capabilities, $lastTargetMailbox;
 
-$imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0);
-$aMailbox = sqm_api_mailbox_select($imapConnection, $mailbox,array('setindex' => $what),array());
+$imapConnection = sqimap_login($username, false, $imapServerAddress, $imapPort, 0);
+$aMailbox = sqm_api_mailbox_select($imapConnection, $iAccount, $mailbox,array('setindex' => $what, 'offset' => $startMessage),array());
+
+
+/**
+ Start code to set the columns to fetch in case of hitting the next/prev link
+ The reason for this is the fact that the cache can be invalidated which means that the headers
+ to fetch aren't there anymore. Before they got calculated when the messagelist was shown.
+
+ Todo, better central handling of setting the mailbox options so we do not need to do the stuff below
+*/
+
+/**
+ * Replace From => To  in case it concerns a draft or sent folder
+ */
+$aColumns = array();
+if (($mailbox == $sent_folder || $mailbox == $draft_folder) &&
+    !in_array(SQM_COL_TO,$index_order)) {
+    $aNewOrder = array(); // nice var name ;)
+    foreach($index_order as $iCol) {
+        if ($iCol == SQM_COL_FROM) {
+            $iCol = SQM_COL_TO;
+        }
+        $aColumns[$iCol] = array();
+   }
+} else {
+   foreach ($index_order as $iCol) {
+       $aColumns[$iCol] = array();
+   }
+}
+
+$aProps = array(
+    'columns' => $aColumns, // columns bound settings
+    'config'  => array(
+                        'highlight_list'        => $message_highlight_list, // row highlighting rules
+                        'trash_folder'          => $trash_folder,
+                        'sent_folder'           => $sent_folder,
+                        'draft_folder'          => $draft_folder));
+
+calcFetchColumns($aMailbox,$aProps);
+
+/**
+ End code to set the columns to fetch in case of hitting the next/prev link
+*/
+
+
+
+/**
+ * Check if cache is still valid, $what contains the key
+ * which gives us acces to the array with uid's. At this moment
+ * 0 is used for a normal message list and search uses 1 as key. This can be
+ * changed / extended in the future.
+ * If on a select of a mailbox we detect that the cache should be invalidated due to
+ * the delete of messages or due to new messages we empty the list with uid's and
+ * that's what we detect below.
+ */
+if (!is_array($aMailbox['UIDSET'][$what])) {
+    fetchMessageHeaders($imapConnection, $aMailbox);
+}
+
+$iSetIndex = $aMailbox['SETINDEX'];
+$aMailbox['CURRENT_MSG'][$iSetIndex] = $passed_id;
 
 /**
  * Update the seen state
@@ -810,8 +931,6 @@ if (isset($aMailbox['MSG_HEADERS'][$passed_id]['FLAGS'])) {
  */
 if ( sqgetGlobalVar('delete_id', $delete_id, SQ_GET) ) {
     handleMessageListForm($imapConnection,$aMailbox,$sButton='setDeleted', array($delete_id));
-//    sqimap_messages_delete($imapConnection, $delete_id, $delete_id, $mailbox);
-//    sqimap_mailbox_expunge_dmn($imapConnection,$aMailbox,$delete_id);
 }
 
 /**
@@ -825,10 +944,14 @@ if (isset($aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT'])) {
 } else {
     $message = sqimap_get_message($imapConnection, $passed_id, $mailbox);
     $FirstTimeSee = !$message->is_seen;
-    $message->is_seen = true;
-    $aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT'] = $message;
 }
 
+/**
+ * update message seen status and put in cache
+ */
+$message->is_seen = true;
+$aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT'] = $message;
+
 if (isset($passed_ent_id) && $passed_ent_id) {
     $message = $message->getEntity($passed_ent_id);
     if ($message->type0 != 'message'  && $message->type1 != 'rfc822') {
@@ -838,6 +961,11 @@ if (isset($passed_ent_id) && $passed_ent_id) {
     $rfc822_header = new Rfc822Header();
     $rfc822_header->parseHeader($read);
     $message->rfc822_header = $rfc822_header;
+} else if ($message->type0 == 'message'  && $message->type1 == 'rfc822' && isset($message->entities[0])) {
+    $read = sqimap_run_command ($imapConnection, "FETCH $passed_id BODY[1.HEADER]", true, $response, $msg, TRUE);
+    $rfc822_header = new Rfc822Header();
+    $rfc822_header->parseHeader($read);
+    $message->rfc822_header = $rfc822_header;
 } else {
     $passed_ent_id = 0;
 }
@@ -850,28 +978,22 @@ $header = $message->header;
 
 if (isset($sendreceipt)) {
    if ( !$message->is_mdnsent ) {
-      $final_recipient = '';
-      if ((isset($identity)) && ($identity != 0)) //Main identity
-         $final_recipient = trim(getPref($data_dir, $username, 'email_address' . $identity, '' ));
-      if ($final_recipient == '' )
-         $final_recipient = trim(getPref($data_dir, $username, 'email_address', '' ));
       $supportMDN = ServerMDNSupport($aMailbox["PERMANENTFLAGS"]);
-      if ( SendMDN( $mailbox, $passed_id, $final_recipient, $message, $imapConnection ) > 0 && $supportMDN ) {
+      if ( SendMDN( $mailbox, $passed_id, $message, $imapConnection ) > 0 && $supportMDN ) {
          ToggleMDNflag( true, $imapConnection, $mailbox, $passed_id);
          $message->is_mdnsent = true;
          $aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT'] = $message;
       }
-      ClearAttachments();
    }
 }
 /***********************************************/
 /* End of block for handling incoming url vars */
 /***********************************************/
 
-
-
+$oTemplate->assign('aAttribs', array('class' => 'entity_sep'));
+$hr = $oTemplate->fetch('horizontal_rule.tpl');
 $messagebody = '';
-do_hook('read_body_top');
+do_hook('read_body_top', $null);
 if ($show_html_default == 1) {
     $ent_ar = $message->findDisplayEntity(array());
 } else {
@@ -881,55 +1003,38 @@ $cnt = count($ent_ar);
 for ($i = 0; $i < $cnt; $i++) {
    $messagebody .= formatBody($imapConnection, $message, $color, $wrap_at, $ent_ar[$i], $passed_id, $mailbox);
    if ($i != $cnt-1) {
-       $messagebody .= '<hr noshade size="1" />';
+       $messagebody .= $hr;
    }
 }
 
-displayPageHeader($color, $mailbox);
-formatMenuBar($aMailbox, $passed_id, $passed_ent_id, $message,false);
+/**
+ * Write mailbox with updated seen flag information back to cache.
+ */
+$mailbox_cache[$iAccount.'_'.$aMailbox['NAME']] = $aMailbox;
+sqsession_register($mailbox_cache,'mailbox_cache');
+$_SESSION['mailbox_cache'] = $mailbox_cache;
+
+// message list URI is used in page header when on read_body
+$oTemplate->assign('message_list_href', get_message_list_uri($aMailbox['NAME'], $startMessage, $what));
+
+displayPageHeader($color, $mailbox,'','');
+
+/* this is the non-javascript version of printer friendly */
+if ( sqgetGlobalVar('print', $print, SQ_GET) ) {
+    $oTemplate->display('read_message_print.tpl');
+} else {
+    formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message,false);
+}
 formatEnvheader($aMailbox, $passed_id, $passed_ent_id, $message, $color, $FirstTimeSee);
-echo '<table width="100%" cellpadding="0" cellspacing="0" align="center" border="0">';
-echo '  <tr><td>';
-echo '    <table width="100%" cellpadding="1" cellspacing="0" align="center" border="0" bgcolor="'.$color[9].'">';
-echo '      <tr><td>';
-echo '        <table width="100%" cellpadding="3" cellspacing="0" align="center" border="0">';
-echo '          <tr bgcolor="'.$color[4].'"><td>';
-// echo '            <table cellpadding="1" cellspacing="5" align="left" border="0">';
-echo html_tag( 'table' ,'' , 'left', '', 'cellpadding="1" cellspacing="5" border="0"' );
-echo '              <tr>' . html_tag( 'td', '<br />'. $messagebody."\n", 'left')
-                        . '</tr>';
-echo '            </table>';
-echo '          </td></tr>';
-echo '        </table></td></tr>';
-echo '    </table>';
-echo '  </td></tr>';
-
-echo '<tr><td height="5" colspan="2" bgcolor="'.
-          $color[4].'"></td></tr>'."\n";
-
-$attachmentsdisplay = formatAttachments($message,$ent_ar,$mailbox, $passed_id);
-if ($attachmentsdisplay) {
-   echo '  </table>';
-   echo '    <table width="100%" cellpadding="1" cellspacing="0" align="center"'.' border="0" bgcolor="'.$color[9].'">';
-   echo '     <tr><td>';
-   echo '       <table width="100%" cellpadding="0" cellspacing="0" align="center" border="0" bgcolor="'.$color[4].'">';
-   echo '        <tr>' . html_tag( 'td', '', 'left', $color[9] );
-   echo '           <b>' . _("Attachments") . ':</b>';
-   echo '        </td></tr>';
-   echo '        <tr><td>';
-   echo '          <table width="100%" cellpadding="2" cellspacing="2" align="center"'.' border="0" bgcolor="'.$color[0].'"><tr><td>';
-   echo              $attachmentsdisplay;
-   echo '          </td></tr></table>';
-   echo '       </td></tr></table>';
-   echo '  </td></tr>';
-   echo '<tr><td height="5" colspan="2" bgcolor="'.
-          $color[4].'"></td></tr>';
-}
-echo '</table>';
+
+$oTemplate->assign('message_body', $messagebody);
+$oTemplate->display('read_message_body.tpl');
+
+formatAttachments($message,$ent_ar,$mailbox, $passed_id);
 
 /* show attached images inline -- if pref'fed so */
-if (($attachment_common_show_images) &&
-    is_array($attachment_common_show_images_list)) {
+if ($attachment_common_show_images && is_array($attachment_common_show_images_list)) {
+    $images = array();
     foreach ($attachment_common_show_images_list as $img) {
         $imgurl = SM_PATH . 'src/download.php' .
                 '?' .
@@ -937,24 +1042,19 @@ if (($attachment_common_show_images) &&
                 '&amp;mailbox='       . urlencode($mailbox) .
                 '&amp;ent_id=' . urlencode($img['ent_id']) .
                 '&amp;absolute_dl=true';
-
-        echo html_tag( 'table', "\n" .
-                    html_tag( 'tr', "\n" .
-                        html_tag( 'td', '<img src="' . $imgurl . '" />' ."\n", 'left'
-                        )
-                    ) ,
-        'center', '', 'cellspacing="0" border="0" cellpadding="2"');
+        $a = array();
+        $a['Name'] = $img['name'];
+        $a['DisplayURL'] = $imgurl;
+        $a['DownloadURL'] = $img['download_href'];
+        $images[] = $a;
     }
+
+    $oTemplate->assign('images', $images);
+    $oTemplate->display('read_display_images_inline.tpl');
 }
 
-formatMenuBar($aMailbox, $passed_id, $passed_ent_id, $message, false, FALSE);
+formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message, false, FALSE);
 
-do_hook('read_body_bottom');
+do_hook('read_body_bottom', $null);
 sqimap_logout($imapConnection);
-/* sessions are written at the end of the script. it's better to register
-   them at the end so we avoid double session_register calls */
-/* add the mailbox to the cache */
-$mailbox_cache[$aMailbox['NAME']] = $aMailbox;
-sqsession_register($mailbox_cache,'mailbox_cache');
-?>
-</body></html>
+$oTemplate->display('footer.tpl');