prefer to use move_uploaded_file over rename, <quote who=""> indeed doesn't
[squirrelmail.git] / src / compose.php
index a11e178e518d84a12e1d3a5395ef8d2e971b0e6e..468b262dc95f3dfba5bdb202bde61a0805c4ed36 100644 (file)
@@ -3,9 +3,6 @@
 /**
  * compose.php
  *
- * Copyright (c) 1999-2005 The SquirrelMail Project Team
- * Licensed under the GNU GPL. For full terms see the file COPYING.
- *
  * This code sends a mail.
  *
  * There are 4 modes of operation:
@@ -14,6 +11,8 @@
  *    - Send mail
  *    - Save As Draft
  *
+ * @copyright &copy; 1999-2005 The SquirrelMail Project Team
+ * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  * @version $Id$
  * @package squirrelmail
  */
@@ -83,6 +82,7 @@ if ( sqgetGlobalVar('startMessage',$startMessage) ) {
     $startMessage = 1;
 }
 
+
 /** POST VARS */
 sqgetGlobalVar('sigappend',             $sigappend,             SQ_POST);
 sqgetGlobalVar('from_htmladdr_search',  $from_htmladdr_search,  SQ_POST);
@@ -97,6 +97,12 @@ if ( sqgetGlobalVar('return', $temp, SQ_POST) ) {
 
 /** GET VARS */
 sqgetGlobalVar('attachedmessages', $attachedmessages, SQ_GET);
+if ( sqgetGlobalVar('account', $temp,  SQ_GET) ) {
+    $iAccount = (int) $temp;
+} else {
+    $iAccount = 0;
+}
+
 
 /** get smaction */
 if ( !sqgetGlobalVar('smaction',$action) )
@@ -179,8 +185,6 @@ function getReplyCitation($orig_from, $orig_date) {
         $sOrig_from = decodeHeader($orig_from->getAddress(false),false,false,true);
     }
 
-//    $from = decodeHeader($orig_header->getAddr_s('from',"\n$indent"),false,false);
-
     /* First, return an empty string when no citation style selected. */
     if (($reply_citation_style == '') || ($reply_citation_style == 'none')) {
         return '';
@@ -200,8 +204,7 @@ function getReplyCitation($orig_from, $orig_date) {
         $full_reply_citation = sprintf(_("%s wrote:"),$sOrig_from);
         break;
     case 'quote_who':
-        // FIXME: do we have to translate xml formating?
-        $start = '<' . _("quote") . ' ' . _("who") . '="';
+        $start = '<quote who="';
         $end   = '">';
         $full_reply_citation = $start . $sOrig_from . $end;
         break;
@@ -342,7 +345,6 @@ if (!isset($compose_messages)) {
 }
 
 if (!isset($compose_messages[$session]) || ($compose_messages[$session] == NULL)) {
-    /* if (!array_key_exists($session, $compose_messages)) {  /* We can only do this in PHP >= 4.1 */
     $composeMessage = new Message();
     $rfc822_header = new Rfc822Header();
     $composeMessage->rfc822_header = $rfc822_header;
@@ -384,6 +386,7 @@ if ($draft) {
             }
             sqimap_logout($imap_stream);
         }
+        session_write_close();
         if ($compose_new_win == '1') {
             if ( !isset($pageheader_sent) || !$pageheader_sent ) {
                 Header("Location: $location/compose.php?saved_draft=yes&session=$composesession");
@@ -417,7 +420,7 @@ if ($send) {
     if (checkInput(false) && !isset($AttachFailure)) {
         if ($mailbox == "All Folders") {
             /* We entered compose via the search results page */
-            $mailbox="INBOX"; /* Send 'em to INBOX, that's safe enough */
+            $mailbox = 'INBOX'; /* Send 'em to INBOX, that's safe enough */
         }
         $urlMailbox = urlencode (trim($mailbox));
         if (! isset($passed_id)) {
@@ -458,11 +461,13 @@ if ($send) {
         $composeMessage=$compose_messages[$session];
 
         $Result = deliverMessage($composeMessage);
+        do_hook('compose_send_after', $Result, $composeMessage);
         if (! $Result) {
             showInputForm($session);
             exit();
         }
         unset($compose_messages[$session]);
+        
         /* if it is resumed draft, delete draft message */
         if ( isset($delete_draft)) {
             $imap_stream = sqimap_login($username, $key, $imapServerAddress, $imapPort, false);
@@ -476,6 +481,7 @@ if ($send) {
             }
             sqimap_logout($imap_stream);
         }
+        session_write_close();
         if ($compose_new_win == '1') {
             if ( !isset($pageheader_sent) || !$pageheader_sent ) {
                 Header("Location: $location/compose.php?mail_sent=yes");
@@ -587,9 +593,10 @@ elseif (isset($sigappend)) {
     if (isset($delete) && is_array($delete)) {
         $composeMessage = $compose_messages[$session];
         foreach($delete as $index) {
-            $attached_file = $composeMessage->entities[$index]->att_local_name;
-            unlink ($attached_file);
-            unset ($composeMessage->entities[$index]);
+            if (!empty($composeMessage->entities) && isset($composeMessage->entities[$index])) {
+                $composeMessage->entities[$index]->purgeAttachments();
+                unset ($composeMessage->entities[$index]);
+            }
         }
         $new_entities = array();
         foreach ($composeMessage->entities as $entity) {
@@ -756,7 +763,6 @@ function newMail ($mailbox='', $passed_id='', $passed_ent_id='', $action='', $se
         } else {
             $mailprio = '';
         }
-        //ClearAttachments($session);
 
         $identity = '';
         $from_o = $orig_header->from;
@@ -1018,7 +1024,17 @@ function showInputForm ($session, $values=false) {
         $from_htmladdr_search, $location_of_buttons, $attachment_dir,
         $username, $data_dir, $identity, $idents, $delete_draft,
         $mailprio, $compose_new_win, $saved_draft, $mail_sent, $sig_first,
-        $username, $compose_messages, $composesession, $default_charset;
+        $username, $compose_messages, $composesession, $default_charset,
+        $compose_onsubmit;
+
+    if (checkForJavascript()) {
+        $onfocus = ' onfocus="alreadyFocused=true;"';
+        $onfocus_array = array('onfocus' => 'alreadyFocused=true;');
+    }
+    else {
+        $onfocus = '';
+        $onfocus_array = array();
+    }
 
     $composeMessage = $compose_messages[$session];
     if ($values) {
@@ -1048,8 +1064,37 @@ function showInputForm ($session, $values=false) {
 
     echo "\n" . '<form name="compose" action="compose.php" method="post" ' .
         'enctype="multipart/form-data"';
+
+    $compose_onsubmit = array();
     do_hook('compose_form');
 
+    // Plugins that use compose_form hook can add an array entry
+    // to the globally scoped $compose_onsubmit; we add them up
+    // here and format the form tag's full onsubmit handler.  
+    // Each plugin should use "return false" if they need to 
+    // stop form submission but otherwise should NOT use "return
+    // true" to give other plugins the chance to do what they need
+    // to do; SquirrelMail itself will add the final "return true".
+    // Onsubmit text is enclosed inside of double quotes, so plugins
+    // need to quote accordingly.
+    if (checkForJavascript()) {
+        $onsubmit_text = ' onsubmit="';
+        if (empty($compose_onsubmit)) 
+            $compose_onsubmit = array();
+        else if (!is_array($compose_onsubmit)) 
+            $compose_onsubmit = array($compose_onsubmit);
+
+        foreach ($compose_onsubmit as $text) {
+            $text = trim($text);
+            if (substr($text, -1) != ';' && substr($text, -1) != '}') 
+                $text .= '; ';
+            $onsubmit_text .= $text;
+        }
+
+        echo $onsubmit_text . ' return true;"';
+    }
+    
+
     echo ">\n";
 
     echo addHidden('startMessage', $startMessage);
@@ -1108,28 +1153,28 @@ function showInputForm ($session, $values=false) {
         html_tag( 'td', '', 'right', $color[4], 'width="10%"' ) .
         _("To") . ':</td>' . "\n" .
         html_tag( 'td', '', 'left', $color[4], 'width="90%"' ) .
-        addInput('send_to', $send_to, 60). '<br />' . "\n" .
+        addInput('send_to', $send_to, 60, 0, $onfocus_array). '<br />' . "\n" .
         '      </td>' . "\n" .
         '   </tr>' . "\n" .
         '   <tr>' . "\n" .
         html_tag( 'td', '', 'right', $color[4] ) .
         _("Cc") . ':</td>' . "\n" .
         html_tag( 'td', '', 'left', $color[4] ) .
-        addInput('send_to_cc', $send_to_cc, 60). '<br />' . "\n" .
+        addInput('send_to_cc', $send_to_cc, 60, 0, $onfocus_array). '<br />' . "\n" .
         '      </td>' . "\n" .
         '   </tr>' . "\n" .
         '   <tr>' . "\n" .
         html_tag( 'td', '', 'right', $color[4] ) .
         _("Bcc") . ':</td>' . "\n" .
         html_tag( 'td', '', 'left', $color[4] ) .
-        addInput('send_to_bcc', $send_to_bcc, 60).'<br />' . "\n" .
+        addInput('send_to_bcc', $send_to_bcc, 60, 0, $onfocus_array).'<br />' . "\n" .
         '      </td>' . "\n" .
         '   </tr>' . "\n" .
         '   <tr>' . "\n" .
         html_tag( 'td', '', 'right', $color[4] ) .
         _("Subject") . ':</td>' . "\n" .
         html_tag( 'td', '', 'left', $color[4] ) . "\n";
-    echo '         '.addInput('subject', $subject, 60).
+    echo '         '.addInput('subject', $subject, 60, 0, $onfocus_array).
         '      </td>' . "\n" .
         '   </tr>' . "\n\n";
 
@@ -1142,13 +1187,13 @@ function showInputForm ($session, $values=false) {
         echo '   <tr>' . "\n" .
             '      <td bgcolor="' . $color[0] . '" colspan="2" align="center">' . "\n" .
             '         <textarea name="body" id="body" rows="' . (int)$editor_height .
-            '" cols="' . (int)$editor_size . '" wrap="virtual">';
+            '" cols="' . (int)$editor_size . '" wrap="virtual"' . $onfocus . '>';
     }
     else {
         echo '   <tr>' . "\n" .
             '      <td bgcolor="' . $color[4] . '" colspan="2">' . "\n" .
             '         &nbsp;&nbsp;<textarea name="body" id="body" rows="' . (int)$editor_height .
-            '" cols="' . (int)$editor_size . '" wrap="virtual">';
+            '" cols="' . (int)$editor_size . '" wrap="virtual"' . $onfocus . '>';
     }
 
     if ($use_signature == true && $newmail == true && !isset($from_htmladdr_search)) {
@@ -1378,7 +1423,7 @@ function checkInput ($show) {
 
 /* True if FAILURE */
 function saveAttachedFiles($session) {
-    global $_FILES, $attachment_dir, $attachments, $username,
+    global $_FILES, $attachment_dir, $username,
         $data_dir, $compose_messages;
 
     /* get out of here if no file was attached at all */
@@ -1394,10 +1439,10 @@ function saveAttachedFiles($session) {
         $full_localfilename = "$hashed_attachment_dir/$localfilename";
     }
 
-    // FIXME: we SHOULD prefer move_uploaded_file over rename because
-    // m_u_f works better with restricted PHP installs (safe_mode, open_basedir)
-    if (!@rename($_FILES['attachfile']['tmp_name'], $full_localfilename)) {
-        if (!@move_uploaded_file($_FILES['attachfile']['tmp_name'],$full_localfilename)) {
+    // m_u_f works better with restricted PHP installs (safe_mode, open_basedir),
+    // if that doesn't work, try a simple rename.
+    if (!@move_uploaded_file($_FILES['attachfile']['tmp_name'],$full_localfilename)) {
+        if (!@rename($_FILES['attachfile']['tmp_name'], $full_localfilename)) {
             return true;
         }
     }
@@ -1409,18 +1454,6 @@ function saveAttachedFiles($session) {
     sqsession_register($compose_messages , 'compose_messages');
 }
 
-function ClearAttachments($composeMessage) {
-    if ($composeMessage->att_local_name) {
-        $attached_file = $composeMessage->att_local_name;
-        if (file_exists($attached_file)) {
-            unlink($attached_file);
-        }
-    }
-    for ($i=0, $entCount=count($composeMessage->entities);$i< $entCount; ++$i) {
-        ClearAttachments($composeMessage->entities[$i]);
-    }
-}
-
 /* parse values like 8M and 2k into bytes */
 function getByteSize($ini_size) {
 
@@ -1454,7 +1487,7 @@ function getByteSize($ini_size) {
 
 /**
  * temporary function to make use of the deliver class.
- * In the future the responsable backend should be automaticly loaded
+ * In the future the responsible backend should be automaticly loaded
  * and conf.pl should show a list of available backends.
  * The message also should be constructed by the message class.
  */
@@ -1592,6 +1625,7 @@ function deliverMessage($composeMessage, $draft=false) {
             sqimap_append_done ($imap_stream, $draft_folder);
             sqimap_logout($imap_stream);
             unset ($imap_deliver);
+            $composeMessage->purgeAttachments();
             return $length;
         } else {
             $msg  = '<br />'.sprintf(_("Error: Draft folder %s does not exist."), $draft_folder);
@@ -1599,12 +1633,12 @@ function deliverMessage($composeMessage, $draft=false) {
             return false;
         }
     }
-    $succes = false;
+    $success = false;
     if ($stream) {
         $length = $deliver->mail($composeMessage, $stream);
-        $succes = $deliver->finalizeStream($stream);
+        $success = $deliver->finalizeStream($stream);
     }
-    if (!$succes) {
+    if (!$success) {
         $msg  = $deliver->dlv_msg . '<br />' .
             _("Server replied:") . ' ' . $deliver->dlv_ret_nr . ' ' .
             $deliver->dlv_server_msg;
@@ -1649,15 +1683,32 @@ function deliverMessage($composeMessage, $draft=false) {
             sqimap_append_done ($imap_stream, $sent_folder);
             unset ($imap_deliver);
         }
-        global $passed_id, $mailbox, $action;
-        ClearAttachments($composeMessage);
+
+        global $passed_id, $mailbox, $action, $what, $iAccount,$startMessage;
+
+        $composeMessage->purgeAttachments();
         if ($action == 'reply' || $action == 'reply_all') {
-            sqimap_mailbox_select ($imap_stream, $mailbox);
-            sqimap_toggle_flag($imap_stream, array($passed_id), '\\Answered', true, false);
+            $aMailbox = sqm_api_mailbox_select($imap_stream, $iAccount, $mailbox,array('setindex' => $what, 'offset' => $startMessage),array());
+            //sqimap_mailbox_select ($imap_stream, $mailbox);
+            $aUpdatedMsgs = sqimap_toggle_flag($imap_stream, array($passed_id), '\\Answered', true, false);
+             if (isset($aUpdatedMsgs[$passed_id]['FLAGS'])) {
+                /**
+                 * Only update the cached headers if the header is
+                 * cached.
+                 */
+                if (isset($aMailbox['MSG_HEADERS'][$passed_id])) {
+                    $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS'] = $aMsg['FLAGS'];
+                }
+            }
+            /**
+             * Write mailbox with updated seen flag information back to cache.
+             */
+            $mailbox_cache[$iAccount.'_'.$aMailbox['NAME']] = $aMailbox;
+            sqsession_register($mailbox_cache,'mailbox_cache');
         }
         sqimap_logout($imap_stream);
     }
-    return $succes;
+    return $success;
 }
 
-?>
\ No newline at end of file
+?>