Account for case when no reply-to is set in user prefs
[squirrelmail.git] / src / compose.php
index 069623e38d89775f8b9a64b619cfc2acda573159..fb0a9c57f5af6233667736e6e71d4165b933c0b4 100644 (file)
@@ -10,7 +10,7 @@
  *    - Send mail
  *    - Save As Draft
  *
  *    - Send mail
  *    - Save As Draft
  *
- * @copyright © 1999-2007 The SquirrelMail Project Team
+ * @copyright 1999-2012 The SquirrelMail Project Team
  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  * @version $Id$
  * @package squirrelmail
  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  * @version $Id$
  * @package squirrelmail
@@ -87,6 +87,7 @@ sqgetGlobalVar('html_addr_search',$html_addr_search, $SQ_GLOBAL);
 sqgetGlobalVar('mail_sent',$mail_sent, $SQ_GLOBAL);
 sqgetGlobalVar('passed_id',$passed_id, $SQ_GLOBAL, NULL, SQ_TYPE_BIGINT);
 sqgetGlobalVar('passed_ent_id',$passed_ent_id, $SQ_GLOBAL);
 sqgetGlobalVar('mail_sent',$mail_sent, $SQ_GLOBAL);
 sqgetGlobalVar('passed_id',$passed_id, $SQ_GLOBAL, NULL, SQ_TYPE_BIGINT);
 sqgetGlobalVar('passed_ent_id',$passed_ent_id, $SQ_GLOBAL);
+sqgetGlobalVar('fwduid',$fwduid, $SQ_GLOBAL, '');
 
 sqgetGlobalVar('attach',$attach, SQ_POST);
 sqgetGlobalVar('draft',$draft, SQ_POST);
 
 sqgetGlobalVar('attach',$attach, SQ_POST);
 sqgetGlobalVar('draft',$draft, SQ_POST);
@@ -137,6 +138,8 @@ if ( !sqgetGlobalVar('smaction',$action) )
     if ( sqgetGlobalVar('smaction_edit_new',$tmp) )   $action = 'edit_as_new';
 }
 
     if ( sqgetGlobalVar('smaction_edit_new',$tmp) )   $action = 'edit_as_new';
 }
 
+sqgetGlobalVar('smtoken', $submitted_token, $SQ_GLOBAL, '');
+
 /**
  * Here we decode the data passed in from mailto.php.
  */
 /**
  * Here we decode the data passed in from mailto.php.
  */
