Fix broken'Thread' and the no-javascript 'All' links (add security tokens)
[squirrelmail.git] / functions / mailbox_display.php
index 18ddf201ed54c4571e5f0195f76bf7f9a1cae2e1..d16679a4d6373132154b04c6897a288e2b73e0cc 100644 (file)
@@ -6,7 +6,7 @@
  * This contains functions that display mailbox information, such as the
  * table row that has sender, date, subject, etc...
  *
- * @copyright © 1999-2007 The SquirrelMail Project Team
+ * @copyright © 1999-2009 The SquirrelMail Project Team
  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  * @version $Id$
  * @package squirrelmail
@@ -624,17 +624,19 @@ function prepareMessageList(&$aMailbox, $aProps) {
                     $aFlagColumn = array('seen' => false,
                                          'deleted'=>false,
                                          'answered'=>false,
+                                         'forwarded'=>false,
                                          'flagged' => false,
                                          'draft' => false);
 
                     if(!is_array($value)) $value = array();
                     foreach ($value as $sFlag => $v) {
                         switch ($sFlag) {
-                          case '\\seen'    : $aFlagColumn['seen']     = true; break;
-                          case '\\deleted' : $aFlagColumn['deleted']  = true; break;
-                          case '\\answered': $aFlagColumn['answered'] = true; break;
-                          case '\\flagged' : $aFlagColumn['flagged']  = true; break;
-                          case '\\draft'   : $aFlagColumn['draft']    = true; break;
+                          case '\\seen'    : $aFlagColumn['seen']      = true; break;
+                          case '\\deleted' : $aFlagColumn['deleted']   = true; break;
+                          case '\\answered': $aFlagColumn['answered']  = true; break;
+                          case '$forwarded': $aFlagColumn['forwarded'] = true; break;
+                          case '\\flagged' : $aFlagColumn['flagged']   = true; break;
+                          case '\\draft'   : $aFlagColumn['draft']     = true; break;
                           default:  break;
                         }
                     }
@@ -973,7 +975,7 @@ function showMessagesForMailbox($imapConnection, &$aMailbox,$aProps, &$iError) {
         $source_url = $php_self;
     }
 
-    $baseurl = $source_url.'?mailbox=' . urlencode($aMailbox['NAME']) .'&account='.$aMailbox['ACCOUNT'];
+    $baseurl = $source_url.'?mailbox=' . urlencode($aMailbox['NAME']) .'&account='.$aMailbox['ACCOUNT'] . (strpos($source_url, 'src/search.php') ? '&smtoken=' . sm_generate_security_token() : '');
     $where = urlencode($aMailbox['SEARCH'][$iSetIndx][0]);
     $what = urlencode($aMailbox['SEARCH'][$iSetIndx][1]);
     $baseurl .= '&where=' . $where .  '&what=' .  $what;
@@ -1002,8 +1004,8 @@ function showMessagesForMailbox($imapConnection, &$aMailbox,$aProps, &$iError) {
 
     /* future admin control over displayable buttons */
     $aAdminControl = array(
-                           'markUnflagged' => 1,
                            'markFlagged'   => 1,
+                           'markUnflagged' => 1,
                            'markRead'      => 1,
                            'markUnread'    => 1,
                            'forward'       => 1,
@@ -1018,8 +1020,8 @@ function showMessagesForMailbox($imapConnection, &$aMailbox,$aProps, &$iError) {
     /* user prefs control */
     $aUserControl = array (
 
-                           'markUnflagged' => $show_flag_buttons,
                            'markFlagged'   => $show_flag_buttons,
+                           'markUnflagged' => $show_flag_buttons,
                            'markRead'      => 1,
                            'markUnread'    => 1,
                            'forward'       => 1,
@@ -1060,17 +1062,37 @@ function showMessagesForMailbox($imapConnection, &$aMailbox,$aProps, &$iError) {
                           );
     /* Button strings */
     $aButtonStrings = array(
-                           'markUnflagged' => _("Unflag"),
-                           'markFlagged'   => _("Flag"),
-                           'markRead'      => _("Read"),
-                           'markUnread'    => _("Unread"),
-                           'forward'       => _("Forward"),
-                           'delete'    => _("Delete"),
-                           'undeleteButton'  => _("Undelete"),
-                           'bypass_trash'  => _("Bypass Trash"),
-                           'expungeButton' => _("Expunge"),
-                           'moveButton'          => _("Move"),
-                           'copyButton'          => _("Copy")
+                           'markFlagged'    => _("Flag"),
+                           'markUnflagged'  => _("Unflag"),
+                           'markRead'       => _("Read"),
+                           'markUnread'     => _("Unread"),
+                           'forward'        => _("Forward"),
+                           'delete'         => _("Delete"),
+                           'undeleteButton' => _("Undelete"),
+                           'bypass_trash'   => _("Bypass Trash"),
+                           'expungeButton'  => _("Expunge"),
+                           'moveButton'     => _("Move"),
+                           'copyButton'     => _("Copy")
+                           );
+    /* Button access keys */
+    global $accesskey_mailbox_flag, $accesskey_mailbox_unflag,
+           $accesskey_mailbox_read, $accesskey_mailbox_unread,
+           $accesskey_mailbox_forward, $accesskey_mailbox_delete,
+           $accesskey_mailbox_undelete, $accesskey_mailbox_bypass_trash,
+           $accesskey_mailbox_expunge, $accesskey_mailbox_move,
+           $accesskey_mailbox_copy, $accesskey_mailbox_move_to;
+    $aButtonAccessKeys = array(
+                           'markFlagged'    => $accesskey_mailbox_flag,
+                           'markUnflagged'  => $accesskey_mailbox_unflag,
+                           'markRead'       => $accesskey_mailbox_read,
+                           'markUnread'     => $accesskey_mailbox_unread,
+                           'forward'        => $accesskey_mailbox_forward,
+                           'delete'         => $accesskey_mailbox_delete,
+                           'undeleteButton' => $accesskey_mailbox_undelete,
+                           'bypass_trash'   => $accesskey_mailbox_bypass_trash,
+                           'expungeButton'  => $accesskey_mailbox_expunge,
+                           'moveButton'     => $accesskey_mailbox_move,
+                           'copyButton'     => $accesskey_mailbox_copy,
                            );
 
 
@@ -1082,8 +1104,8 @@ function showMessagesForMailbox($imapConnection, &$aMailbox,$aProps, &$iError) {
     foreach($aAdminControl as $k => $v) {
         if ($v & $aUserControl[$k] & $aImapControl[$k]) {
             switch ($k) {
-              case 'markUnflagged':
               case 'markFlagged':
+              case 'markUnflagged':
               case 'markRead':
               case 'markUnread':
               case 'delete':
@@ -1091,23 +1113,24 @@ function showMessagesForMailbox($imapConnection, &$aMailbox,$aProps, &$iError) {
               case 'expungeButton':
               case 'forward':
                 $aFormElements[$k] 
-                    = array('value' => $aButtonStrings[$k], 'type' => 'submit');
+                    = array('value' => $aButtonStrings[$k], 'type' => 'submit', 'accesskey' => (isset($aButtonAccessKeys[$k]) ? $aButtonAccessKeys[$k] : 'NONE'));
                 break;
               case 'bypass_trash':
                 $aFormElements[$k] 
-                    = array('value' => $aButtonStrings[$k], 'type' => 'checkbox');
+                    = array('value' => $aButtonStrings[$k], 'type' => 'checkbox', 'accesskey' => (isset($aButtonAccessKeys[$k]) ? $aButtonAccessKeys[$k] : 'NONE'));
                 break;
               case 'moveButton':
               case 'copyButton':
                 $aFormElements['targetMailbox']
                     = array('options_list' => sqimap_mailbox_option_list($imapConnection, array(strtolower($lastTargetMailbox)), 0, $boxes),
-                            'type' => 'select');
+                            'type' => 'select',
+                            'accesskey' => $accesskey_mailbox_move_to);
                 $aFormElements['mailbox']       
                     = array('value' => $aMailbox['NAME'], 'type' => 'hidden');
                 $aFormElements['startMessage']  
                     = array('value' => $aMailbox['PAGEOFFSET'], 'type' => 'hidden');
                 $aFormElements[$k]              
-                    = array('value' => $aButtonStrings[$k], 'type' => 'submit');
+                    = array('value' => $aButtonStrings[$k], 'type' => 'submit', 'accesskey' => (isset($aButtonAccessKeys[$k]) ? $aButtonAccessKeys[$k] : 'NONE'));
                 break;
             }
         }
@@ -1277,23 +1300,6 @@ function truncateWithEntities($s, $iTrimAt) {
 }
 
 
-/**
- * This should go in imap_mailbox.php
- * @param string $mailbox
- */
-function handleAsSent($mailbox) {
-    global $handleAsSent_result;
-
-    /* First check if this is the sent or draft folder. */
-    $handleAsSent_result = isSentMailbox($mailbox) || isDraftMailbox($mailbox);
-
-    /* Then check the result of the handleAsSent hook. */
-    do_hook('check_handleAsSent_result', $mailbox);
-
-    /* And return the result. */
-    return $handleAsSent_result;
-}
-
 /**
  * Process messages list form and handle the cache gracefully. If $sButton and
  * $aUid are provided as argument then you can fake a message list submit and
@@ -1334,6 +1340,16 @@ function handleMessageListForm($imapConnection, &$aMailbox, $sButton='',
     /* retrieve the check boxes */
     $aUid = (isset($msg) && is_array($msg)) ? array_values($msg) : $aUid;
     if (count($aUid) && $sButton != 'expunge') {
+
+        // don't do anything to any messages until we have done security check
+        // FIXME: not sure this code really belongs here, but there's nowhere else to put it with this architecture
+        sqgetGlobalVar('smtoken', $submitted_token, SQ_FORM, '');
+        sm_validate_security_token($submitted_token, 3600, TRUE);
+
+        // make sure message UIDs are sanitized (BIGINT)
+        foreach ($aUid as $i => $uid)
+           $aUid[$i] = (preg_match('/^[0-9]+$/', $uid) ? $uid : '0');
+
         $aUpdatedMsgs = false;
         $bExpunge = false;
         switch ($sButton) {
@@ -1376,12 +1392,14 @@ function handleMessageListForm($imapConnection, &$aMailbox, $sButton='',
             if (count($aMsgHeaders)) {
                 $composesession = attachSelectedMessages($imapConnection,$aMsgHeaders);
                 // dirty hack, add info to $aMailbox
-                $aMailbox['FORWARD_SESSION'] = $composesession;
+                $aMailbox['FORWARD_SESSION']['SESSION_NUMBER'] = $composesession;
+                $aMailbox['FORWARD_SESSION']['UIDS'] = $aUid;
             }
             break;
           default:
              // Hook for plugin buttons
-             do_hook('mailbox_display_button_action', $aUid);
+             $temp = array(&$sButton, &$aMailbox, $iAccount, $aMailbox['NAME'], &$aUid);
+             do_hook('mailbox_display_button_action', $temp);
              break;
         }
         /**
@@ -1409,6 +1427,7 @@ function handleMessageListForm($imapConnection, &$aMailbox, $sButton='',
                         $message = $aMailbox['MSG_HEADERS'][$iUid]['MESSAGE_OBJECT'];
                         $message->is_seen = false;
                         $message->is_answered = false;
+                        $message->is_forwarded = false;
                         $message->is_deleted = false;
                         $message->is_flagged = false;
                         $message->is_mdnsent = false;
@@ -1417,6 +1436,8 @@ function handleMessageListForm($imapConnection, &$aMailbox, $sButton='',
                                 $message->is_seen = true;
                             else if (strtolower($flag) == '\\answered' && $value)
                                 $message->is_answered = true;
+                            else if (strtolower($flag) == '$forwarded' && $value)
+                                $message->is_forwarded = true;
                             else if (strtolower($flag) == '\\deleted' && $value)
                                 $message->is_deleted = true;
                             else if (strtolower($flag) == '\\flagged' && $value)
@@ -1490,7 +1511,15 @@ function handleMessageListForm($imapConnection, &$aMailbox, $sButton='',
             sqimap_run_command($imapConnection,'CLOSE',false,$result,$message);
             $aMailbox = sqm_api_mailbox_select($imapConnection,$iAccount, $aMailbox['NAME'],array(),array());
         } else {
-            if ($sButton) {
+            // this is the same hook as above, but here it is called in the
+            // context of not having had any messages selected and if any
+            // plugin handles the situation, it should return TRUE so we
+            // know this was not an erroneous user action
+            //
+            global $null;
+            $temp = array(&$sButton, &$aMailbox, $iAccount, $aMailbox['NAME'], $null);
+            if (!boolean_hook_function('mailbox_display_button_action', $temp, 1)
+             && $sButton) {
                 $sError = _("No messages were selected.");
             }
         }
@@ -1549,8 +1578,7 @@ function attachSelectedMessages($imapConnection,$aMsgHeaders) {
             fwrite ($fp, $body);
             fclose($fp);
 
-            $composeMessage->initAttachment('message/rfc822',$subject.'.msg',
-                 $filename);
+            $composeMessage->initAttachment('message/rfc822', $subject . '.eml', $filename);
         }
     }