No longer store all message composition sessions in the PHP session, since it was...
[squirrelmail.git] / src / compose.php
index a81e2e2a7f99cfa6e5fb0d0e81afd5c3db3fb713..cbde37838c6e033a72a64846f3d206f062ac25b3 100644 (file)
@@ -16,6 +16,9 @@
  * @package squirrelmail
  */
 
+/** This is the compose page */
+define('PAGE_NAME', 'compose');
+
 /**
  * Include the SquirrelMail initialization file.
  */
@@ -44,9 +47,14 @@ require_once(SM_PATH . 'functions/identity.php');
 /** SESSION VARS */
 sqgetGlobalVar('delimiter', $delimiter,     SQ_SESSION);
 
+sqgetGlobalVar('delayed_errors',  $delayed_errors,  SQ_SESSION);
 sqgetGlobalVar('composesession',    $composesession,    SQ_SESSION);
 sqgetGlobalVar('compose_messages',  $compose_messages,  SQ_SESSION);
-sqgetGlobalVar('delayed_errors',  $delayed_errors,  SQ_SESSION);
+
+// compose_messages only useful in SESSION when a forward-as-attachment
+// has been preconstructed for us and passed in via that mechanism; once
+// we have it, we can clear it from the SESSION
+sqsession_unregister('compose_messages');
 
 // Turn on delayed error handling in case we wind up redirecting below
 $oErrorHandler->setDelayedErrors(true);
@@ -103,7 +111,7 @@ sqgetGlobalVar('addr_search_cancel',    $html_addr_search_cancel,   SQ_POST);
 sqgetGlobalVar('send_to_search',        $send_to_search,            SQ_POST);
 sqgetGlobalVar('do_delete',             $do_delete,                 SQ_POST);
 sqgetGlobalVar('delete',                $delete,                    SQ_POST);
-sqgetGlobalVar('restoremessages',       $restoremessages,           SQ_POST);
+sqgetGlobalVar('attachments',           $attachments,               SQ_POST);
 if ( sqgetGlobalVar('return', $temp, SQ_POST) ) {
     $html_addr_search_done = 'Use Addresses';
 }
