Implement ability to move to next message after moving the one you are viewing, per...
[squirrelmail.git] / src / read_body.php
index f8fde2ed85dc07339cffc41cb4d721df315eee6f..dbc58c3593863b4fef9c32b35288111b31613a29 100644 (file)
@@ -6,7 +6,7 @@
  * 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
+ * @copyright 1999-2020 The SquirrelMail Project Team
  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  * @version $Id$
  * @package squirrelmail
@@ -37,7 +37,7 @@ require_once(SM_PATH . 'functions/compose.php');
  * and sorted msgs array and return the index of the next message
  *
  * @param int $passed_id The current message UID
- * @return the index of the next valid message from the array
+ * @return the index of the next valid message from the array or -1 if there is no next message
  */
 function findNextMessage($uidset,$passed_id='backwards') {
     if (!is_array($uidset)) {
@@ -59,7 +59,7 @@ function findNextMessage($uidset,$passed_id='backwards') {
  * and sorted msgs array and return the index of the previous message
  *
  * @param int $passed_id The current message UID
- * @return the index of the next valid message from the array
+ * @return the index of the previous valid message from the array or -1 if there is no previous message
  */
 
 function findPreviousMessage($uidset, $passed_id) {
@@ -206,7 +206,7 @@ function SendMDN ( $mailbox, $passed_id, $message, $imapConnection) {
     if ($special_encoding) {
         $mime_header->encoding = $special_encoding;
     } else {
-        $mime_header->encoding = 'us-ascii';
+        $mime_header->encoding = '7bit';
     }
     if ($default_charset) {
         $mime_header->parameters['charset'] = $default_charset;
@@ -230,7 +230,7 @@ function SendMDN ( $mailbox, $passed_id, $message, $imapConnection) {
     $mime_header = new MessageHeader;
     $mime_header->type0 = 'message';
     $mime_header->type1 = 'disposition-notification';
-    $mime_header->encoding = 'us-ascii';
+    $mime_header->encoding = '7bit';
     $part2->mime_header = $mime_header;
 
     $composeMessage = new Message();
@@ -273,7 +273,7 @@ function SendMDN ( $mailbox, $passed_id, $message, $imapConnection) {
         if (! empty($deliver->dlv_server_msg)) {
             $msg.= "\n" .
                 _("Server replied:") . ' ' . $deliver->dlv_ret_nr . ' ' .
-                nl2br(htmlspecialchars($deliver->dlv_server_msg));
+                nl2br(sm_encode_html_special_chars($deliver->dlv_server_msg));
         }
         plain_error_message($msg);
     } else {
@@ -358,7 +358,7 @@ function formatRecipientString($recipients, $item ) {
             $a[] = array(
                             // note: decodeHeader is htmlsafe by default
                             'Name'  => decodeHeader($r->getAddress(false)),
-                            'Email' => htmlspecialchars($r->getEmail()),
+                            'Email' => sm_encode_html_special_chars($r->getEmail()),
                             'Full'  => decodeHeader($r->getAddress(true))
                         );
         }
@@ -479,7 +479,7 @@ function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message,
            $enable_forward_as_attachment, $imapConnection, $lastTargetMailbox,
            $delete_prev_next_display, $show_copy_buttons,
            $compose_new_win, $compose_width, $compose_height,
-           $oTemplate;
+           $oTemplate, $return_to_message_list_after_move;
 
     //FIXME cleanup argument list, use $aMailbox where possible
     $mailbox = $aMailbox['NAME'];
@@ -554,7 +554,8 @@ function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message,
                        '&mailbox='.$urlMailbox.'&sort='.$sort.
                        '&startMessage='.$startMessage.'&show_more=0'.
                        "&where=$where&what=$what" .
-                       '&delete_id='.$passed_id;
+                       '&delete_id='.$passed_id .
+                       '&smtoken='.sm_generate_security_token();
             }
 
             if ($next >= 0) {
@@ -562,7 +563,8 @@ function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message,
                        '&mailbox='.$urlMailbox.'&sort='.$sort.
                        '&startMessage='.$startMessage.'&show_more=0'.
                        "&where=$where&what=$what" .
-                       '&delete_id='.$passed_id;
+                       '&delete_id='.$passed_id .
+                       '&smtoken='.sm_generate_security_token();
             }
         }
     }
@@ -628,8 +630,8 @@ function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message,
 
     // If Draft folder - create Resume link
     $resume_draft = $edit_as_new = false;
-    if (($mailbox == $draft_folder) && ($save_as_draft)) {
-        $resume_draft = true; 'smaction_draft';
+    if (isDraftMailbox($mailbox) && ($save_as_draft)) {
+        $resume_draft = true;
     } else if (handleAsSent($mailbox)) {
         $edit_as_new = true;
     }
@@ -638,16 +640,22 @@ function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message,
 
     $oTemplate->assign('mailboxes', sqimap_mailbox_option_array($imapConnection));
     if (in_array('\\deleted', $aMailbox['PERMANENTFLAGS'],true)) {
-        $delete_url = $base_uri . "src/$where";
         $oTemplate->assign('can_be_deleted', true);
-        $oTemplate->assign('move_delete_form_action', $base_uri.'src/'.$where);
+        // force return-to-message-list if this is the only message in the folder
+        if ($return_to_message_list_after_move || ($next < 0 && $prev < 0))
+            $oTemplate->assign('move_delete_form_action', $base_uri.'src/'.$where);
+        else
+            $oTemplate->assign('move_delete_form_action', $base_uri.'src/read_body.php');
         $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)) {
             $oTemplate->assign('can_be_moved', true);
             $oTemplate->assign('move_form_extra', addHidden('mailbox', $aMailbox['NAME'])."\n" .
-                                                  addHidden('msg[0]', $passed_id)."\n" );
+                                                  addHidden('msg[0]', $passed_id)."\n" .
+                                                  // only need when $return_to_message_list_after_move is off
+                                                  addHidden('passed_id', ($next >= 0 ? $next : $prev))."\n" .
+                                                  addHidden('startMessage', $startMessage)."\n" );
             $oTemplate->assign('last_move_target', isset($lastTargetMailbox) && !empty($lastTargetMailbox) ? $lastTargetMailbox : '');
             $oTemplate->assign('can_be_copied', $show_copy_buttons==1);
         } else {
@@ -666,29 +674,22 @@ function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message,
         $oTemplate->assign('can_be_copied', false);
     }
 
-    // access keys... only add to the bottom menubar, because adding
+    // access keys... only add to the top 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
+    // press <enter> to make it work)
     //
-    // 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) {
+    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;
+               $accesskey_read_msg_move, $accesskey_read_msg_move_to,
+               $accesskey_read_msg_copy;
     } 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';
+        $accesskey_read_msg_move = $accesskey_read_msg_move_to =
+        $accesskey_read_msg_copy = 'NONE';
     }
     $oTemplate->assign('accesskey_read_msg_reply', $accesskey_read_msg_reply);
     $oTemplate->assign('accesskey_read_msg_reply_all', $accesskey_read_msg_reply_all);
@@ -698,6 +699,7 @@ function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message,
     $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);
+    $oTemplate->assign('accesskey_read_msg_copy', $accesskey_read_msg_copy);
 
     global $null;
     do_hook('read_body_menu', $null);
@@ -933,6 +935,14 @@ if ( sqgetGlobalVar('delete_id', $delete_id, SQ_GET) ) {
     handleMessageListForm($imapConnection,$aMailbox,$sButton='setDeleted', array($delete_id));
 }
 
+/**
+ * or move button... why is handleMessageListForm (per above) conditional anway?
+ */
+if ( sqgetGlobalVar('moveButton', $ignore, SQ_POST) ) {
+    $sError = handleMessageListForm($imapConnection,$aMailbox);
+    sqgetGlobalVar('targetMailbox', $lastTargetMailbox, SQ_POST);
+}
+
 /**
  * $message contains all information about the message
  * including header and body
@@ -971,6 +981,14 @@ if (isset($passed_ent_id) && $passed_ent_id) {
 }
 $header = $message->header;
 
+// gmail does not mark messages as read when retrieving the message body
+// even though RFC 3501, section 6.4.5 (FETCH Command) says:
+// "The \Seen flag is implicitly set; if this causes the flags to change,
+// they SHOULD be included as part of the FETCH responses."
+//
+if ($imap_server_type == 'gmail') {
+    sqimap_toggle_flag($imapConnection, $passed_id, '\\Seen', true, true);
+}
 
 /****************************************/
 /* Block for handling incoming url vars */