Make drafts send with in-reply-to headers (fix regression from long ago)
[squirrelmail.git] / src / compose.php
CommitLineData
59177427 1<?php
35586184 2/**
3 * compose.php
4 *
35586184 5 * This code sends a mail.
6 *
7 * There are 4 modes of operation:
8 * - Start new mail
9 * - Add an attachment
10 * - Send mail
11 * - Save As Draft
12 *
22387c8d 13 * @copyright 1999-2017 The SquirrelMail Project Team
4b4abf93 14 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
30967a1e 15 * @version $Id$
8f6f9ba5 16 * @package squirrelmail
35586184 17 */
f7fb20fe 18
ebd2391c 19/** This is the compose page */
20define('PAGE_NAME', 'compose');
21
30967a1e 22/**
202bcbcc 23 * Include the SquirrelMail initialization file.
30967a1e 24 */
202bcbcc 25require('../include/init.php');
86725763 26
c90271cb 27/* If email_address not set and admin wants us to ask user for it,
28 * redirect to options page. */
29if ( $ask_user_info && getPref($data_dir, $username,'email_address') == "" ) {
30 header("Location: " . get_location() . "/options.php?optpage=personal");
31 exit;
32}
33
86725763 34/* SquirrelMail required files. */
202bcbcc 35require_once(SM_PATH . 'functions/imap_general.php');
36require_once(SM_PATH . 'functions/imap_messages.php');
86725763 37require_once(SM_PATH . 'functions/date.php');
38require_once(SM_PATH . 'functions/mime.php');
628bce99 39require_once(SM_PATH . 'functions/compose.php');
86725763 40require_once(SM_PATH . 'class/deliver/Deliver.class.php');
24192f77 41require_once(SM_PATH . 'functions/addressbook.php');
df96b37a 42require_once(SM_PATH . 'functions/forms.php');
a2b193bc 43require_once(SM_PATH . 'functions/identity.php');
a9805897 44global $imap_stream_options; // in case not defined in config
91f2085b 45
0b97a708 46/* --------------------- Get globals ------------------------------------- */
0b97a708 47
953fa718 48/** SESSION VARS */
953fa718 49sqgetGlobalVar('delimiter', $delimiter, SQ_SESSION);
50
f8eb968d 51sqgetGlobalVar('delayed_errors', $delayed_errors, SQ_SESSION);
953fa718 52sqgetGlobalVar('composesession', $composesession, SQ_SESSION);
53sqgetGlobalVar('compose_messages', $compose_messages, SQ_SESSION);
f8eb968d 54
55// compose_messages only useful in SESSION when a forward-as-attachment
56// has been preconstructed for us and passed in via that mechanism; once
57// we have it, we can clear it from the SESSION
58sqsession_unregister('compose_messages');
762853f4 59
60// Turn on delayed error handling in case we wind up redirecting below
61$oErrorHandler->setDelayedErrors(true);
953fa718 62
63/** SESSION/POST/GET VARS */
61bd57f5 64sqgetGlobalVar('send_button_count', $send_button_count, SQ_POST, 1, SQ_TYPE_INT);
65for ($i = 1; $i <= $send_button_count; $i++)
66 if (sqgetGlobalVar('send' . $i, $send, SQ_POST)) break;
567dc524 67// Send can only be achieved by setting $_POST var. If Send = true then
68// retrieve other form fields from $_POST
69if (isset($send) && $send) {
70 $SQ_GLOBAL = SQ_POST;
71} else {
72 $SQ_GLOBAL = SQ_FORM;
73}
74sqgetGlobalVar('session',$session, $SQ_GLOBAL);
75sqgetGlobalVar('mailbox',$mailbox, $SQ_GLOBAL);
79cecc00 76sqgetGlobalVar('identity',$orig_identity, $SQ_GLOBAL);
567dc524 77if(!sqgetGlobalVar('identity',$identity, $SQ_GLOBAL)) {
1e2a6ff6 78 $identity=0;
79}
567dc524 80sqgetGlobalVar('send_to',$send_to, $SQ_GLOBAL);
81sqgetGlobalVar('send_to_cc',$send_to_cc, $SQ_GLOBAL);
82sqgetGlobalVar('send_to_bcc',$send_to_bcc, $SQ_GLOBAL);
83sqgetGlobalVar('subject',$subject, $SQ_GLOBAL);
84sqgetGlobalVar('body',$body, $SQ_GLOBAL);
85sqgetGlobalVar('mailprio',$mailprio, $SQ_GLOBAL);
86sqgetGlobalVar('request_mdn',$request_mdn, $SQ_GLOBAL);
87sqgetGlobalVar('request_dr',$request_dr, $SQ_GLOBAL);
88sqgetGlobalVar('html_addr_search',$html_addr_search, $SQ_GLOBAL);
89sqgetGlobalVar('mail_sent',$mail_sent, $SQ_GLOBAL);
51bbe8fa 90sqgetGlobalVar('passed_id',$passed_id, $SQ_GLOBAL, NULL, SQ_TYPE_BIGINT);
567dc524 91sqgetGlobalVar('passed_ent_id',$passed_ent_id, $SQ_GLOBAL);
e506b6e5 92sqgetGlobalVar('fwduid',$fwduid, $SQ_GLOBAL, '');
12a0ed01 93
567dc524 94sqgetGlobalVar('attach',$attach, SQ_POST);
95sqgetGlobalVar('draft',$draft, SQ_POST);
96sqgetGlobalVar('draft_id',$draft_id, $SQ_GLOBAL);
97sqgetGlobalVar('ent_num',$ent_num, $SQ_GLOBAL);
98sqgetGlobalVar('saved_draft',$saved_draft, SQ_FORM);
7e2ff844 99
100if ( sqgetGlobalVar('delete_draft',$delete_draft) ) {
101 $delete_draft = (int)$delete_draft;
102}
103
a6d3eff6 104if ( sqgetGlobalVar('startMessage',$startMessage) ) {
105 $startMessage = (int)$startMessage;
106} else {
107 $startMessage = 1;
108}
953fa718 109
8780308f 110
953fa718 111/** POST VARS */
167c6996 112sqgetGlobalVar('sigappend', $sigappend, SQ_POST);
113sqgetGlobalVar('from_htmladdr_search', $from_htmladdr_search, SQ_POST);
114sqgetGlobalVar('addr_search_done', $html_addr_search_done, SQ_POST);
115sqgetGlobalVar('addr_search_cancel', $html_addr_search_cancel, SQ_POST);
116sqgetGlobalVar('send_to_search', $send_to_search, SQ_POST);
117sqgetGlobalVar('do_delete', $do_delete, SQ_POST);
118sqgetGlobalVar('delete', $delete, SQ_POST);
f8eb968d 119sqgetGlobalVar('attachments', $attachments, SQ_POST);
953fa718 120if ( sqgetGlobalVar('return', $temp, SQ_POST) ) {
73ad81bf 121 $html_addr_search_done = 'Use Addresses';
953fa718 122}
123
124/** GET VARS */
8780308f 125if ( sqgetGlobalVar('account', $temp, SQ_GET) ) {
126 $iAccount = (int) $temp;
127} else {
128 $iAccount = 0;
129}
130
0b97a708 131
98a9cc03 132/** get smaction */
133if ( !sqgetGlobalVar('smaction',$action) )
134{
73ad81bf 135 if ( sqgetGlobalVar('smaction_reply',$tmp) ) $action = 'reply';
136 if ( sqgetGlobalVar('smaction_reply_all',$tmp) ) $action = 'reply_all';
137 if ( sqgetGlobalVar('smaction_forward',$tmp) ) $action = 'forward';
138 if ( sqgetGlobalVar('smaction_attache',$tmp) ) $action = 'forward_as_attachment';
139 if ( sqgetGlobalVar('smaction_draft',$tmp) ) $action = 'draft';
140 if ( sqgetGlobalVar('smaction_edit_new',$tmp) ) $action = 'edit_as_new';
98a9cc03 141}
142
199a9ab8 143sqgetGlobalVar('smtoken', $submitted_token, $SQ_GLOBAL, '');
144
7e2ff844 145/**
146 * Here we decode the data passed in from mailto.php.
147 */
148if ( sqgetGlobalVar('mailtodata', $mailtodata, SQ_GET) ) {
149 $trtable = array('to' => 'send_to',
150 'cc' => 'send_to_cc',
151 'bcc' => 'send_to_bcc',
152 'body' => 'body',
153 'subject' => 'subject');
154 $mtdata = unserialize($mailtodata);
1638beb6 155
7e2ff844 156 foreach ($trtable as $f => $t) {
157 if ( !empty($mtdata[$f]) ) {
158 $$t = $mtdata[$f];
159 }
160 }
161 unset($mailtodata,$mtdata, $trtable);
162}
163
39cf816f 164/* Location (For HTTP 1.1 header("Location: ...") redirects) */
3461167c 165$location = get_location();
1e2a6ff6 166/* Identities (fetch only once) */
167$idents = get_identities();
3461167c 168
09044055 169/* --------------------- Specific Functions ------------------------------ */
0b97a708 170
41b94d65 171function replyAllString($header) {
73ad81bf 172 global $include_self_reply_all, $idents;
173 $excl_ar = array();
174 /**
175 * 1) Remove the addresses we'll be sending the message 'to'
176 */
af084f6e 177 if (isset($header->reply_to)) {
178 $excl_ar = $header->getAddr_a('reply_to');
73ad81bf 179 }
180 /**
181 * 2) Remove our identities from the CC list (they still can be in the
182 * TO list) only if $include_self_reply_all is turned off
183 */
184 if (!$include_self_reply_all) {
185 foreach($idents as $id) {
186 $excl_ar[strtolower(trim($id['email_address']))] = '';
187 }
188 }
189
190 /**
191 * 3) get the addresses.
192 */
193 $url_replytoall_ar = $header->getAddr_a(array('to','cc'), $excl_ar);
194
195 /**
196 * 4) generate the string.
197 */
198 $url_replytoallcc = '';
199 foreach( $url_replytoall_ar as $email => $personal) {
200 if ($personal) {
a9b9e5d3 201 // always quote personal name (can't just quote it if
202 // it contains a comma separator, since it might still
203 // be encoded)
204 $url_replytoallcc .= ", \"$personal\" <$email>";
73ad81bf 205 } else {
206 $url_replytoallcc .= ', '. $email;
1e2a6ff6 207 }
73ad81bf 208 }
209 $url_replytoallcc = substr($url_replytoallcc,2);
210
211 return $url_replytoallcc;
09044055 212}
213
50706f77 214/**
215 * creates top line in reply citations
216 *
217 * Line style depends on user preferences.
218 * $orig_date argument is available only from 1.4.3 and 1.5.1 version.
219 * @param object $orig_from From: header object.
220 * @param integer $orig_date email's timestamp
221 * @return string reply citation
222 */
b0323712 223function getReplyCitation($orig_from, $orig_date) {
12a0ed01 224 global $reply_citation_style, $reply_citation_start, $reply_citation_end;
50706f77 225
05f7db7a 226 if (!is_object($orig_from)) {
d1205176 227 $sOrig_from = '';
05f7db7a 228 } else {
d1205176 229 $sOrig_from = decodeHeader($orig_from->getAddress(false),false,false,true);
05f7db7a 230 }
91c27aee 231
12a0ed01 232 /* First, return an empty string when no citation style selected. */
233 if (($reply_citation_style == '') || ($reply_citation_style == 'none')) {
234 return '';
235 }
236
237 /* Make sure our final value isn't an empty string. */
d1205176 238 if ($sOrig_from == '') {
12a0ed01 239 return '';
240 }
241
242 /* Otherwise, try to select the desired citation style. */
243 switch ($reply_citation_style) {
50706f77 244 case 'author_said':
b986936a 245 // i18n: %s is for author's name
d1205176 246 $full_reply_citation = sprintf(_("%s wrote:"),$sOrig_from);
50706f77 247 break;
248 case 'quote_who':
a42c236f 249 $start = '<quote who="';
50706f77 250 $end = '">';
d1205176 251 $full_reply_citation = $start . $sOrig_from . $end;
50706f77 252 break;
253 case 'date_time_author':
b986936a 254 // i18n:
255 // The first %s is for date string, the second %s is for author's name.
256 // The date uses formating from "D, F j, Y g:i a" and "D, F j, Y H:i"
257 // translations.
258 // Example string:
259 // "On Sat, December 24, 2004 23:59, Santa wrote:"
260 // If you have to put author's name in front of date string, check comments about
261 // argument swapping at http://php.net/sprintf
d1205176 262 $full_reply_citation = sprintf(_("On %s, %s wrote:"), getLongDateString($orig_date), $sOrig_from);
50706f77 263 break;
264 case 'user-defined':
265 $start = $reply_citation_start .
266 ($reply_citation_start == '' ? '' : ' ');
267 $end = $reply_citation_end;
d1205176 268 $full_reply_citation = $start . $sOrig_from . $end;
50706f77 269 break;
270 default:
271 return '';
272 }
273
274 /* Add line feed and return the citation string. */
275 return ($full_reply_citation . "\n");
12a0ed01 276}
277
50706f77 278/**
279 * Creates header fields in forwarded email body
280 *
91c27aee 281 * $default_charset global must be set correctly before you call this function.
50706f77 282 * @param object $orig_header
91c27aee 283 * @return $string
50706f77 284 */
41b94d65 285function getforwardHeader($orig_header) {
50706f77 286 global $editor_size, $default_charset;
287
288 // using own strlen function in order to detect correct string length
289 $display = array( _("Subject") => sq_strlen(_("Subject"),$default_charset),
290 _("From") => sq_strlen(_("From"),$default_charset),
291 _("Date") => sq_strlen(_("Date"),$default_charset),
292 _("To") => sq_strlen(_("To"),$default_charset),
293 _("Cc") => sq_strlen(_("Cc"),$default_charset) );
73ad81bf 294 $maxsize = max($display);
295 $indent = str_pad('',$maxsize+2);
296 foreach($display as $key => $val) {
297 $display[$key] = $key .': '. str_pad('', $maxsize - $val);
298 }
299 $from = decodeHeader($orig_header->getAddr_s('from',"\n$indent"),false,false,true);
300 $from = str_replace('&nbsp;',' ',$from);
301 $to = decodeHeader($orig_header->getAddr_s('to',"\n$indent"),false,false,true);
302 $to = str_replace('&nbsp;',' ',$to);
303 $subject = decodeHeader($orig_header->subject,false,false,true);
304 $subject = str_replace('&nbsp;',' ',$subject);
50706f77 305
306 // using own str_pad function in order to create correct string pad
307 $bodyTop = sq_str_pad(' '._("Original Message").' ',$editor_size -2,'-',STR_PAD_BOTH,$default_charset) .
73ad81bf 308 "\n". $display[_("Subject")] . $subject . "\n" .
309 $display[_("From")] . $from . "\n" .
3aaa3214 310 $display[_("Date")] . getLongDateString( $orig_header->date, $orig_header->date_unparsed ). "\n" .
73ad81bf 311 $display[_("To")] . $to . "\n";
312 if ($orig_header->cc != array() && $orig_header->cc !='') {
313 $cc = decodeHeader($orig_header->getAddr_s('cc',"\n$indent"),false,false,true);
314 $cc = str_replace('&nbsp;',' ',$cc);
315 $bodyTop .= $display[_("Cc")] .$cc . "\n";
316 }
317 $bodyTop .= str_pad('', $editor_size -2 , '-') .
318 "\n\n";
319 return $bodyTop;
41b94d65 320}
09044055 321/* ----------------------------------------------------------------------- */
322
44560457 323/*
1c044820 324 * If the session is expired during a post this restores the compose session
44560457 325 * vars.
326 */
f8eb968d 327$session_expired = false;
5da08ef7 328if (sqsession_is_registered('session_expired_post')) {
953fa718 329 sqgetGlobalVar('session_expired_post', $session_expired_post, SQ_SESSION);
1c044820 330 /*
40934000 331 * extra check for username so we don't display previous post data from
332 * another user during this session.
333 */
c7ebdfcf 334 if (!empty($session_expired_post['username'])
335 && $session_expired_post['username'] == $username) {
1638beb6 336 // these are the vars that we can set from the expired composed session
f8eb968d 337 $compo_var_list = array ('send_to', 'send_to_cc', 'body',
338 'startMessage', 'passed_body', 'use_signature', 'signature',
339 'subject', 'newmail', 'send_to_bcc', 'passed_id', 'mailbox',
340 'from_htmladdr_search', 'identity', 'draft_id', 'delete_draft',
341 'mailprio', 'edit_as_new', 'attachments', 'composesession',
e506b6e5 342 'request_mdn', 'request_dr', 'fwduid');
c6f28eb1 343
344 foreach ($compo_var_list as $var) {
345 if ( isset($session_expired_post[$var]) && !isset($$var) ) {
774d79cc 346 $$var = $session_expired_post[$var];
61e96f7e 347 }
40934000 348 }
c6f28eb1 349
f8eb968d 350 if (!empty($attachments))
177cb345 351 $attachments = unserialize(urldecode($attachments));
f8eb968d 352
0ec1a14b 353 sqsession_register($composesession,'composesession');
f8eb968d 354
40934000 355 if (isset($send)) {
356 unset($send);
357 }
358 $session_expired = true;
359 }
5da08ef7 360 unset($session_expired_post);
0b97a708 361 sqsession_unregister('session_expired_post');
5da08ef7 362 session_write_close();
40934000 363 if (!isset($mailbox)) {
364 $mailbox = '';
365 }
366 if ($compose_new_win == '1') {
367 compose_Header($color, $mailbox);
368 } else {
91c27aee 369 $sHeaderJs = (isset($sHeaderJs)) ? $sHeaderJs : '';
370 if (strpos($action, 'reply') !== false && $reply_focus) {
ca14ebb7 371 $sOnload = 'checkForm(\''.$replyfocus.'\');';
91c27aee 372 } else {
ca14ebb7 373 $sOnload = 'checkForm();';
91c27aee 374 }
ca14ebb7 375 displayPageHeader($color, $mailbox,$sHeaderJs,$sOnload);
40934000 376 }
377 showInputForm($session, false);
378 exit();
44560457 379}
f8eb968d 380
da95c4b6 381if (!isset($composesession)) {
382 $composesession = 0;
a43e4b90 383 sqsession_register(0,'composesession');
7e2ff844 384} else {
385 $composesession = (int)$composesession;
da95c4b6 386}
387
d7f8e6e6 388if (!isset($session) || (isset($newmessage) && $newmessage)) {
0b97a708 389 sqsession_unregister('composesession');
1c044820 390 $session = "$composesession" +1;
91f2085b 391 $composesession = $session;
a43e4b90 392 sqsession_register($composesession,'composesession');
1c044820 393}
b4e7df34 394if (!empty($compose_messages[$session])) {
395 $composeMessage = $compose_messages[$session];
396} else {
73ad81bf 397 $composeMessage = new Message();
398 $rfc822_header = new Rfc822Header();
399 $composeMessage->rfc822_header = $rfc822_header;
400 $composeMessage->reply_rfc822_header = '';
a43e4b90 401}
a43e4b90 402
f8eb968d 403// re-add attachments that were already in this message
404// FIXME: note that technically this is very bad form -
405// should never directly manipulate an object like this
406if (!empty($attachments)) {
177cb345 407 $attachments = unserialize(urldecode($attachments));
f8eb968d 408 if (!empty($attachments) && is_array($attachments))
409 $composeMessage->entities = $attachments;
410}
411
876fdb60 412if (empty($mailbox)) {
00793a25 413 $mailbox = 'INBOX';
414}
415
4dfb9db7 416if ($draft) {
199a9ab8 417
418 // validate security token
419 //
2cefa62a 420 sm_validate_security_token($submitted_token, -1, TRUE);
199a9ab8 421
4dfb9db7 422 /*
423 * Set $default_charset to correspond with the user's selection
424 * of language interface.
425 */
426 set_my_charset();
b7ff469f 427 if (! deliverMessage($composeMessage, true)) {
da95c4b6 428 showInputForm($session);
00793a25 429 exit();
734f4ee6 430 } else {
00793a25 431 $draft_message = _("Draft Email Saved");
432 /* If this is a resumed draft, then delete the original */
433 if(isset($delete_draft)) {
a9805897 434 $imap_stream = sqimap_login($username, false, $imapServerAddress, $imapPort, false, $imap_stream_options);
b034bca2 435 sqimap_mailbox_select($imap_stream, $draft_folder);
436 // force bypass_trash=true because message should be saved when deliverMessage() returns true.
91c27aee 437 // in current implementation of sqimap_msgs_list_flag() single message id can
b034bca2 438 // be submitted as string. docs state that it should be array.
439 sqimap_msgs_list_delete($imap_stream, $draft_folder, $delete_draft, true);
440 if ($auto_expunge) {
441 sqimap_mailbox_expunge($imap_stream, $draft_folder, true);
9c3e6cd4 442 }
b034bca2 443 sqimap_logout($imap_stream);
444 }
1638beb6 445
762853f4 446 $oErrorHandler->saveDelayedErrors();
c077ffeb 447 session_write_close();
762853f4 448
b034bca2 449 if ($compose_new_win == '1') {
09047d19 450 if ( !isset($pageheader_sent) || !$pageheader_sent ) {
39cf816f 451 header("Location: $location/compose.php?saved_draft=yes&session=$composesession");
09047d19 452 } else {
c8dc86c9 453//FIXME: DON'T ECHO HTML FROM CORE!
f265009a 454 echo ' <br><br><div style="text-align: center;"><a href="' . $location
09047d19 455 . '/compose.php?saved_sent=yes&amp;session=' . $composesession . '">'
f265009a 456 . _("Return") . '</a></div>';
a6d3eff6 457 }
b034bca2 458 exit();
459 } else {
09047d19 460 if ( !isset($pageheader_sent) || !$pageheader_sent ) {
39cf816f 461 header("Location: $location/right_main.php?mailbox=" . urlencode($draft_folder) .
b034bca2 462 "&startMessage=1&note=".urlencode($draft_message));
09047d19 463 } else {
c8dc86c9 464//FIXME: DON'T ECHO HTML FROM CORE!
f265009a 465 echo ' <br><br><div style="text-align: center;"><a href="' . $location
09047d19 466 . '/right_main.php?mailbox=' . urlencode($draft_folder)
467 . '&amp;startMessage=1&amp;note=' . urlencode($draft_message) .'">'
f265009a 468 . _("Return") . '</a></div>';
a6d3eff6 469 }
b034bca2 470 exit();
00793a25 471 }
472 }
473}
474
4dfb9db7 475if ($send) {
199a9ab8 476
477 // validate security token
478 //
2cefa62a 479 sm_validate_security_token($submitted_token, -1, TRUE);
199a9ab8 480
0b97a708 481 if (isset($_FILES['attachfile']) &&
73ad81bf 482 $_FILES['attachfile']['tmp_name'] &&
483 $_FILES['attachfile']['tmp_name'] != 'none') {
da95c4b6 484 $AttachFailure = saveAttachedFiles($session);
00793a25 485 }
d887e067 486
00793a25 487 if (checkInput(false) && !isset($AttachFailure)) {
73ad81bf 488 if ($mailbox == "All Folders") {
489 /* We entered compose via the search results page */
a42c236f 490 $mailbox = 'INBOX'; /* Send 'em to INBOX, that's safe enough */
73ad81bf 491 }
9a19cc66 492 $urlMailbox = urlencode($mailbox);
3f6b1b6f 493 if (! isset($passed_id)) {
494 $passed_id = 0;
00793a25 495 }
d4c5c50c 496 /**
00793a25 497 * Set $default_charset to correspond with the user's selection
7058a2a9 498 * of language interface.
00793a25 499 */
500 set_my_charset();
d4c5c50c 501 /**
00793a25 502 * This is to change all newlines to \n
7058a2a9 503 * We'll change them to \r\n later (in the sendMessage function)
00793a25 504 */
505 $body = str_replace("\r\n", "\n", $body);
506 $body = str_replace("\r", "\n", $body);
507
d4c5c50c 508 /**
18c9998a 509 * Rewrap $body so that no line is bigger than $editor_size
00793a25 510 */
18c9998a 511 $body = explode("\n", $body);
512 $newBody = '';
513 foreach ($body as $line) {
514 if( $line <> '-- ' ) {
73ad81bf 515 $line = rtrim($line);
18c9998a 516 }
774d79cc 517 if (sq_strlen($line, $default_charset) <= $editor_size + 1) {
18c9998a 518 $newBody .= $line . "\n";
519 } else {
774d79cc 520 sqWordWrap($line, $editor_size, $default_charset);
18c9998a 521 $newBody .= $line . "\n";
522
523 }
524
525 }
526 $body = $newBody;
1c044820 527
a91189d6 528 $Result = deliverMessage($composeMessage);
81de00c0 529
64793f9a 530 if ($Result)
531 $mail_sent = 'yes';
532 else
533 $mail_sent = 'no';
534
1638beb6 535 // NOTE: this hook changed in 1.5.2 from sending $Result and
6e515418 536 // $composeMessage as args #2 and #3 to being in an array
537 // under arg #2
802e7490 538 $temp = array(&$Result, &$composeMessage, &$mail_sent);
539 do_hook('compose_send_after', $temp);
00793a25 540 if (! $Result) {
da95c4b6 541 showInputForm($session);
00793a25 542 exit();
543 }
5c4ff7bf 544
b034bca2 545 /* if it is resumed draft, delete draft message */
00793a25 546 if ( isset($delete_draft)) {
a9805897 547 $imap_stream = sqimap_login($username, false, $imapServerAddress, $imapPort, false, $imap_stream_options);
b034bca2 548 sqimap_mailbox_select($imap_stream, $draft_folder);
549 // bypass_trash=true because message should be saved when deliverMessage() returns true.
91c27aee 550 // in current implementation of sqimap_msgs_list_flag() single message id can
b034bca2 551 // be submitted as string. docs state that it should be array.
552 sqimap_msgs_list_delete($imap_stream, $draft_folder, $delete_draft, true);
553 if ($auto_expunge) {
554 sqimap_mailbox_expunge($imap_stream, $draft_folder, true);
555 }
556 sqimap_logout($imap_stream);
00793a25 557 }
81de00c0 558 /*
559 * Store the error array in the session because they will be lost on a redirect
560 */
762853f4 561 $oErrorHandler->saveDelayedErrors();
c077ffeb 562 session_write_close();
762853f4 563
9c3e6cd4 564 if ($compose_new_win == '1') {
09047d19 565 if ( !isset($pageheader_sent) || !$pageheader_sent ) {
39cf816f 566 header("Location: $location/compose.php?mail_sent=$mail_sent");
09047d19 567 } else {
c8dc86c9 568//FIXME: DON'T ECHO HTML FROM CORE!
f265009a 569 echo ' <br><br><div style="text-align: center;"><a href="' . $location
64793f9a 570 . '/compose.php?mail_sent=$mail_sent">'
f265009a 571 . _("Return") . '</a></div>';
09047d19 572 }
573 exit();
574 } else {
575 if ( !isset($pageheader_sent) || !$pageheader_sent ) {
39cf816f 576 header("Location: $location/right_main.php?mailbox=$urlMailbox".
64793f9a 577 "&startMessage=$startMessage&mail_sent=$mail_sent");
09047d19 578 } else {
c8dc86c9 579//FIXME: DON'T ECHO HTML FROM CORE!
f265009a 580 echo ' <br><br><div style="text-align: center;"><a href="' . $location
09047d19 581 . "/right_main.php?mailbox=$urlMailbox"
64793f9a 582 . "&amp;startMessage=$startMessage&amp;mail_sent=$mail_sent\">"
f265009a 583 . _("Return") . '</a></div>';
09047d19 584 }
585 exit();
9c3e6cd4 586 }
734f4ee6 587 } else {
9c3e6cd4 588 if ($compose_new_win == '1') {
589 compose_Header($color, $mailbox);
590 }
591 else {
592 displayPageHeader($color, $mailbox);
593 }
00793a25 594 if (isset($AttachFailure)) {
73ad81bf 595 plain_error_message(_("Could not move/copy file. File not attached"),
596 $color);
00793a25 597 }
00793a25 598 checkInput(true);
da95c4b6 599 showInputForm($session);
00793a25 600 /* sqimap_logout($imapConnection); */
601 }
e02775fe 602} elseif (isset($html_addr_search_done)) {
199a9ab8 603
604 // validate security token
605 //
2cefa62a 606 sm_validate_security_token($submitted_token, -1, TRUE);
199a9ab8 607
73ad81bf 608 if ($compose_new_win == '1') {
609 compose_Header($color, $mailbox);
610 }
611 else {
612 displayPageHeader($color, $mailbox);
613 }
00793a25 614
615 if (isset($send_to_search) && is_array($send_to_search)) {
616 foreach ($send_to_search as $k => $v) {
617 if (substr($k, 0, 1) == 'T') {
618 if ($send_to) {
619 $send_to .= ', ';
620 }
621 $send_to .= $v;
622 }
623 elseif (substr($k, 0, 1) == 'C') {
624 if ($send_to_cc) {
625 $send_to_cc .= ', ';
626 }
627 $send_to_cc .= $v;
628 }
629 elseif (substr($k, 0, 1) == 'B') {
630 if ($send_to_bcc) {
631 $send_to_bcc .= ', ';
632 }
633 $send_to_bcc .= $v;
634 }
635 }
636 }
da95c4b6 637 showInputForm($session);
167c6996 638} elseif (isset($html_addr_search) && !isset($html_addr_search_cancel)) {
0b97a708 639 if (isset($_FILES['attachfile']) &&
73ad81bf 640 $_FILES['attachfile']['tmp_name'] &&
641 $_FILES['attachfile']['tmp_name'] != 'none') {
0b97a708 642 if(saveAttachedFiles($session)) {
cb34dbd0 643 plain_error_message(_("Could not move/copy file. File not attached"));
00793a25 644 }
645 }
646 /*
647 * I am using an include so as to elminiate an extra unnecessary
648 * click. If you can think of a better way, please implement it.
649 */
650 include_once('./addrbook_search_html.php');
e02775fe 651} elseif (isset($attach)) {
199a9ab8 652
653 // validate security token
654 //
2cefa62a 655 sm_validate_security_token($submitted_token, -1, TRUE);
199a9ab8 656
73ad81bf 657 if ($compose_new_win == '1') {
658 compose_Header($color, $mailbox);
659 } else {
660 displayPageHeader($color, $mailbox);
661 }
5a3e52f3 662 if (saveAttachedFiles($session)) {
cb34dbd0 663 plain_error_message(_("Could not move/copy file. File not attached"));
5a3e52f3 664 }
da95c4b6 665 showInputForm($session);
01265fba 666}
667elseif (isset($sigappend)) {
199a9ab8 668
669 // validate security token
670 //
2cefa62a 671 sm_validate_security_token($submitted_token, -1, TRUE);
199a9ab8 672
1e2a6ff6 673 $signature = $idents[$identity]['signature'];
674
01265fba 675 $body .= "\n\n".($prefix_sig==true? "-- \n":'').$signature;
676 if ($compose_new_win == '1') {
73ad81bf 677 compose_Header($color, $mailbox);
01265fba 678 } else {
679 displayPageHeader($color, $mailbox);
680 }
da95c4b6 681 showInputForm($session);
e02775fe 682} elseif (isset($do_delete)) {
199a9ab8 683
684 // validate security token
685 //
2cefa62a 686 sm_validate_security_token($submitted_token, -1, TRUE);
199a9ab8 687
73ad81bf 688 if ($compose_new_win == '1') {
689 compose_Header($color, $mailbox);
690 } else {
691 displayPageHeader($color, $mailbox);
692 }
00793a25 693
00793a25 694 if (isset($delete) && is_array($delete)) {
695 foreach($delete as $index) {
a58b05b4 696 if (!empty($composeMessage->entities) && isset($composeMessage->entities[$index])) {
c077ffeb 697 $composeMessage->entities[$index]->purgeAttachments();
16449d84 698 // FIXME: one person reported that unset() didn't do anything at all here, so this is a work-around... but it triggers PHP notices if the unset() doesn't work, which should be fixed... but bigger question is if unset() doesn't work here, what about everywhere else? Anyway, uncomment this if you think you need it
699 //$composeMessage->entities[$index] = NULL;
a58b05b4 700 unset ($composeMessage->entities[$index]);
701 }
a91189d6 702 }
703 $new_entities = array();
704 foreach ($composeMessage->entities as $entity) {
705 $new_entities[] = $entity;
00793a25 706 }
a91189d6 707 $composeMessage->entities = $new_entities;
00793a25 708 }
da95c4b6 709 showInputForm($session);
734f4ee6 710} else {
00793a25 711 /*
712 * This handles the default case as well as the error case
1c044820 713 * (they had the same code) --> if (isset($smtpErrors))
00793a25 714 */
44560457 715
716 if ($compose_new_win == '1') {
73ad81bf 717 compose_Header($color, $mailbox);
44560457 718 } else {
73ad81bf 719 displayPageHeader($color, $mailbox);
44560457 720 }
00793a25 721
722 $newmail = true;
723
a61878d0 724 if (!isset($passed_ent_id)) {
725 $passed_ent_id = '';
726 }
727 if (!isset($passed_id)) {
1c044820 728 $passed_id = '';
a61878d0 729 }
730 if (!isset($mailbox)) {
731 $mailbox = '';
1c044820 732 }
a61878d0 733 if (!isset($action)) {
734 $action = '';
735 }
1c044820 736
44560457 737 $values = newMail($mailbox,$passed_id,$passed_ent_id, $action, $session);
b9928adc 738
f2ad47f1 739 // forward as attachment - subject is in the message in session
740 //
741 if ($action == 'forward_as_attachment' && empty($values['subject']))
742 $subject = $composeMessage->rfc822_header->subject;
743
b9928adc 744 /* in case the origin is not read_body.php */
745 if (isset($send_to)) {
73ad81bf 746 $values['send_to'] = $send_to;
b9928adc 747 }
748 if (isset($send_to_cc)) {
73ad81bf 749 $values['send_to_cc'] = $send_to_cc;
b9928adc 750 }
751 if (isset($send_to_bcc)) {
73ad81bf 752 $values['send_to_bcc'] = $send_to_bcc;
b9928adc 753 }
2a2f2185 754 if (isset($subject)) {
73ad81bf 755 $values['subject'] = $subject;
2a2f2185 756 }
79cecc00 757 if (isset($mailprio)) {
758 $values['mailprio'] = $mailprio;
759 }
760 if (isset($orig_identity)) {
761 $values['identity'] = $orig_identity;
762 }
41b94d65 763 showInputForm($session, $values);
00793a25 764}
765
766exit();
767
00793a25 768/**************** Only function definitions go below *************/
769
92c6f757 770function getforwardSubject($subject)
771{
772 if ((substr(strtolower($subject), 0, 4) != 'fwd:') &&
73ad81bf 773 (substr(strtolower($subject), 0, 5) != '[fwd:') &&
774 (substr(strtolower($subject), 0, 6) != '[ fwd:')) {
92c6f757 775 $subject = '[Fwd: ' . $subject . ']';
776 }
777 return $subject;
778}
00793a25 779
48985d59 780/* This function is used when not sending or adding attachments */
44560457 781function newMail ($mailbox='', $passed_id='', $passed_ent_id='', $action='', $session='') {
1e2a6ff6 782 global $editor_size, $default_use_priority, $body, $idents,
ce68b76b 783 $use_signature, $data_dir, $username,
a9805897 784 $key, $imapServerAddress, $imapPort, $imap_stream_options,
74f66d27 785 $composeMessage, $body_quote, $request_mdn, $request_dr,
856e58ef 786 $mdn_user_support, $languages, $squirrelmail_language,
ace75dcb 787 $default_charset, $do_not_reply_to_self;
e7f1a81d 788
d4f20027 789 /*
790 * Set $default_charset to correspond with the user's selection
791 * of language interface. $default_charset global is not correct,
792 * if message is composed in new window.
793 */
794 set_my_charset();
795
91f2085b 796 $send_to = $send_to_cc = $send_to_bcc = $subject = $identity = '';
bdb92db3 797 $mailprio = 3;
44560457 798
41b94d65 799 if ($passed_id) {
906f7e9f 800 $imapConnection = sqimap_login($username, false, $imapServerAddress,
a9805897 801 $imapPort, 0, $imap_stream_options);
a61878d0 802
48985d59 803 sqimap_mailbox_select($imapConnection, $mailbox);
41b94d65 804 $message = sqimap_get_message($imapConnection, $passed_id, $mailbox);
1c044820 805
a61878d0 806 $body = '';
807 if ($passed_ent_id) {
808 /* redefine the messsage in case of message/rfc822 */
809 $message = $message->getEntity($passed_ent_id);
810 /* message is an entity which contains the envelope and type0=message
73ad81bf 811 * and type1=rfc822. The actual entities are childs from
812 * $message->entities[0]. That's where the encoding and is located
813 */
a61878d0 814
815 $entities = $message->entities[0]->findDisplayEntity
73ad81bf 816 (array(), $alt_order = array('text/plain'));
a61878d0 817 if (!count($entities)) {
818 $entities = $message->entities[0]->findDisplayEntity
9c462f8b 819 (array(), $alt_order = array('text/plain','text/html'));
a61878d0 820 }
821 $orig_header = $message->rfc822_header; /* here is the envelope located */
822 /* redefine the message for picking up the attachments */
823 $message = $message->entities[0];
824
825 } else {
826 $entities = $message->findDisplayEntity (array(), $alt_order = array('text/plain'));
827 if (!count($entities)) {
9c462f8b 828 $entities = $message->findDisplayEntity (array(), $alt_order = array('text/plain','text/html'));
a61878d0 829 }
830 $orig_header = $message->rfc822_header;
831 }
1c044820 832
a61878d0 833 $type0 = $message->type0;
834 $type1 = $message->type1;
41b94d65 835 foreach ($entities as $ent) {
b455e47b 836 $msg = $message->getEntity($ent);
837 $type0 = $msg->type0;
838 $type1 = $msg->type1;
a61878d0 839 $unencoded_bodypart = mime_fetch_body($imapConnection, $passed_id, $ent);
840 $body_part_entity = $message->getEntity($ent);
1638beb6 841 $bodypart = decodeBody($unencoded_bodypart,
73ad81bf 842 $body_part_entity->header->encoding);
a61878d0 843 if ($type1 == 'html') {
5b755d9f 844 $bodypart = str_replace("\n", ' ', $bodypart);
bb977394 845 $bodypart = preg_replace(array('/<\/?p>/i','/<div><\/div>/i','/<br\s*(\/)*>/i','/<\/?div>/i'), "\n", $bodypart);
5b755d9f 846 $bodypart = str_replace(array('&nbsp;','&gt;','&lt;'),array(' ','>','<'),$bodypart);
a61878d0 847 $bodypart = strip_tags($bodypart);
848 }
e842b215 849 if (isset($languages[$squirrelmail_language]['XTRA_CODE']) &&
73ad81bf 850 function_exists($languages[$squirrelmail_language]['XTRA_CODE'] . '_decode')) {
e842b215 851 if (mb_detect_encoding($bodypart) != 'ASCII') {
f4bb5d22 852 $bodypart = call_user_func($languages[$squirrelmail_language]['XTRA_CODE'] . '_decode', $bodypart);
e842b215 853 }
854 }
eceefdfe 855
bfa54da7 856 // charset encoding in compose form stuff
73ad81bf 857 if (isset($body_part_entity->header->parameters['charset'])) {
858 $actual = $body_part_entity->header->parameters['charset'];
859 } else {
860 $actual = 'us-ascii';
861 }
beca818e 862
73ad81bf 863 if ( $actual && is_conversion_safe($actual) && $actual != $default_charset){
864 $bodypart = charset_convert($actual,$bodypart,$default_charset,false);
865 }
bfa54da7 866 // end of charset encoding in compose
eceefdfe 867
a61878d0 868 $body .= $bodypart;
869 }
870 if ($default_use_priority) {
871 $mailprio = substr($orig_header->priority,0,1);
872 if (!$mailprio) {
873 $mailprio = 3;
874 }
875 } else {
876 $mailprio = '';
877 }
bdb92db3 878
a45887d7 879 $from_o = $orig_header->from;
fe868193 880 if (is_array($from_o)) {
881 if (isset($from_o[0])) {
882 $from_o = $from_o[0];
883 }
884 }
bdb92db3 885 if (is_object($from_o)) {
886 $orig_from = $from_o->getAddress();
887 } else {
888 $orig_from = '';
a61878d0 889 }
1e2a6ff6 890
a91189d6 891 $identities = array();
1e2a6ff6 892 if (count($idents) > 1) {
893 foreach($idents as $nr=>$data) {
894 $enc_from_name = '"'.$data['full_name'].'" <'. $data['email_address'].'>';
a91189d6 895 $identities[] = $enc_from_name;
896 }
1e2a6ff6 897
a91189d6 898 $identity_match = $orig_header->findAddress($identities);
ea721316 899 if ($identity_match !== FALSE) {
a91189d6 900 $identity = $identity_match;
a61878d0 901 }
bdb92db3 902 }
a61878d0 903
904 switch ($action) {
73ad81bf 905 case ('draft'):
906 $use_signature = FALSE;
907 $composeMessage->rfc822_header = $orig_header;
908 $send_to = decodeHeader($orig_header->getAddr_s('to'),false,false,true);
909 $send_to_cc = decodeHeader($orig_header->getAddr_s('cc'),false,false,true);
910 $send_to_bcc = decodeHeader($orig_header->getAddr_s('bcc'),false,false,true);
911 $send_from = $orig_header->getAddr_s('from');
912 $send_from_parts = new AddressStructure();
913 $send_from_parts = $orig_header->parseAddress($send_from);
914 $send_from_add = $send_from_parts->mailbox . '@' . $send_from_parts->host;
40e07136 915 $identity = find_identity(array($send_from_add));
73ad81bf 916 $subject = decodeHeader($orig_header->subject,false,false,true);
1638beb6 917
762853f4 918 // Remember the receipt settings
919 $request_mdn = $mdn_user_support && !empty($orig_header->dnt) ? '1' : '0';
920 $request_dr = $mdn_user_support && !empty($orig_header->drnt) ? '1' : '0';
1638beb6 921
73ad81bf 922 /* remember the references and in-reply-to headers in case of an reply */
657fe1bd 923//FIXME: it would be better to fiddle with headers inside of the message object or possibly when delivering the message to its destination (drafts folder?); is this possible?
73ad81bf 924 $composeMessage->rfc822_header->more_headers['References'] = $orig_header->references;
925 $composeMessage->rfc822_header->more_headers['In-Reply-To'] = $orig_header->in_reply_to;
926 // rewrap the body to clean up quotations and line lengths
927 sqBodyWrap($body, $editor_size);
928 $composeMessage = getAttachments($message, $composeMessage, $passed_id, $entities, $imapConnection);
041d360b 929//TODO: completely unclear if should be using $compose_session instead of $session below
930 $compose_messages[$session] = $composeMessage;
931 sqsession_register($compose_messages,'compose_messages');
73ad81bf 932 break;
933 case ('edit_as_new'):
934 $send_to = decodeHeader($orig_header->getAddr_s('to'),false,false,true);
935 $send_to_cc = decodeHeader($orig_header->getAddr_s('cc'),false,false,true);
936 $send_to_bcc = decodeHeader($orig_header->getAddr_s('bcc'),false,false,true);
937 $subject = decodeHeader($orig_header->subject,false,false,true);
938 $mailprio = $orig_header->priority;
939 $orig_from = '';
940 $composeMessage = getAttachments($message, $composeMessage, $passed_id, $entities, $imapConnection);
941 // rewrap the body to clean up quotations and line lengths
942 sqBodyWrap($body, $editor_size);
943 break;
944 case ('forward'):
945 $send_to = '';
946 $subject = getforwardSubject(decodeHeader($orig_header->subject,false,false,true));
947 $body = getforwardHeader($orig_header) . $body;
948 // the logic for calling sqUnWordWrap here would be to allow the browser to wrap the lines
949 // forwarded message text should be as undisturbed as possible, so commenting out this call
950 // sqUnWordWrap($body);
951 $composeMessage = getAttachments($message, $composeMessage, $passed_id, $entities, $imapConnection);
91c27aee 952
73ad81bf 953 //add a blank line after the forward headers
954 $body = "\n" . $body;
955 break;
956 case ('forward_as_attachment'):
957 $subject = getforwardSubject(decodeHeader($orig_header->subject,false,false,true));
958 $composeMessage = getMessage_RFC822_Attachment($message, $composeMessage, $passed_id, $passed_ent_id, $imapConnection);
f2ad47f1 959 $subject = decodeHeader($orig_header->subject,false,false,true);
960 $subject = str_replace('"', "'", $subject);
961 $subject = trim($subject);
962 if (substr(strtolower($subject), 0, 4) != 'fwd:') {
963 $subject = 'Fwd: ' . $subject;
964 }
73ad81bf 965 $body = '';
966 break;
967 case ('reply_all'):
968 if(isset($orig_header->mail_followup_to) && $orig_header->mail_followup_to) {
969 $send_to = $orig_header->getAddr_s('mail_followup_to');
b268e66b 970 } else {
73ad81bf 971 $send_to_cc = replyAllString($orig_header);
972 $send_to_cc = decodeHeader($send_to_cc,false,false,true);
a9b9e5d3 973 $send_to_cc = str_replace('""', '"', $send_to_cc);
b268e66b 974 }
73ad81bf 975 case ('reply'):
976 // skip this if send_to was already set right above here
977 if(!$send_to) {
978 $send_to = $orig_header->reply_to;
979 if (is_array($send_to) && count($send_to)) {
a9b9e5d3 980 $send_to = $orig_header->getAddr_s('reply_to', ',', FALSE, TRUE);
73ad81bf 981 } else if (is_object($send_to)) { /* unneccesarry, just for failsafe purpose */
a9b9e5d3 982 $send_to = $orig_header->getAddr_s('reply_to', ',', FALSE, TRUE);
73ad81bf 983 } else {
a9b9e5d3 984 $send_to = $orig_header->getAddr_s('from', ',', FALSE, TRUE);
73ad81bf 985 }
dd4a44cd 986 }
73ad81bf 987 $send_to = decodeHeader($send_to,false,false,true);
a9b9e5d3 988 $send_to = str_replace('""', '"', $send_to);
ace75dcb 989
990
991 // If user doesn't want replies to her own messages
992 // going back to herself (instead send again to the
993 // original recipient of the message being replied to),
994 // then iterate through identities, checking if the TO
995 // field is one of them (if the reply is to ourselves)
996 //
997 // Note we don't bother if the original message doesn't
998 // have anything in the TO field itself (because that's
999 // what we use if we change the recipient to be that of
1000 // the previous message)
1001 //
1002 if ($do_not_reply_to_self && !empty($orig_header->to)) {
1003
1004 $orig_to = '';
1005
1006 foreach($idents as $id) {
1007
1008 if (!empty($id['email_address'])
1009 && strpos($send_to, $id['email_address']) !== FALSE) {
1010
1011 // if this is a reply-all, the original recipient
1012 // is already in the CC field, so we can just blank
1013 // the recipient (TO field) (as long as the CC field
a9b6e52d 1014 // isn't empty that is)... but then move the CC into
1015 // the TO, so TO isn't empty
ace75dcb 1016 //
6fac6196 1017 if ($action == 'reply_all' && !empty($send_to_cc)) {
a9b6e52d 1018 $orig_to = $send_to_cc;
1019 $send_to_cc = '';
ace75dcb 1020 break;
1021 }
1022
1023 $orig_to = $orig_header->to;
1024 if (is_array($orig_to) && count($orig_to)) {
1025 $orig_to = $orig_header->getAddr_s('to', ',', FALSE, TRUE);
1026 } else if (is_object($orig_to)) { /* unneccesarry, just for failsafe purpose */
1027 $orig_to = $orig_header->getAddr_s('to', ',', FALSE, TRUE);
1028 } else {
1029 $orig_to = '';
1030 }
1031 $orig_to = decodeHeader($orig_to,false,false,true);
1032 $orig_to = str_replace('""', '"', $orig_to);
1033
1034 break;
1035 }
1036 }
1037
1038 // if the reply was addressed back to ourselves,
5df2efa2 1039 // we will send it to the TO of the previous message
ace75dcb 1040 //
1041 if (!empty($orig_to)) {
1042
5df2efa2 1043 $send_to = $orig_to;
5777c73d 1044
1045 // in this case, we also want to reset the FROM
1046 // identity as well (it should match the original
1047 // *FROM* header instead of TO or CC)
1048 //
1049 if (count($idents) > 1) {
1050 $identity = '';
1051 foreach($idents as $i => $id) {
1052 if (!empty($id['email_address'])
1053 && strpos($orig_from, $id['email_address']) !== FALSE) {
1054 $identity = $i;
1055 break;
1056 }
1057 }
1058 }
1059
ace75dcb 1060 }
1061
1062 }
1063
1064
73ad81bf 1065 $subject = decodeHeader($orig_header->subject,false,false,true);
1066 $subject = str_replace('"', "'", $subject);
1067 $subject = trim($subject);
1068 if (substr(strtolower($subject), 0, 3) != 're:') {
1069 $subject = 'Re: ' . $subject;
1070 }
1071 /* this corrects some wrapping/quoting problems on replies */
1072 $rewrap_body = explode("\n", $body);
3aaa3214 1073 $from = (is_array($orig_header->from) && !empty($orig_header->from)) ? $orig_header->from[0] : $orig_header->from;
73ad81bf 1074 $body = '';
1075 $strip_sigs = getPref($data_dir, $username, 'strip_sigs');
1076 foreach ($rewrap_body as $line) {
3673a2de 1077 if ($strip_sigs && rtrim($line, "\r\n") == '-- ') {
73ad81bf 1078 break;
1079 }
1080 if (preg_match("/^(>+)/", $line, $matches)) {
1081 $gt = $matches[1];
1082 $body .= $body_quote . str_replace("\n", "\n$body_quote$gt ", rtrim($line)) ."\n";
1083 } else {
1084 $body .= $body_quote . (!empty($body_quote) ? ' ' : '') . str_replace("\n", "\n$body_quote" . (!empty($body_quote) ? ' ' : ''), rtrim($line)) . "\n";
1085 }
a61878d0 1086 }
c9d61baf 1087
73ad81bf 1088 //rewrap the body to clean up quotations and line lengths
1089 $body = sqBodyWrap ($body, $editor_size);
c9d61baf 1090
73ad81bf 1091 $body = getReplyCitation($from , $orig_header->date) . $body;
1092 $composeMessage->reply_rfc822_header = $orig_header;
12a0ed01 1093
73ad81bf 1094 break;
1095 default:
1096 break;
41b94d65 1097 }
b4e7df34 1098//FIXME: we used to register $compose_messages in the session here, but not any more - so do we still need the session_write_close() and sqimap_logout() here? We probably need the IMAP logout, but what about the session closure?
5da08ef7 1099 session_write_close();
a61878d0 1100 sqimap_logout($imapConnection);
41b94d65 1101 }
a61878d0 1102 $ret = array( 'send_to' => $send_to,
73ad81bf 1103 'send_to_cc' => $send_to_cc,
1104 'send_to_bcc' => $send_to_bcc,
1105 'subject' => $subject,
1106 'mailprio' => $mailprio,
1107 'body' => $body,
1108 'identity' => $identity );
a61878d0 1109
41b94d65 1110 return ($ret);
48985d59 1111} /* function newMail() */
1112
50706f77 1113/**
1114 * downloads attachments from original message, stores them in attachment directory and adds
1115 * them to composed message.
1116 * @param object $message
1117 * @param object $composeMessage
1118 * @param integer $passed_id
1119 * @param mixed $entities
1120 * @param mixed $imapConnection
91c27aee 1121 * @return object
50706f77 1122 */
a43e4b90 1123function getAttachments($message, &$composeMessage, $passed_id, $entities, $imapConnection) {
1f270d3c 1124 global $squirrelmail_language, $languages, $username, $attachment_dir;
628bce99 1125
1c044820 1126 if (!count($message->entities) ||
73ad81bf 1127 ($message->type0 == 'message' && $message->type1 == 'rfc822')) {
41b94d65 1128 if ( !in_array($message->entity_id, $entities) && $message->entity_id) {
73ad81bf 1129 switch ($message->type0) {
1130 case 'message':
1131 if ($message->type1 == 'rfc822') {
1132 $filename = $message->rfc822_header->subject;
1133 if ($filename == "") {
1134 $filename = "untitled-".$message->entity_id;
1135 }
6f71f6e6 1136 $filename .= '.eml';
73ad81bf 1137 } else {
1138 $filename = $message->getFilename();
181538ac 1139 }
73ad81bf 1140 break;
1141 default:
1142 if (!$message->mime_header) { /* temporary hack */
1143 $message->mime_header = $message->header;
1144 }
1145 $filename = $message->getFilename();
1146 break;
1147 }
117aa0c5 1148//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
1149 $filename = str_replace('&#32;', ' ', decodeHeader($filename, true, true, true));
73ad81bf 1150 if (isset($languages[$squirrelmail_language]['XTRA_CODE']) &&
1151 function_exists($languages[$squirrelmail_language]['XTRA_CODE'] . '_encode')) {
f4bb5d22 1152 $filename = call_user_func($languages[$squirrelmail_language]['XTRA_CODE'] . '_encode', $filename);
73ad81bf 1153 }
1f270d3c 1154
1155 $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
628bce99 1156 $localfilename = sq_get_attach_tempfile();
1157 $message->att_local_name = $localfilename;
73ad81bf 1158
1159 $composeMessage->initAttachment($message->type0.'/'.$message->type1,$filename,
628bce99 1160 $localfilename);
73ad81bf 1161
1162 /* Write Attachment to file */
1f270d3c 1163 $fp = fopen ($hashed_attachment_dir . '/' . $localfilename, 'wb');
91c27aee 1164 mime_print_body_lines ($imapConnection, $passed_id, $message->entity_id, $message->header->encoding, $fp);
73ad81bf 1165 fclose ($fp);
48985d59 1166 }
734f4ee6 1167 } else {
a43e4b90 1168 for ($i=0, $entCount=count($message->entities); $i<$entCount;$i++) {
1169 $composeMessage=getAttachments($message->entities[$i], $composeMessage, $passed_id, $entities, $imapConnection);
48985d59 1170 }
1171 }
a43e4b90 1172 return $composeMessage;
48985d59 1173}
1174
1c044820 1175function getMessage_RFC822_Attachment($message, $composeMessage, $passed_id,
73ad81bf 1176 $passed_ent_id='', $imapConnection) {
756406df 1177 if (!$passed_ent_id) {
1c044820 1178 $body_a = sqimap_run_command($imapConnection,
73ad81bf 1179 'FETCH '.$passed_id.' RFC822',
1180 TRUE, $response, $readmessage,
1181 TRUE);
756406df 1182 } else {
1c044820 1183 $body_a = sqimap_run_command($imapConnection,
73ad81bf 1184 'FETCH '.$passed_id.' BODY['.$passed_ent_id.']',
1185 TRUE, $response, $readmessage, TRUE);
a61878d0 1186 $message = $message->parent;
756406df 1187 }
d0519c03 1188 if ($response == 'OK') {
a61878d0 1189 $subject = encodeHeader($message->rfc822_header->subject);
1190 array_shift($body_a);
1c044820 1191 array_pop($body_a);
a61878d0 1192 $body = implode('', $body_a) . "\r\n";
1c044820 1193
1f270d3c 1194 global $username, $attachment_dir;
1195 $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
628bce99 1196 $localfilename = sq_get_attach_tempfile();
1f270d3c 1197 $fp = fopen($hashed_attachment_dir . '/' . $localfilename, 'wb');
a61878d0 1198 fwrite ($fp, $body);
1199 fclose($fp);
6f71f6e6 1200 $composeMessage->initAttachment('message/rfc822',$subject.'.eml',
628bce99 1201 $localfilename);
a43e4b90 1202 }
1203 return $composeMessage;
a6ec592e 1204}
1205
41b94d65 1206function showInputForm ($session, $values=false) {
856e58ef 1207 global $send_to, $send_to_cc, $send_to_bcc,
f8eb968d 1208 $body, $startMessage, $action, $attachments,
b2b614bb 1209 $use_signature, $signature, $prefix_sig, $session_expired,
8d8da447 1210 $editor_size, $editor_height, $subject, $newmail,
e506b6e5 1211 $use_javascript_addr_book, $passed_id, $mailbox, $fwduid,
73ad81bf 1212 $from_htmladdr_search, $location_of_buttons, $attachment_dir,
ce68b76b 1213 $username, $data_dir, $identity, $idents, $delete_draft,
1214 $mailprio, $compose_new_win, $saved_draft, $mail_sent, $sig_first,
b4e7df34 1215 $composeMessage, $composesession, $default_charset,
762853f4 1216 $compose_onsubmit, $oTemplate, $oErrorHandler;
a43e4b90 1217
87745b9c 1218 if (checkForJavascript()) {
1219 $onfocus = ' onfocus="alreadyFocused=true;"';
1220 $onfocus_array = array('onfocus' => 'alreadyFocused=true;');
1221 }
1222 else {
1223 $onfocus = '';
1224 $onfocus_array = array();
1225 }
1226
41b94d65 1227 if ($values) {
73ad81bf 1228 $send_to = $values['send_to'];
1229 $send_to_cc = $values['send_to_cc'];
1230 $send_to_bcc = $values['send_to_bcc'];
1231 $subject = $values['subject'];
1232 $mailprio = $values['mailprio'];
1233 $body = $values['body'];
1234 $identity = (int) $values['identity'];
676bb189 1235 } else {
73ad81bf 1236 $send_to = decodeHeader($send_to, true, false);
1237 $send_to_cc = decodeHeader($send_to_cc, true, false);
1238 $send_to_bcc = decodeHeader($send_to_bcc, true, false);
41b94d65 1239 }
1c044820 1240
48985d59 1241 if ($use_javascript_addr_book) {
c8dc86c9 1242//FIXME: NO HTML IN CORE!
2c92ea9d 1243 echo "\n". '<script type="text/javascript">'."\n<!--\n" .
73ad81bf 1244 'function open_abook() { ' . "\n" .
1245 ' var nwin = window.open("addrbook_popup.php","abookpopup",' .
1246 '"width=670,height=300,resizable=yes,scrollbars=yes");' . "\n" .
1247 ' if((!nwin.opener) && (document.windows != null))' . "\n" .
1248 ' nwin.opener = document.windows;' . "\n" .
1249 "}\n" .
1250 "// -->\n</script>\n\n";
48985d59 1251 }
1252
c8dc86c9 1253//FIXME: NO HTML IN CORE!
4a1788b3 1254 echo "\n" . '<form name="compose" action="compose.php" method="post" ' .
73ad81bf 1255 'enctype="multipart/form-data"';
a34b07a5 1256
1257 $compose_onsubmit = array();
6e515418 1258 global $null;
1259 do_hook('compose_form', $null);
1c044820 1260
a34b07a5 1261 // Plugins that use compose_form hook can add an array entry
1262 // to the globally scoped $compose_onsubmit; we add them up
5c4ff7bf 1263 // here and format the form tag's full onsubmit handler.
1264 // Each plugin should use "return false" if they need to
a34b07a5 1265 // stop form submission but otherwise should NOT use "return
1266 // true" to give other plugins the chance to do what they need
1267 // to do; SquirrelMail itself will add the final "return true".
1268 // Onsubmit text is enclosed inside of double quotes, so plugins
1269 // need to quote accordingly.
395c3216 1270 //
1271 // Also, plugin authors should try to retain compatibility with
1272 // the Compose Extras plugin by resetting its compose submit
1273 // counter when preventing form submit. Use this code:
1274 // if (your-code-here) { submit_count = 0; return false; }
1275 //
a34b07a5 1276 if (checkForJavascript()) {
5c4ff7bf 1277 if (empty($compose_onsubmit))
a34b07a5 1278 $compose_onsubmit = array();
5c4ff7bf 1279 else if (!is_array($compose_onsubmit))
a34b07a5 1280 $compose_onsubmit = array($compose_onsubmit);
1281
82dcbb1e 1282 $onsubmit_text = '';
a34b07a5 1283 foreach ($compose_onsubmit as $text) {
1284 $text = trim($text);
82dcbb1e 1285 if (!empty($text)) {
1286 if (substr($text, -1) != ';' && substr($text, -1) != '}')
1287 $text .= '; ';
1288 $onsubmit_text .= $text;
1289 }
a34b07a5 1290 }
1291
82dcbb1e 1292 if (!empty($onsubmit_text))
c8dc86c9 1293//FIXME: DON'T ECHO HTML FROM CORE!
82dcbb1e 1294 echo ' onsubmit="' . $onsubmit_text . ' return true;"';
a34b07a5 1295 }
5c4ff7bf 1296
a34b07a5 1297
c8dc86c9 1298//FIXME: NO HTML IN CORE!
48985d59 1299 echo ">\n";
1300
c8dc86c9 1301//FIXME: DON'T ECHO HTML FROM CORE!
199a9ab8 1302 echo addHidden('smtoken', sm_generate_security_token());
1303
1304//FIXME: DON'T ECHO HTML FROM CORE!
df96b37a 1305 echo addHidden('startMessage', $startMessage);
4a1788b3 1306
41b94d65 1307 if ($action == 'draft') {
c8dc86c9 1308//FIXME: DON'T ECHO HTML FROM CORE!
df96b37a 1309 echo addHidden('delete_draft', $passed_id);
48985d59 1310 }
1311 if (isset($delete_draft)) {
c8dc86c9 1312//FIXME: DON'T ECHO HTML FROM CORE!
df96b37a 1313 echo addHidden('delete_draft', $delete_draft);
48985d59 1314 }
da95c4b6 1315 if (isset($session)) {
c8dc86c9 1316//FIXME: DON'T ECHO HTML FROM CORE!
df96b37a 1317 echo addHidden('session', $session);
da95c4b6 1318 }
1c044820 1319
08bad2b1 1320 if (isset($passed_id)) {
c8dc86c9 1321//FIXME: DON'T ECHO HTML FROM CORE!
df96b37a 1322 echo addHidden('passed_id', $passed_id);
08bad2b1 1323 }
44560457 1324
e506b6e5 1325 if (isset($fwduid)) {
1326//FIXME: DON'T ECHO HTML FROM CORE!
1327 echo addHidden('fwduid', $fwduid);
1328 }
1329
9c3e6cd4 1330 if ($saved_draft == 'yes') {
774d79cc 1331 $oTemplate->assign('note', _("Your draft has been saved."));
762853f4 1332 $oTemplate->display('note.tpl');
9c3e6cd4 1333 }
1334 if ($mail_sent == 'yes') {
774d79cc 1335 $oTemplate->assign('note', _("Your mail has been sent."));
762853f4 1336 $oTemplate->display('note.tpl');
9c3e6cd4 1337 }
9c3e6cd4 1338 if ($compose_new_win == '1') {
762853f4 1339 $oTemplate->display('compose_newwin_close.tpl');
9c3e6cd4 1340 }
1638beb6 1341
78a35fcd 1342 if ($location_of_buttons == 'top') {
c8dc86c9 1343//FIXME: DON'T ECHO HTML FROM CORE!
78a35fcd 1344 showComposeButtonRow();
1345 }
48985d59 1346
762853f4 1347 $identities = array();
1e2a6ff6 1348 if (count($idents) > 1) {
762853f4 1349 reset($idents);
73ad81bf 1350 foreach($idents as $id => $data) {
762853f4 1351 $identities[$id] = $data['full_name'].' &lt;'.$data['email_address'].'&gt;';
73ad81bf 1352 }
762853f4 1353 }
1638beb6 1354
762853f4 1355 $oTemplate->assign('identities', $identities);
1356 $oTemplate->assign('identity_def', $identity);
1357 $oTemplate->assign('input_onfocus', 'onfocus="'.join(' ', $onfocus_array).'"');
1638beb6 1358
3047e291 1359 $oTemplate->assign('to', sm_encode_html_special_chars($send_to));
1360 $oTemplate->assign('cc', sm_encode_html_special_chars($send_to_cc));
1361 $oTemplate->assign('bcc', sm_encode_html_special_chars($send_to_bcc));
1362 $oTemplate->assign('subject', sm_encode_html_special_chars($subject));
1638beb6 1363
8949acd6 1364 // access keys...
1365 //
1366 global $accesskey_compose_to, $accesskey_compose_cc,
5f20677e 1367 $accesskey_compose_identity, $accesskey_compose_bcc,
1368 $accesskey_compose_subject;
1369 $oTemplate->assign('accesskey_compose_identity', $accesskey_compose_identity);
8949acd6 1370 $oTemplate->assign('accesskey_compose_to', $accesskey_compose_to);
1371 $oTemplate->assign('accesskey_compose_cc', $accesskey_compose_cc);
1372 $oTemplate->assign('accesskey_compose_bcc', $accesskey_compose_bcc);
1373 $oTemplate->assign('accesskey_compose_subject', $accesskey_compose_subject);
1374
762853f4 1375 $oTemplate->display('compose_header.tpl');
48985d59 1376
78a35fcd 1377 if ($location_of_buttons == 'between') {
c8dc86c9 1378//FIXME: DON'T ECHO HTML FROM CORE!
78a35fcd 1379 showComposeButtonRow();
1380 }
4dfb9db7 1381
762853f4 1382 $body_str = '';
48985d59 1383 if ($use_signature == true && $newmail == true && !isset($from_htmladdr_search)) {
1e2a6ff6 1384 $signature = $idents[$identity]['signature'];
d3c13a51 1385
3b17e952 1386 if ($sig_first == '1') {
50706f77 1387 /*
1388 * FIXME: test is specific to ja_JP translation implementation.
1389 * This test might apply incorrect conversion to other translations, but
91c27aee 1390 * use of 7bit iso-2022-jp charset in other translations might have other
50706f77 1391 * issues too.
1392 */
ab4700c3 1393 if ($default_charset == 'iso-2022-jp') {
762853f4 1394 $body_str = "\n\n".($prefix_sig==true? "-- \n":'').mb_convert_encoding($signature, 'EUC-JP');
83be314a 1395 } else {
762853f4 1396 $body_str = "\n\n".($prefix_sig==true? "-- \n":'').decodeHeader($signature,false,false);
83be314a 1397 }
3047e291 1398 $body_str .= "\n\n".sm_encode_html_special_chars(decodeHeader($body,false,false));
762853f4 1399 } else {
3047e291 1400 $body_str = "\n\n".sm_encode_html_special_chars(decodeHeader($body,false,false));
50706f77 1401 // FIXME: test is specific to ja_JP translation implementation. See above comments.
ab4700c3 1402 if ($default_charset == 'iso-2022-jp') {
762853f4 1403 $body_str .= "\n\n".($prefix_sig==true? "-- \n":'').mb_convert_encoding($signature, 'EUC-JP');
1404 } else {
1405 $body_str .= "\n\n".($prefix_sig==true? "-- \n":'').decodeHeader($signature,false,false);
73ad81bf 1406 }
3b17e952 1407 }
73ad81bf 1408 } else {
3047e291 1409 $body_str = sm_encode_html_special_chars(decodeHeader($body,false,false));
48985d59 1410 }
12a0ed01 1411
762853f4 1412 $oTemplate->assign('editor_width', (int)$editor_size);
1413 $oTemplate->assign('editor_height', (int)$editor_height);
1414 $oTemplate->assign('input_onfocus', 'onfocus="'.join(' ', $onfocus_array).'"');
1415 $oTemplate->assign('body', $body_str);
1416 $oTemplate->assign('show_bottom_send', $location_of_buttons!='bottom');
1638beb6 1417
8949acd6 1418 // access keys...
1419 //
1420 global $accesskey_compose_body, $accesskey_compose_send;
1421 $oTemplate->assign('accesskey_compose_body', $accesskey_compose_body);
1422 $oTemplate->assign('accesskey_compose_send', $accesskey_compose_send);
1423
762853f4 1424 $oTemplate->display ('compose_body.tpl');
1638beb6 1425
48985d59 1426 if ($location_of_buttons == 'bottom') {
c8dc86c9 1427//FIXME: DON'T ECHO HTML FROM CORE!
48985d59 1428 showComposeButtonRow();
48985d59 1429 }
46bb8da8 1430
f8eb968d 1431 // composeMessage can be empty when coming from a restored session
1432 if (is_object($composeMessage) && $composeMessage->entities)
1433 $attach_array = $composeMessage->entities;
1434 if ($session_expired && !empty($attachments) && is_array($attachments))
1435 $attach_array = $attachments;
1436
48985d59 1437 /* This code is for attachments */
73ad81bf 1438 if ((bool) ini_get('file_uploads')) {
1439
1440 /* Calculate the max size for an uploaded file.
1441 * This is advisory for the user because we can't actually prevent
1442 * people to upload too large files. */
1443 $sizes = array();
1444 /* php.ini vars which influence the max for uploads */
1445 $configvars = array('post_max_size', 'memory_limit', 'upload_max_filesize');
1446 foreach($configvars as $var) {
4f21ba00 1447 /* skip 0 or empty values, and -1 which means 'unlimited' */
73ad81bf 1448 if( $size = getByteSize(ini_get($var)) ) {
4f21ba00 1449 if ( $size != '-1' ) {
1450 $sizes[] = $size;
1451 }
73ad81bf 1452 }
0a2c3218 1453 }
0a2c3218 1454
762853f4 1455 $attach = array();
1f270d3c 1456 global $username, $attachment_dir;
1457 $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
f8eb968d 1458 if (!empty($attach_array)) {
1459 foreach ($attach_array as $key => $attachment) {
73ad81bf 1460 $attached_file = $attachment->att_local_name;
1461 if ($attachment->att_local_name || $attachment->body_part) {
1462 $attached_filename = decodeHeader($attachment->mime_header->getParameter('name'));
1463 $type = $attachment->mime_header->type0.'/'.
a91189d6 1464 $attachment->mime_header->type1;
1638beb6 1465
762853f4 1466 $a = array();
1467 $a['Key'] = $key;
1468 $a['FileName'] = $attached_filename;
1469 $a['ContentType'] = $type;
1f270d3c 1470 $a['Size'] = filesize($hashed_attachment_dir . '/' . $attached_file);
762853f4 1471 $attach[$key] = $a;
73ad81bf 1472 }
1473 }
4dfb9db7 1474 }
1638beb6 1475
762853f4 1476 $max = min($sizes);
1477 $oTemplate->assign('max_file_size', empty($max) ? -1 : $max);
1478 $oTemplate->assign('attachments', $attach);
1638beb6 1479
8949acd6 1480 // access keys...
1481 //
1482 global $accesskey_compose_attach_browse, $accesskey_compose_attach,
1483 $accesskey_compose_delete_attach;
1484 $oTemplate->assign('accesskey_compose_attach_browse', $accesskey_compose_attach_browse);
1485 $oTemplate->assign('accesskey_compose_attach', $accesskey_compose_attach);
1486 $oTemplate->assign('accesskey_compose_delete_attach', $accesskey_compose_delete_attach);
1487
762853f4 1488 $oTemplate->display('compose_attachments.tpl');
73ad81bf 1489 } // End of file_uploads if-block
41b94d65 1490 /* End of attachment code */
762853f4 1491
253ad942 1492 $oTemplate->assign('username', $username);
1493 $oTemplate->assign('smaction', $action);
1494 $oTemplate->assign('mailbox', $mailbox);
953fa718 1495 sqgetGlobalVar('QUERY_STRING', $queryString, SQ_SERVER);
253ad942 1496 $oTemplate->assign('querystring', $queryString);
1497 $oTemplate->assign('composesession', $composesession);
1498 $oTemplate->assign('send_button_count', unique_widget_name('send', TRUE));
1499 if (!empty($attach_array))
1500 $oTemplate->assign('attachments', urlencode(serialize($attach_array)));
1501
1502 $aUserNotices = array();
1503
1504 // File uploads are off, so we didn't show that part of the form.
1505 // To avoid bogus bug reports, tell the user why.
a64f47e7 1506 if (!(bool) ini_get('file_uploads')) {
253ad942 1507 $aUserNotices[] = _("Because PHP file uploads are turned off, you can not attach files to this message. Please see your system administrator for details.");
a64f47e7 1508 }
1509
253ad942 1510 $oTemplate->assign('user_notices', $aUserNotices);
1511
1512 $oTemplate->display('compose_form_close.tpl');
1513
762853f4 1514 if ($compose_new_win=='1') {
1515 $oTemplate->display('compose_newwin_close.tpl');
1516 }
1638beb6 1517
762853f4 1518 $oErrorHandler->setDelayedErrors(false);
5c4ff7bf 1519 $oTemplate->display('footer.tpl');
48985d59 1520}
1521
1522
70c4fd84 1523function showComposeButtonRow() {
78a35fcd 1524 global $use_javascript_addr_book, $save_as_draft,
73ad81bf 1525 $default_use_priority, $mailprio, $default_use_mdn,
1526 $request_mdn, $request_dr,
1527 $data_dir, $username;
70c4fd84 1528
762853f4 1529 global $oTemplate, $buffer_hook;
1638beb6 1530
1531 if ($default_use_priority) {
762853f4 1532 $priorities = array('1'=>_("High"), '3'=>_("Normal"), '5'=>_("Low"));
1533 $priority = isset($mailprio) ? $mailprio : 3;
1534 } else {
1535 $priorities = array();
1536 $priority = NULL;
ae25968c 1537 }
1638beb6 1538
ae25968c 1539 $mdn_user_support=getPref($data_dir, $username, 'mdn_user_support',$default_use_mdn);
48985d59 1540
8949acd6 1541 $address_book_button_attribs = array();
1542 global $accesskey_compose_addresses;
1543 if ($accesskey_compose_addresses != 'NONE')
1544 $address_book_button_attribs['accesskey'] = $accesskey_compose_addresses;
c40a269e 1545 if ($use_javascript_addr_book && checkForJavascript()) {
8949acd6 1546 $addr_book = addButton(_("Addresses"),
1547 null,
1548 array_merge($address_book_button_attribs, array('onclick' => 'javascript:open_abook();')));
734f4ee6 1549 } else {
8949acd6 1550 $addr_book = addSubmit(_("Addresses"), 'html_addr_search', $address_book_button_attribs);
78a35fcd 1551 }
48985d59 1552
762853f4 1553 $oTemplate->assign('allow_priority', $default_use_priority==1);
1554 $oTemplate->assign('priority_list', $priorities);
1555 $oTemplate->assign('current_priority', $priority);
1638beb6 1556
762853f4 1557 $oTemplate->assign('notifications_enabled', $mdn_user_support==1);
1558 $oTemplate->assign('read_receipt', $request_mdn=='1');
1559 $oTemplate->assign('delivery_receipt', $request_dr=='1');
1638beb6 1560
762853f4 1561 $oTemplate->assign('drafts_enabled', $save_as_draft);
1562 $oTemplate->assign('address_book_button', $addr_book);
441f2d33 1563
8949acd6 1564 // access keys...
1565 //
1566 global $accesskey_compose_priority, $accesskey_compose_on_read,
1567 $accesskey_compose_on_delivery, $accesskey_compose_signature,
1568 $accesskey_compose_save_draft, $accesskey_compose_send;
1569 $oTemplate->assign('accesskey_compose_priority', $accesskey_compose_priority);
1570 $oTemplate->assign('accesskey_compose_on_read', $accesskey_compose_on_read);
1571 $oTemplate->assign('accesskey_compose_on_delivery', $accesskey_compose_on_delivery);
1572 $oTemplate->assign('accesskey_compose_signature', $accesskey_compose_signature);
1573 $oTemplate->assign('accesskey_compose_save_draft', $accesskey_compose_save_draft);
1574 $oTemplate->assign('accesskey_compose_send', $accesskey_compose_send);
1575
762853f4 1576 $oTemplate->display('compose_buttons.tpl');
78a35fcd 1577}
b278172f 1578
70c4fd84 1579function checkInput ($show) {
78a35fcd 1580 /*
1581 * I implemented the $show variable because the error messages
1582 * were getting sent before the page header. So, I check once
1583 * using $show=false, and then when i'm ready to display the error
1584 * message, show=true
1585 */
1356041d 1586 global $send_to, $send_to_cc, $send_to_bcc;
78a35fcd 1587
1356041d 1588 $send_to = trim($send_to);
1589 $send_to_cc = trim($send_to_cc);
1590 $send_to_bcc = trim($send_to_bcc);
1591 if (empty($send_to) && empty($send_to_cc) && empty($send_to_bcc)) {
78a35fcd 1592 if ($show) {
cb34dbd0 1593 plain_error_message(_("You have not filled in the \"To:\" field."));
78a35fcd 1594 }
1595 return false;
1596 }
1597 return true;
1598} /* function checkInput() */
df15de21 1599
3806fa52 1600
00793a25 1601/* True if FAILURE */
da95c4b6 1602function saveAttachedFiles($session) {
b4e7df34 1603 global $composeMessage, $username, $attachment_dir;
bfa54da7 1604
45cdd1b5 1605 /* get out of here if no file was attached at all */
1606 if (! is_uploaded_file($_FILES['attachfile']['tmp_name']) ) {
1607 return true;
1608 }
1609
1f270d3c 1610 $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
628bce99 1611 $localfilename = sq_get_attach_tempfile();
1f270d3c 1612 $fullpath = $hashed_attachment_dir . '/' . $localfilename;
4c9d2242 1613
a42c236f 1614 // m_u_f works better with restricted PHP installs (safe_mode, open_basedir),
1615 // if that doesn't work, try a simple rename.
8442ecb9 1616 if (!sq_call_function_suppress_errors('move_uploaded_file', array($_FILES['attachfile']['tmp_name'], $fullpath))) {
1617 if (!sq_call_function_suppress_errors('rename', array($_FILES['attachfile']['tmp_name'], $fullpath))) {
73ad81bf 1618 return true;
1619 }
a61878d0 1620 }
0b97a708 1621 $type = strtolower($_FILES['attachfile']['type']);
1622 $name = $_FILES['attachfile']['name'];
b4e7df34 1623 $composeMessage->initAttachment($type, $name, $localfilename);
4c9d2242 1624}
1625
5fe7d683 1626/**
1627 * Parse strings such as "8M" and "2k" into their corresponding size in bytes
1628 *
1629 * NOTE: This function only recognizes the suffixes "K", "M" and "G"
1630 * and will probably break very easily if the given size is in
1631 * some completely different format.
1632 *
1633 * @param string $ini_size The input string to be converted
1634 *
1635 * @return mixed Boolean FALSE if something went wrong (the value passed in
1636 * was empty?, the suffix was not recognized?), otherwise, the
1637 * converted size in bytes (just the number (as an integer),
1638 * no unit identifier included)
1639 *
1640 */
0a2c3218 1641function getByteSize($ini_size) {
1642
4d30dc83 1643 if(!$ini_size) {
1644 return FALSE;
1645 }
da95c4b6 1646
0a2c3218 1647 $ini_size = trim($ini_size);
1648
5b9716de 1649 // if there's some kind of letter at the end of the string we need to multiply.
1650 if(!is_numeric(substr($ini_size, -1))) {
1651
1652 switch(strtoupper(substr($ini_size, -1))) {
1653 case 'G':
73ad81bf 1654 $bytesize = 1073741824;
1655 break;
5b9716de 1656 case 'M':
73ad81bf 1657 $bytesize = 1048576;
1658 break;
5b9716de 1659 case 'K':
73ad81bf 1660 $bytesize = 1024;
1661 break;
5fe7d683 1662 default:
1663 return FALSE;
5b9716de 1664 }
1665
4d30dc83 1666 return ($bytesize * (int)substr($ini_size, 0, -1));
0a2c3218 1667 }
1c044820 1668
4d30dc83 1669 return $ini_size;
0a2c3218 1670}
a43e4b90 1671
4c9d2242 1672
50706f77 1673/**
1674 * temporary function to make use of the deliver class.
a42c236f 1675 * In the future the responsible backend should be automaticly loaded
50706f77 1676 * and conf.pl should show a list of available backends.
1677 * The message also should be constructed by the message class.
b67d61ee 1678 *
10adeb76 1679 * @param object $composeMessage The message being sent. Please note
1680 * that it is passed by reference and
1681 * will be returned modified, with additional
1682 * headers, such as Message-ID, Date, In-Reply-To,
1683 * References, and so forth.
1684 *
b67d61ee 1685 * @return boolean FALSE if delivery failed, or some non-FALSE value
1686 * upon success.
1687 *
73ad81bf 1688 */
10adeb76 1689function deliverMessage(&$composeMessage, $draft=false) {
a43e4b90 1690 global $send_to, $send_to_cc, $send_to_bcc, $mailprio, $subject, $body,
10adeb76 1691 $username, $identity, $idents, $data_dir,
856e58ef 1692 $request_mdn, $request_dr, $default_charset, $useSendmail,
1693 $domain, $action, $default_move_to_sent, $move_to_sent,
a9805897 1694 $imapServerAddress, $imapPort, $imap_stream_options, $sent_folder, $key;
a43e4b90 1695
1696 $rfc822_header = $composeMessage->rfc822_header;
24192f77 1697
1698 $abook = addressbook_init(false, true);
310dfeb6 1699 $rfc822_header->to = $rfc822_header->parseAddress($send_to,true, array(), '', $domain, array(&$abook,'lookup'));
1700 $rfc822_header->cc = $rfc822_header->parseAddress($send_to_cc,true,array(), '',$domain, array(&$abook,'lookup'));
1701 $rfc822_header->bcc = $rfc822_header->parseAddress($send_to_bcc,true, array(), '',$domain, array(&$abook,'lookup'));
a43e4b90 1702 $rfc822_header->priority = $mailprio;
1703 $rfc822_header->subject = $subject;
310dfeb6 1704
a43e4b90 1705 $special_encoding='';
1706 if (strtolower($default_charset) == 'iso-2022-jp') {
1707 if (mb_detect_encoding($body) == 'ASCII') {
a91189d6 1708 $special_encoding = '8bit';
a43e4b90 1709 } else {
1710 $body = mb_convert_encoding($body, 'JIS');
1711 $special_encoding = '7bit';
1712 }
1713 }
1714 $composeMessage->setBody($body);
1715
a43e4b90 1716 $reply_to = '';
1e2a6ff6 1717 $reply_to = $idents[$identity]['reply_to'];
52ead32b 1718 if ($reply_to && strpos($reply_to, '@') === FALSE)
8b213268 1719 $reply_to .= '@' . $domain;
40e07136 1720
1721 $from_addr = build_from_header($identity);
1722 $rfc822_header->from = $rfc822_header->parseAddress($from_addr,true);
a43e4b90 1723 if ($reply_to) {
73ad81bf 1724 $rfc822_header->reply_to = $rfc822_header->parseAddress($reply_to,true);
a43e4b90 1725 }
1726 /* Receipt: On Read */
1727 if (isset($request_mdn) && $request_mdn) {
40e07136 1728 $rfc822_header->dnt = $rfc822_header->parseAddress($from_addr,true);
762853f4 1729 } elseif (isset($rfc822_header->dnt)) {
1730 unset($rfc822_header->dnt);
a43e4b90 1731 }
1638beb6 1732
a43e4b90 1733 /* Receipt: On Delivery */
657fe1bd 1734 if (!empty($request_dr)) {
1735//FIXME: it would be better to fiddle with headers inside of the message object or possibly when delivering the message to its destination; is this possible?
cc51047f 1736 $rfc822_header->more_headers['Return-Receipt-To'] = $from_addr;
762853f4 1737 } elseif (isset($rfc822_header->more_headers['Return-Receipt-To'])) {
1738 unset($rfc822_header->more_headers['Return-Receipt-To']);
a43e4b90 1739 }
762853f4 1740
a43e4b90 1741 /* multipart messages */
1742 if (count($composeMessage->entities)) {
1743 $message_body = new Message();
a91189d6 1744 $message_body->body_part = $composeMessage->body_part;
1745 $composeMessage->body_part = '';
1746 $mime_header = new MessageHeader;
1747 $mime_header->type0 = 'text';
1748 $mime_header->type1 = 'plain';
1749 if ($special_encoding) {
1750 $mime_header->encoding = $special_encoding;
1c044820 1751 } else {
12a0ed01 1752 $mime_header->encoding = '8bit';
a91189d6 1753 }
1754 if ($default_charset) {
1755 $mime_header->parameters['charset'] = $default_charset;
1756 }
1c044820 1757 $message_body->mime_header = $mime_header;
a43e4b90 1758 array_unshift($composeMessage->entities, $message_body);
a91189d6 1759 $content_type = new ContentType('multipart/mixed');
a43e4b90 1760 } else {
1e2026df 1761 $content_type = new ContentType('text/plain');
1762 if ($special_encoding) {
1763 $rfc822_header->encoding = $special_encoding;
1c044820 1764 } else {
1e2026df 1765 $rfc822_header->encoding = '8bit';
1c044820 1766 }
426e0b72 1767 if ($default_charset) {
1768 $content_type->properties['charset']=$default_charset;
73ad81bf 1769 }
181538ac 1770 }
1c044820 1771
a43e4b90 1772 $rfc822_header->content_type = $content_type;
1773 $composeMessage->rfc822_header = $rfc822_header;
0fdb0aa1 1774 if ($action == 'reply' || $action == 'reply_all') {
1775 global $passed_id, $passed_ent_id;
1776 $reply_id = $passed_id;
1777 $reply_ent_id = $passed_ent_id;
1778 } else {
1779 $reply_id = '';
1780 $reply_ent_id = '';
1781 }
1638beb6 1782
1c044820 1783 /* Here you can modify the message structure just before we hand
6e515418 1784 it over to deliver; plugin authors note that $composeMessage
1785 is sent and modified by reference since 1.5.2 */
1786 do_hook('compose_send', $composeMessage);
66540988 1787//TODO: need to migrate to the following, but it neessitates changes in existing plugins, since the args are now an array
1788 //$temp = array(&$composeMessage, &$draft);
1789 //do_hook('compose_send', $temp);
a43e4b90 1790
b48d3c53 1791 if (!$useSendmail && !$draft) {
a91189d6 1792 require_once(SM_PATH . 'class/deliver/Deliver_SMTP.class.php');
1793 $deliver = new Deliver_SMTP();
a9805897 1794 global $smtpServerAddress, $smtpPort, $smtp_stream_options, $pop_before_smtp, $pop_before_smtp_host;
a91189d6 1795
a91189d6 1796 $authPop = (isset($pop_before_smtp) && $pop_before_smtp) ? true : false;
783e926e 1797 if (empty($pop_before_smtp_host)) $pop_before_smtp_host = $smtpServerAddress;
9bd3b1e6 1798 get_smtp_user($user, $pass);
a91189d6 1799 $stream = $deliver->initStream($composeMessage,$domain,0,
a9805897 1800 $smtpServerAddress, $smtpPort, $user, $pass, $authPop, $pop_before_smtp_host, $smtp_stream_options);
b48d3c53 1801 } elseif (!$draft) {
73ad81bf 1802 require_once(SM_PATH . 'class/deliver/Deliver_SendMail.class.php');
fd7ab795 1803 global $sendmail_path, $sendmail_args;
f3dc9c62 1804 // Check for outdated configuration
1805 if (!isset($sendmail_args)) {
1806 if ($sendmail_path=='/var/qmail/bin/qmail-inject') {
1807 $sendmail_args = '';
1808 } else {
1809 $sendmail_args = '-i -t';
1810 }
1811 }
fd7ab795 1812 $deliver = new Deliver_SendMail(array('sendmail_args'=>$sendmail_args));
73ad81bf 1813 $stream = $deliver->initStream($composeMessage,$sendmail_path);
b48d3c53 1814 } elseif ($draft) {
73ad81bf 1815 global $draft_folder;
906f7e9f 1816 $imap_stream = sqimap_login($username, false, $imapServerAddress,
a9805897 1817 $imapPort, 0, $imap_stream_options);
73ad81bf 1818 if (sqimap_mailbox_exists ($imap_stream, $draft_folder)) {
1819 require_once(SM_PATH . 'class/deliver/Deliver_IMAP.class.php');
1820 $imap_deliver = new Deliver_IMAP();
a90d951c 1821 $success = $imap_deliver->mail($composeMessage, $imap_stream, $reply_id, $reply_ent_id, $imap_stream, $draft_folder);
73ad81bf 1822 sqimap_logout($imap_stream);
1823 unset ($imap_deliver);
c077ffeb 1824 $composeMessage->purgeAttachments();
b67d61ee 1825 return $success;
4dfb9db7 1826 } else {
3047e291 1827 $msg = '<br />'.sprintf(_("Error: Draft folder %s does not exist."), sm_encode_html_special_chars($draft_folder));
cb34dbd0 1828 plain_error_message($msg);
73ad81bf 1829 return false;
a91189d6 1830 }
a43e4b90 1831 }
0c59bbe1 1832 $success = false;
a43e4b90 1833 if ($stream) {
10adeb76 1834 $deliver->mail($composeMessage, $stream, $reply_id, $reply_ent_id);
0c59bbe1 1835 $success = $deliver->finalizeStream($stream);
a43e4b90 1836 }
0c59bbe1 1837 if (!$success) {
fd7ab795 1838 // $deliver->dlv_server_msg is not always server's reply
32433689 1839 $msg = _("Message not sent.")
1840 . "<br />\n"
1841 . (isset($deliver->dlv_msg) ? $deliver->dlv_msg : '');
a15f9d93 1842 if (!empty($deliver->dlv_server_msg)) {
1843 // add 'server replied' part only when it is not empty.
1844 // Delivery error can be generated by delivery class itself
32433689 1845 $msg .= '<br />'
1846 . _("Server replied:") . ' '
1847 . (isset($deliver->dlv_ret_nr) ? $deliver->dlv_ret_nr . ' ' : '')
3047e291 1848 . nl2br(sm_encode_html_special_chars($deliver->dlv_server_msg));
a15f9d93 1849 }
cb34dbd0 1850 plain_error_message($msg);
a43e4b90 1851 } else {
1852 unset ($deliver);
a9805897 1853 $imap_stream = sqimap_login($username, false, $imapServerAddress, $imapPort, 0, $imap_stream_options);
e4a1f097 1854
8780308f 1855
414303b8 1856 // mark as replied or forwarded if applicable
1857 //
e506b6e5 1858 global $what, $iAccount, $startMessage, $passed_id, $fwduid, $mailbox;
8780308f 1859
bc29bf70 1860 if ($action=='reply' || $action=='reply_all' || $action=='forward' || $action=='forward_as_attachment') {
202bcbcc 1861 require(SM_PATH . 'functions/mailbox_display.php');
8780308f 1862 $aMailbox = sqm_api_mailbox_select($imap_stream, $iAccount, $mailbox,array('setindex' => $what, 'offset' => $startMessage),array());
bc29bf70 1863 switch($action) {
1864 case 'reply':
1865 case 'reply_all':
1866 // check if we are allowed to set the \\Answered flag
1867 if (in_array('\\answered',$aMailbox['PERMANENTFLAGS'], true)) {
1868 $aUpdatedMsgs = sqimap_toggle_flag($imap_stream, array($passed_id), '\\Answered', true, false);
1869 if (isset($aUpdatedMsgs[$passed_id]['FLAGS'])) {
1870 /**
1871 * Only update the cached headers if the header is
1872 * cached.
1873 */
1874 if (isset($aMailbox['MSG_HEADERS'][$passed_id])) {
1875 $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS'] = $aMsg['FLAGS'];
1876 }
1877 }
1878 }
1879 break;
1880 case 'forward':
1881 case 'forward_as_attachment':
1882 // check if we are allowed to set the $Forwarded flag (RFC 4550 paragraph 2.8)
1638beb6 1883 if (in_array('$forwarded',$aMailbox['PERMANENTFLAGS'], true) ||
bc29bf70 1884 in_array('\\*',$aMailbox['PERMANENTFLAGS'])) {
1885
e506b6e5 1886 // when forwarding as an attachment from the message
1887 // list, passed_id is not used, need to get UID(s)
1888 // from the query string
1889 //
1890 if (empty($passed_id) && !empty($fwduid))
1891 $ids = explode('_', $fwduid);
1892 else
1893 $ids = array($passed_id);
1894
1895 $aUpdatedMsgs = sqimap_toggle_flag($imap_stream, $ids, '$Forwarded', true, false);
1896
1897 foreach ($ids as $id) {
1898 if (isset($aUpdatedMsgs[$id]['FLAGS'])) {
1899 if (isset($aMailbox['MSG_HEADERS'][$id])) {
1900 $aMailbox['MSG_HEADERS'][$id]['FLAGS'] = $aMsg['FLAGS'];
1901 }
bc29bf70 1902 }
bda07b93 1903 }
8780308f 1904 }
bc29bf70 1905 break;
8780308f 1906 }
bc29bf70 1907
4d1cb59a 1908 /**
1909 * Write mailbox with updated seen flag information back to cache.
1910 */
bc29bf70 1911 if(isset($aUpdatedMsgs[$passed_id])) {
1912 $mailbox_cache[$iAccount.'_'.$aMailbox['NAME']] = $aMailbox;
1913 sqsession_register($mailbox_cache,'mailbox_cache');
1914 }
1915
a91189d6 1916 }
414303b8 1917
1918
1919 // move to sent folder
1920 //
1921 $move_to_sent = getPref($data_dir,$username,'move_to_sent');
1922 if (isset($default_move_to_sent) && ($default_move_to_sent != 0)) {
1923 $svr_allow_sent = true;
1924 } else {
1925 $svr_allow_sent = false;
1926 }
1927
1928 if (isset($sent_folder) && (($sent_folder != '') || ($sent_folder != 'none'))
1929 && sqimap_mailbox_exists( $imap_stream, $sent_folder)) {
1930 $fld_sent = true;
1931 } else {
1932 $fld_sent = false;
1933 }
1934
1935 if ((isset($move_to_sent) && ($move_to_sent != 0)) || (!isset($move_to_sent))) {
1936 $lcl_allow_sent = true;
1937 } else {
1938 $lcl_allow_sent = false;
1939 }
1940
1941 if (($fld_sent && $svr_allow_sent && !$lcl_allow_sent) || ($fld_sent && $lcl_allow_sent)) {
1942 if ($action == 'reply' || $action == 'reply_all') {
1943 $save_reply_with_orig=getPref($data_dir,$username,'save_reply_with_orig');
1944 if ($save_reply_with_orig) {
1945 $sent_folder = $mailbox;
1946 }
1947 }
414303b8 1948 require_once(SM_PATH . 'class/deliver/Deliver_IMAP.class.php');
1949 $imap_deliver = new Deliver_IMAP();
33f0da43 1950 $imap_deliver->mail($composeMessage, $imap_stream, $reply_id, $reply_ent_id, $imap_stream, $sent_folder);
414303b8 1951 unset ($imap_deliver);
1952 }
1953
1954
1955 // final cleanup
1956 //
1957 $composeMessage->purgeAttachments();
1958 sqimap_logout($imap_stream);
1959
a43e4b90 1960 }
0c59bbe1 1961 return $success;
a43e4b90 1962}