@@ -314,6 +322,7 @@ function getforwardHeader($orig_header) {
  * If the session is expired during a post this restores the compose session
  * vars.
  */
+$session_expired = false;
 if (sqsession_is_registered('session_expired_post')) {
     sqgetGlobalVar('session_expired_post', $session_expired_post, SQ_SESSION);
     /*
@@ -326,11 +335,12 @@ if (sqsession_is_registered('session_expired_post')) {
         session_write_close();
     } else {
         // these are the vars that we can set from the expired composed session
-        $compo_var_list = array ( 'send_to', 'send_to_cc','body','startMessage',
-            'passed_body','use_signature','signature','attachments','subject','newmail',
-            'send_to_bcc', 'passed_id', 'mailbox', 'from_htmladdr_search', 'identity',
-            'draft_id', 'delete_draft', 'mailprio', 'edit_as_new', 'compose_messsages',
-            'composesession', 'request_mdn', 'request_dr');
+        $compo_var_list = array ('send_to', 'send_to_cc', 'body',
+            'startMessage', 'passed_body', 'use_signature', 'signature',
+            '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');
 
         foreach ($compo_var_list as $var) {
             if ( isset($session_expired_post[$var]) && !isset($$var) ) {
@@ -338,9 +348,11 @@ if (sqsession_is_registered('session_expired_post')) {
             }
         }
 
-        $compose_messages = unserialize($restoremessages);
-        sqsession_register($compose_messages,'compose_messages');
+        if (!empty($attachments))
+            $attachments = unserialize($attachments);
+
         sqsession_register($composesession,'composesession');
+
         if (isset($send)) {
             unset($send);
         }
@@ -366,6 +378,7 @@ if (sqsession_is_registered('session_expired_post')) {
     showInputForm($session, false);
     exit();
 }
+
 if (!isset($composesession)) {
     $composesession = 0;
     sqsession_register(0,'composesession');
@@ -389,12 +402,19 @@ if (!isset($compose_messages[$session]) || ($compose_messages[$session] == NULL)
     $composeMessage->rfc822_header = $rfc822_header;
     $composeMessage->reply_rfc822_header = '';
     $compose_messages[$session] = $composeMessage;
-
-    sqsession_register($compose_messages,'compose_messages');
 } else {
     $composeMessage=$compose_messages[$session];
 }
 
+// re-add attachments that were already in this message
+// FIXME: note that technically this is very bad form -
+// should never directly manipulate an object like this
+if (!empty($attachments)) {
+    $attachments = unserialize($attachments);
+    if (!empty($attachments) && is_array($attachments))
+        $composeMessage->entities = $attachments;
+}
+
 if (empty($mailbox)) {
     $mailbox = 'INBOX';
 }
@@ -405,13 +425,11 @@ if ($draft) {
      * of language interface.
      */
     set_my_charset();
-    $composeMessage=$compose_messages[$session];
+    $composeMessage = $compose_messages[$session];
     if (! deliverMessage($composeMessage, true)) {
         showInputForm($session);
         exit();
     } else {
-        unset($compose_messages[$session]);
-        sqsession_register($compose_messages,'compose_messages');
         $draft_message = _("Draft Email Saved");
         /* If this is a resumed draft, then delete the original */
         if(isset($delete_draft)) {
@@ -434,6 +452,7 @@ if ($draft) {
             if ( !isset($pageheader_sent) || !$pageheader_sent ) {
                 Header("Location: $location/compose.php?saved_draft=yes&session=$composesession");
             } else {
+//FIXME: DON'T ECHO HTML FROM CORE!
                 echo '   <br><br><div style="text-align: center;"><a href="' . $location
                     . '/compose.php?saved_sent=yes&amp;session=' . $composesession . '">'
                     . _("Return") . '</a></div>';
@@ -444,6 +463,7 @@ if ($draft) {
                 Header("Location: $location/right_main.php?mailbox=" . urlencode($draft_folder) .
                    "&startMessage=1&note=".urlencode($draft_message));
             } else {
+//FIXME: DON'T ECHO HTML FROM CORE!
                 echo '   <br><br><div style="text-align: center;"><a href="' . $location
                     . '/right_main.php?mailbox=' . urlencode($draft_folder)
                     . '&amp;startMessage=1&amp;note=' . urlencode($draft_message) .'">'
@@ -518,8 +538,6 @@ if ($send) {
             showInputForm($session);
             exit();
         }
-        unset($compose_messages[$session]);
-        sqsession_register($compose_messages,'compose_messages');
 
         /* if it is resumed draft, delete draft message */
         if ( isset($delete_draft)) {
@@ -544,6 +562,7 @@ if ($send) {
             if ( !isset($pageheader_sent) || !$pageheader_sent ) {
                 Header("Location: $location/compose.php?mail_sent=$mail_sent");
             } else {
+//FIXME: DON'T ECHO HTML FROM CORE!
                 echo '   <br><br><div style="text-align: center;"><a href="' . $location
                     . '/compose.php?mail_sent=$mail_sent">'
                     . _("Return") . '</a></div>';
@@ -554,6 +573,7 @@ if ($send) {
                 Header("Location: $location/right_main.php?mailbox=$urlMailbox".
                     "&startMessage=$startMessage&mail_sent=$mail_sent");
             } else {
+//FIXME: DON'T ECHO HTML FROM CORE!
                 echo '   <br><br><div style="text-align: center;"><a href="' . $location
                     . "/right_main.php?mailbox=$urlMailbox"
                     . "&amp;startMessage=$startMessage&amp;mail_sent=$mail_sent\">"
@@ -662,7 +682,6 @@ elseif (isset($sigappend)) {
         }
         $composeMessage->entities = $new_entities;
         $compose_messages[$session] = $composeMessage;
-        sqsession_register($compose_messages, 'compose_messages');
     }
     showInputForm($session);
 } else {
@@ -985,7 +1004,7 @@ function newMail ($mailbox='', $passed_id='', $passed_ent_id='', $action='', $se
  * @return object
  */
 function getAttachments($message, &$composeMessage, $passed_id, $entities, $imapConnection) {
-    global $squirrelmail_language, $languages;
+    global $squirrelmail_language, $languages, $username, $attachment_dir;
 
     if (!count($message->entities) ||
             ($message->type0 == 'message' && $message->type1 == 'rfc822')) {
@@ -1014,6 +1033,8 @@ function getAttachments($message, &$composeMessage, $passed_id, $entities, $imap
                     function_exists($languages[$squirrelmail_language]['XTRA_CODE'] . '_encode')) {
                 $filename =  call_user_func($languages[$squirrelmail_language]['XTRA_CODE'] . '_encode', $filename);
             }
+
+            $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
             $localfilename = sq_get_attach_tempfile();
             $message->att_local_name = $localfilename;
 
@@ -1021,7 +1042,7 @@ function getAttachments($message, &$composeMessage, $passed_id, $entities, $imap
                     $localfilename);
 
             /* Write Attachment to file */
-            $fp = fopen ($localfilename, 'wb');
+            $fp = fopen ($hashed_attachment_dir . '/' . $localfilename, 'wb');
             mime_print_body_lines ($imapConnection, $passed_id, $message->entity_id, $message->header->encoding, $fp);
             fclose ($fp);
         }
@@ -1052,8 +1073,10 @@ function getMessage_RFC822_Attachment($message, $composeMessage, $passed_id,
         array_pop($body_a);
         $body = implode('', $body_a) . "\r\n";
 
+        global $username, $attachment_dir;
+        $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
         $localfilename = sq_get_attach_tempfile();
-        $fp = fopen($localfilename, 'wb');
+        $fp = fopen($hashed_attachment_dir . '/' . $localfilename, 'wb');
         fwrite ($fp, $body);
         fclose($fp);
         $composeMessage->initAttachment('message/rfc822',$subject.'.msg',
@@ -1064,7 +1087,7 @@ function getMessage_RFC822_Attachment($message, $composeMessage, $passed_id,
 
 function showInputForm ($session, $values=false) {
     global $send_to, $send_to_cc, $send_to_bcc,
-        $body, $startMessage, $action,
+        $body, $startMessage, $action, $attachments,
         $use_signature, $signature, $prefix_sig,
         $editor_size, $editor_height, $subject, $newmail,
         $use_javascript_addr_book, $passed_id, $mailbox,
@@ -1099,6 +1122,7 @@ function showInputForm ($session, $values=false) {
     }
 
     if ($use_javascript_addr_book) {
+//FIXME: NO HTML IN CORE!
         echo "\n". '<script type="text/javascript">'."\n<!--\n" .
             'function open_abook() { ' . "\n" .
             '  var nwin = window.open("addrbook_popup.php","abookpopup",' .
@@ -1109,6 +1133,7 @@ function showInputForm ($session, $values=false) {
             "// -->\n</script>\n\n";
     }
 
+//FIXME: NO HTML IN CORE!
     echo "\n" . '<form name="compose" action="compose.php" method="post" ' .
         'enctype="multipart/form-data"';
 
@@ -1139,25 +1164,32 @@ function showInputForm ($session, $values=false) {
             $onsubmit_text .= $text;
         }
 
+//FIXME: DON'T ECHO HTML FROM CORE!
         echo $onsubmit_text . ' return true;"';
     }
 
 
+//FIXME: NO HTML IN CORE!
     echo ">\n";
 
+//FIXME: DON'T ECHO HTML FROM CORE!
     echo addHidden('startMessage', $startMessage);
 
     if ($action == 'draft') {
+//FIXME: DON'T ECHO HTML FROM CORE!
         echo addHidden('delete_draft', $passed_id);
     }
     if (isset($delete_draft)) {
+//FIXME: DON'T ECHO HTML FROM CORE!
         echo addHidden('delete_draft', $delete_draft);
     }
     if (isset($session)) {
+//FIXME: DON'T ECHO HTML FROM CORE!
         echo addHidden('session', $session);
     }
 
     if (isset($passed_id)) {
+//FIXME: DON'T ECHO HTML FROM CORE!
         echo addHidden('passed_id', $passed_id);
     }
 
@@ -1174,6 +1206,7 @@ function showInputForm ($session, $values=false) {
     }
 
     if ($location_of_buttons == 'top') {
+//FIXME: DON'T ECHO HTML FROM CORE!
         showComposeButtonRow();
     }
 
@@ -1197,6 +1230,7 @@ function showInputForm ($session, $values=false) {
     $oTemplate->display('compose_header.tpl');
 
     if ($location_of_buttons == 'between') {
+//FIXME: DON'T ECHO HTML FROM CORE!
         showComposeButtonRow();
     }
 
@@ -1239,9 +1273,16 @@ function showInputForm ($session, $values=false) {
     $oTemplate->display ('compose_body.tpl');
 
     if ($location_of_buttons == 'bottom') {
+//FIXME: DON'T ECHO HTML FROM CORE!
         showComposeButtonRow();
     }
 
+    // composeMessage can be empty when coming from a restored session
+    if (is_object($composeMessage) && $composeMessage->entities)
+        $attach_array = $composeMessage->entities;
+    if ($session_expired && !empty($attachments) && is_array($attachments))
+        $attach_array = $attachments;
+
     /* This code is for attachments */
     if ((bool) ini_get('file_uploads')) {
 
@@ -1261,9 +1302,10 @@ function showInputForm ($session, $values=false) {
         }
 
         $attach = array();
-        // composeMessage can be empty when coming from a restored session
-        if (is_object($composeMessage) && $composeMessage->entities) {
-            foreach ($composeMessage->entities as $key => $attachment) {
+        global $username, $attachment_dir;
+        $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
+        if (!empty($attach_array)) {
+            foreach ($attach_array as $key => $attachment) {
                 $attached_file = $attachment->att_local_name;
                 if ($attachment->att_local_name || $attachment->body_part) {
                     $attached_filename = decodeHeader($attachment->mime_header->getParameter('name'));
@@ -1274,7 +1316,7 @@ function showInputForm ($session, $values=false) {
                     $a['Key'] = $key;
                     $a['FileName'] = $attached_filename;
                     $a['ContentType'] = $type;
-                    $a['Size'] = filesize($attached_file);
+                    $a['Size'] = filesize($hashed_attachment_dir . '/' . $attached_file);
                     $attach[$key] = $a;
                 }
             }
@@ -1292,15 +1334,12 @@ function showInputForm ($session, $values=false) {
     echo addHidden('username', $username).
          addHidden('smaction', $action).
          addHidden('mailbox', $mailbox);
-    /*
-       store the complete ComposeMessages array in a hidden input value
-       so we can restore them in case of a session timeout.
-     */
     sqgetGlobalVar('QUERY_STRING', $queryString, SQ_SERVER);
 //FIXME: no direct echoing to browser, no HTML output in core!
-    echo addHidden('restoremessages', urlencode(serialize($compose_messages))).
-        addHidden('composesession', $composesession).
+    echo addHidden('composesession', $composesession).
         addHidden('querystring', $queryString).
+        (!empty($attach_array) ?
+         addHidden('attachments', urlencode(serialize($attach_array))) : '').
         "</form>\n";
     if (!(bool) ini_get('file_uploads')) {
         /* File uploads are off, so we didn't show that part of the form.
@@ -1384,19 +1423,21 @@ function checkInput ($show) {
 
 /* True if FAILURE */
 function saveAttachedFiles($session) {
-    global $compose_messages;
+    global $compose_messages, $username, $attachment_dir;
 
     /* get out of here if no file was attached at all */
     if (! is_uploaded_file($_FILES['attachfile']['tmp_name']) ) {
         return true;
     }
 
+    $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
     $localfilename = sq_get_attach_tempfile();
+    $fullpath = $hashed_attachment_dir . '/' . $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'],$localfilename)) {
-        if (!@rename($_FILES['attachfile']['tmp_name'], $localfilename)) {
+    if (!@move_uploaded_file($_FILES['attachfile']['tmp_name'],$fullpath)) {
+        if (!@rename($_FILES['attachfile']['tmp_name'], $fullpath)) {
             return true;
         }
     }
@@ -1405,7 +1446,6 @@ function saveAttachedFiles($session) {
     $name = $_FILES['attachfile']['name'];
     $message->initAttachment($type, $name, $localfilename);
     $compose_messages[$session] = $message;
-    sqsession_register($compose_messages , 'compose_messages');
 }
 
 /* parse values like 8M and 2k into bytes */