@@ -193,12 +196,10 @@ function replyAllString($header) {
     $url_replytoallcc = '';
     foreach( $url_replytoall_ar as $email => $personal) {
         if ($personal) {
     $url_replytoallcc = '';
     foreach( $url_replytoall_ar as $email => $personal) {
         if ($personal) {
-            // if personal name contains address separator then surround
-            // the personal name with double quotes.
-            if (strpos($personal,',') !== false) {
-                $personal = '"'.$personal.'"';
-            }
-            $url_replytoallcc .= ", $personal <$email>";
+            // always quote personal name (can't just quote it if
+            // it contains a comma separator, since it might still
+            // be encoded)
+            $url_replytoallcc .= ", \"$personal\" <$email>";
         } else {
             $url_replytoallcc .= ', '. $email;
         }
         } else {
             $url_replytoallcc .= ', '. $email;
         }
@@ -336,7 +337,7 @@ if (sqsession_is_registered('session_expired_post')) {
             'subject', 'newmail', 'send_to_bcc', 'passed_id', 'mailbox', 
             'from_htmladdr_search', 'identity', 'draft_id', 'delete_draft', 
             'mailprio', 'edit_as_new', 'attachments', 'composesession', 
             'subject', 'newmail', 'send_to_bcc', 'passed_id', 'mailbox', 
             'from_htmladdr_search', 'identity', 'draft_id', 'delete_draft', 
             'mailprio', 'edit_as_new', 'attachments', 'composesession', 
-            'request_mdn', 'request_dr');
+            'request_mdn', 'request_dr', 'fwduid');
 
         foreach ($compo_var_list as $var) {
             if ( isset($session_expired_post[$var]) && !isset($$var) ) {
 
         foreach ($compo_var_list as $var) {
             if ( isset($session_expired_post[$var]) && !isset($$var) ) {
@@ -411,6 +412,11 @@ if (empty($mailbox)) {
 }
 
 if ($draft) {
 }
 
 if ($draft) {
+
+    // validate security token
+    //
+    sm_validate_security_token($submitted_token, 3600, TRUE);
+
     /*
      * Set $default_charset to correspond with the user's selection
      * of language interface.
     /*
      * Set $default_charset to correspond with the user's selection
      * of language interface.
@@ -465,11 +471,17 @@ if ($draft) {
 }
 
 if ($send) {
 }
 
 if ($send) {
+
+    // validate security token
+    //
+    sm_validate_security_token($submitted_token, 3600, TRUE);
+
     if (isset($_FILES['attachfile']) &&
             $_FILES['attachfile']['tmp_name'] &&
             $_FILES['attachfile']['tmp_name'] != 'none') {
         $AttachFailure = saveAttachedFiles($session);
     }
     if (isset($_FILES['attachfile']) &&
             $_FILES['attachfile']['tmp_name'] &&
             $_FILES['attachfile']['tmp_name'] != 'none') {
         $AttachFailure = saveAttachedFiles($session);
     }
+    
     if (checkInput(false) && !isset($AttachFailure)) {
         if ($mailbox == "All Folders") {
             /* We entered compose via the search results page */
     if (checkInput(false) && !isset($AttachFailure)) {
         if ($mailbox == "All Folders") {
             /* We entered compose via the search results page */
@@ -586,6 +598,11 @@ if ($send) {
         /* sqimap_logout($imapConnection); */
     }
 } elseif (isset($html_addr_search_done)) {
         /* sqimap_logout($imapConnection); */
     }
 } elseif (isset($html_addr_search_done)) {
+
+    // validate security token
+    //
+    sm_validate_security_token($submitted_token, 3600, TRUE);
+
     if ($compose_new_win == '1') {
         compose_Header($color, $mailbox);
     }
     if ($compose_new_win == '1') {
         compose_Header($color, $mailbox);
     }
@@ -630,6 +647,11 @@ if ($send) {
      */
     include_once('./addrbook_search_html.php');
 } elseif (isset($attach)) {
      */
     include_once('./addrbook_search_html.php');
 } elseif (isset($attach)) {
+
+    // validate security token
+    //
+    sm_validate_security_token($submitted_token, 3600, TRUE);
+
     if ($compose_new_win == '1') {
         compose_Header($color, $mailbox);
     } else {
     if ($compose_new_win == '1') {
         compose_Header($color, $mailbox);
     } else {
@@ -641,6 +663,11 @@ if ($send) {
     showInputForm($session);
 }
 elseif (isset($sigappend)) {
     showInputForm($session);
 }
 elseif (isset($sigappend)) {
+
+    // validate security token
+    //
+    sm_validate_security_token($submitted_token, 3600, TRUE);
+
     $signature = $idents[$identity]['signature'];
 
     $body .= "\n\n".($prefix_sig==true? "-- \n":'').$signature;
     $signature = $idents[$identity]['signature'];
 
     $body .= "\n\n".($prefix_sig==true? "-- \n":'').$signature;
@@ -651,6 +678,11 @@ elseif (isset($sigappend)) {
     }
     showInputForm($session);
 } elseif (isset($do_delete)) {
     }
     showInputForm($session);
 } elseif (isset($do_delete)) {
+
+    // validate security token
+    //
+    sm_validate_security_token($submitted_token, 3600, TRUE);
+
     if ($compose_new_win == '1') {
         compose_Header($color, $mailbox);
     } else {
     if ($compose_new_win == '1') {
         compose_Header($color, $mailbox);
     } else {
@@ -702,6 +734,11 @@ elseif (isset($sigappend)) {
 
     $values = newMail($mailbox,$passed_id,$passed_ent_id, $action, $session);
 
 
     $values = newMail($mailbox,$passed_id,$passed_ent_id, $action, $session);
 
+    // forward as attachment - subject is in the message in session
+    //
+    if ($action == 'forward_as_attachment' && empty($values['subject']))
+        $subject = $composeMessage->rfc822_header->subject;
+
     /* in case the origin is not read_body.php */
     if (isset($send_to)) {
         $values['send_to'] = $send_to;
     /* in case the origin is not read_body.php */
     if (isset($send_to)) {
         $values['send_to'] = $send_to;
@@ -913,6 +950,12 @@ function newMail ($mailbox='', $passed_id='', $passed_ent_id='', $action='', $se
             case ('forward_as_attachment'):
                 $subject = getforwardSubject(decodeHeader($orig_header->subject,false,false,true));
                 $composeMessage = getMessage_RFC822_Attachment($message, $composeMessage, $passed_id, $passed_ent_id, $imapConnection);
             case ('forward_as_attachment'):
                 $subject = getforwardSubject(decodeHeader($orig_header->subject,false,false,true));
                 $composeMessage = getMessage_RFC822_Attachment($message, $composeMessage, $passed_id, $passed_ent_id, $imapConnection);
+                $subject = decodeHeader($orig_header->subject,false,false,true);
+                $subject = str_replace('"', "'", $subject);
+                $subject = trim($subject);
+                if (substr(strtolower($subject), 0, 4) != 'fwd:') {
+                    $subject = 'Fwd: ' . $subject;
+                }
                 $body = '';
                 break;
             case ('reply_all'):
                 $body = '';
                 break;
             case ('reply_all'):
@@ -921,20 +964,22 @@ function newMail ($mailbox='', $passed_id='', $passed_ent_id='', $action='', $se
                 } else {
                     $send_to_cc = replyAllString($orig_header);
                     $send_to_cc = decodeHeader($send_to_cc,false,false,true);
                 } else {
                     $send_to_cc = replyAllString($orig_header);
                     $send_to_cc = decodeHeader($send_to_cc,false,false,true);
+                    $send_to_cc = str_replace('""', '"', $send_to_cc);
                 }
             case ('reply'):
                 // skip this if send_to was already set right above here
                 if(!$send_to) {
                     $send_to = $orig_header->reply_to;
                     if (is_array($send_to) && count($send_to)) {
                 }
             case ('reply'):
                 // skip this if send_to was already set right above here
                 if(!$send_to) {
                     $send_to = $orig_header->reply_to;
                     if (is_array($send_to) && count($send_to)) {
-                        $send_to = $orig_header->getAddr_s('reply_to');
+                        $send_to = $orig_header->getAddr_s('reply_to', ',', FALSE, TRUE);
                     } else if (is_object($send_to)) { /* unneccesarry, just for failsafe purpose */
                     } else if (is_object($send_to)) { /* unneccesarry, just for failsafe purpose */
-                        $send_to = $orig_header->getAddr_s('reply_to');
+                        $send_to = $orig_header->getAddr_s('reply_to', ',', FALSE, TRUE);
                     } else {
                     } else {
-                        $send_to = $orig_header->getAddr_s('from');
+                        $send_to = $orig_header->getAddr_s('from', ',', FALSE, TRUE);
                     }
                 }
                 $send_to = decodeHeader($send_to,false,false,true);
                     }
                 }
                 $send_to = decodeHeader($send_to,false,false,true);
+                $send_to = str_replace('""', '"', $send_to);
                 $subject = decodeHeader($orig_header->subject,false,false,true);
                 $subject = str_replace('"', "'", $subject);
                 $subject = trim($subject);
                 $subject = decodeHeader($orig_header->subject,false,false,true);
                 $subject = str_replace('"', "'", $subject);
                 $subject = trim($subject);
@@ -947,7 +992,7 @@ function newMail ($mailbox='', $passed_id='', $passed_ent_id='', $action='', $se
                 $body = '';
                 $strip_sigs = getPref($data_dir, $username, 'strip_sigs');
                 foreach ($rewrap_body as $line) {
                 $body = '';
                 $strip_sigs = getPref($data_dir, $username, 'strip_sigs');
                 foreach ($rewrap_body as $line) {
-                    if ($strip_sigs && substr($line,0,3) == '-- ') {
+                    if ($strip_sigs && rtrim($line, "\r\n") == '-- ') {
                         break;
                     }
                     if (preg_match("/^(>+)/", $line, $matches)) {
                         break;
                     }
                     if (preg_match("/^(>+)/", $line, $matches)) {
@@ -1018,7 +1063,8 @@ function getAttachments($message, &$composeMessage, $passed_id, $entities, $imap
                     $filename = $message->getFilename();
                     break;
             }
                     $filename = $message->getFilename();
                     break;
             }
-            $filename = str_replace('&#32;', ' ', decodeHeader($filename));
+//FIXME: added three args to the following, so as to set the last one to TRUE, to mimick a fix in 1.4.21 (#2994865), but didn't test this (note that in 1.4.21, the 2nd and 3rd args are FALSE, but here in this code, they weren't being specified (thus defaulting to TRUE), so I don't know if that means this code is outdated and should have been changed to FALSE, FALSE or if this code is completely different and the addition of the TRUE for arg #4 is wrong
+            $filename = str_replace('&#32;', ' ', decodeHeader($filename, true, true, true));
             if (isset($languages[$squirrelmail_language]['XTRA_CODE']) &&
                     function_exists($languages[$squirrelmail_language]['XTRA_CODE'] . '_encode')) {
                 $filename =  call_user_func($languages[$squirrelmail_language]['XTRA_CODE'] . '_encode', $filename);
             if (isset($languages[$squirrelmail_language]['XTRA_CODE']) &&
                     function_exists($languages[$squirrelmail_language]['XTRA_CODE'] . '_encode')) {
                 $filename =  call_user_func($languages[$squirrelmail_language]['XTRA_CODE'] . '_encode', $filename);
@@ -1080,7 +1126,7 @@ function showInputForm ($session, $values=false) {
         $body, $startMessage, $action, $attachments,
         $use_signature, $signature, $prefix_sig, $session_expired,
         $editor_size, $editor_height, $subject, $newmail,
         $body, $startMessage, $action, $attachments,
         $use_signature, $signature, $prefix_sig, $session_expired,
         $editor_size, $editor_height, $subject, $newmail,
-        $use_javascript_addr_book, $passed_id, $mailbox,
+        $use_javascript_addr_book, $passed_id, $mailbox, $fwduid,
         $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,
         $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,
@@ -1139,28 +1185,40 @@ function showInputForm ($session, $values=false) {
     // to do; SquirrelMail itself will add the final "return true".
     // Onsubmit text is enclosed inside of double quotes, so plugins
     // need to quote accordingly.
     // to do; SquirrelMail itself will add the final "return true".
     // Onsubmit text is enclosed inside of double quotes, so plugins
     // need to quote accordingly.
+    //
+    // Also, plugin authors should try to retain compatibility with
+    // the Compose Extras plugin by resetting its compose submit
+    // counter when preventing form submit.  Use this code: 
+    // if (your-code-here) { submit_count = 0; return false; }
+    //
     if (checkForJavascript()) {
     if (checkForJavascript()) {
-        $onsubmit_text = ' onsubmit="';
         if (empty($compose_onsubmit))
             $compose_onsubmit = array();
         else if (!is_array($compose_onsubmit))
             $compose_onsubmit = array($compose_onsubmit);
 
         if (empty($compose_onsubmit))
             $compose_onsubmit = array();
         else if (!is_array($compose_onsubmit))
             $compose_onsubmit = array($compose_onsubmit);
 
+        $onsubmit_text = '';
         foreach ($compose_onsubmit as $text) {
             $text = trim($text);
         foreach ($compose_onsubmit as $text) {
             $text = trim($text);
-            if (substr($text, -1) != ';' && substr($text, -1) != '}')
-                $text .= '; ';
-            $onsubmit_text .= $text;
+            if (!empty($text)) {
+                if (substr($text, -1) != ';' && substr($text, -1) != '}')
+                    $text .= '; ';
+                $onsubmit_text .= $text;
+            }
         }
 
         }
 
+        if (!empty($onsubmit_text))
 //FIXME: DON'T ECHO HTML FROM CORE!
 //FIXME: DON'T ECHO HTML FROM CORE!
-        echo $onsubmit_text . ' return true;"';
+            echo ' onsubmit="' . $onsubmit_text . ' return true;"';
     }
 
 
 //FIXME: NO HTML IN CORE!
     echo ">\n";
 
     }
 
 
 //FIXME: NO HTML IN CORE!
     echo ">\n";
 
+//FIXME: DON'T ECHO HTML FROM CORE!
+    echo addHidden('smtoken', sm_generate_security_token());
+
 //FIXME: DON'T ECHO HTML FROM CORE!
     echo addHidden('startMessage', $startMessage);
 
 //FIXME: DON'T ECHO HTML FROM CORE!
     echo addHidden('startMessage', $startMessage);
 
@@ -1182,6 +1240,11 @@ function showInputForm ($session, $values=false) {
         echo addHidden('passed_id', $passed_id);
     }
 
         echo addHidden('passed_id', $passed_id);
     }
 
+    if (isset($fwduid)) {
+//FIXME: DON'T ECHO HTML FROM CORE!
+        echo addHidden('fwduid', $fwduid);
+    }
+
     if ($saved_draft == 'yes') {
         $oTemplate->assign('note', _("Your draft has been saved."));
         $oTemplate->display('note.tpl');
     if ($saved_draft == 'yes') {
         $oTemplate->assign('note', _("Your draft has been saved."));
         $oTemplate->display('note.tpl');
@@ -1478,7 +1541,21 @@ function saveAttachedFiles($session) {
     $composeMessage->initAttachment($type, $name, $localfilename);
 }
 
     $composeMessage->initAttachment($type, $name, $localfilename);
 }
 
-/* parse values like 8M and 2k into bytes */
+/**
+  * Parse strings such as "8M" and "2k" into their corresponding size in bytes
+  *
+  * NOTE: This function only recognizes the suffixes "K", "M" and "G"
+  *       and will probably break very easily if the given size is in
+  *       some completely different format.
+  *
+  * @param string $ini_size The input string to be converted
+  *
+  * @return mixed Boolean FALSE if something went wrong (the value passed in
+  *               was empty?, the suffix was not recognized?), otherwise, the
+  *               converted size in bytes (just the number (as an integer),
+  *               no unit identifier included)
+  *
+  */
 function getByteSize($ini_size) {
 
     if(!$ini_size) {
 function getByteSize($ini_size) {
 
     if(!$ini_size) {
@@ -1500,6 +1577,8 @@ function getByteSize($ini_size) {
             case 'K':
                 $bytesize = 1024;
                 break;
             case 'K':
                 $bytesize = 1024;
                 break;
+             default:
+                return FALSE;
         }
 
         return ($bytesize * (int)substr($ini_size, 0, -1));
         }
 
         return ($bytesize * (int)substr($ini_size, 0, -1));
@@ -1554,6 +1633,8 @@ function deliverMessage(&$composeMessage, $draft=false) {
 
     $reply_to = '';
     $reply_to  = $idents[$identity]['reply_to'];
 
     $reply_to = '';
     $reply_to  = $idents[$identity]['reply_to'];
+    if ($reply_to && strpos($reply_to, '@') === FALSE)
+        $reply_to .= '@' . $domain;
     
     $from_addr = build_from_header($identity);
     $rfc822_header->from = $rfc822_header->parseAddress($from_addr,true);
     
     $from_addr = build_from_header($identity);
     $rfc822_header->from = $rfc822_header->parseAddress($from_addr,true);
@@ -1687,7 +1768,7 @@ function deliverMessage(&$composeMessage, $draft=false) {
 
         // mark as replied or forwarded if applicable
         //
 
         // mark as replied or forwarded if applicable
         //
-        global $what, $iAccount, $startMessage, $passed_id, $mailbox;
+        global $what, $iAccount, $startMessage, $passed_id, $fwduid, $mailbox;
 
         if ($action=='reply' || $action=='reply_all' || $action=='forward' || $action=='forward_as_attachment') {
             require(SM_PATH . 'functions/mailbox_display.php');
 
         if ($action=='reply' || $action=='reply_all' || $action=='forward' || $action=='forward_as_attachment') {
             require(SM_PATH . 'functions/mailbox_display.php');
@@ -1715,10 +1796,22 @@ function deliverMessage(&$composeMessage, $draft=false) {
                 if (in_array('$forwarded',$aMailbox['PERMANENTFLAGS'], true) ||
                     in_array('\\*',$aMailbox['PERMANENTFLAGS'])) {
 
                 if (in_array('$forwarded',$aMailbox['PERMANENTFLAGS'], true) ||
                     in_array('\\*',$aMailbox['PERMANENTFLAGS'])) {
 
-                    $aUpdatedMsgs = sqimap_toggle_flag($imap_stream, array($passed_id), '$Forwarded', true, false);
-                    if (isset($aUpdatedMsgs[$passed_id]['FLAGS'])) {
-                        if (isset($aMailbox['MSG_HEADERS'][$passed_id])) {
-                            $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS'] = $aMsg['FLAGS'];
+                    // when forwarding as an attachment from the message
+                    // list, passed_id is not used, need to get UID(s)
+                    // from the query string
+                    //
+                    if (empty($passed_id) && !empty($fwduid))
+                        $ids = explode('_', $fwduid);
+                    else
+                        $ids = array($passed_id);
+
+                    $aUpdatedMsgs = sqimap_toggle_flag($imap_stream, $ids, '$Forwarded', true, false);
+
+                    foreach ($ids as $id) {
+                        if (isset($aUpdatedMsgs[$id]['FLAGS'])) {
+                            if (isset($aMailbox['MSG_HEADERS'][$id])) {
+                                $aMailbox['MSG_HEADERS'][$id]['FLAGS'] = $aMsg['FLAGS'];
+                            }
                         }
                     }
                 }
                         }
                     }
                 }