Add ability for saved drafts to indicate if they are a reply or forward and if so...
[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);
aff28a6d 929 if (!empty($orig_header->x_sm_flag_reply))
930 $composeMessage->rfc822_header->more_headers['X-SM-Flag-Reply'] = $orig_header->x_sm_flag_reply;
041d360b 931//TODO: completely unclear if should be using $compose_session instead of $session below
932 $compose_messages[$session] = $composeMessage;
933 sqsession_register($compose_messages,'compose_messages');
73ad81bf 934 break;
935 case ('edit_as_new'):
936 $send_to = decodeHeader($orig_header->getAddr_s('to'),false,false,true);
937 $send_to_cc = decodeHeader($orig_header->getAddr_s('cc'),false,false,true);
938 $send_to_bcc = decodeHeader($orig_header->getAddr_s('bcc'),false,false,true);
939 $subject = decodeHeader($orig_header->subject,false,false,true);
940 $mailprio = $orig_header->priority;
941 $orig_from = '';
942 $composeMessage = getAttachments($message, $composeMessage, $passed_id, $entities, $imapConnection);
943 // rewrap the body to clean up quotations and line lengths
944 sqBodyWrap($body, $editor_size);
945 break;
946 case ('forward'):
947 $send_to = '';
948 $subject = getforwardSubject(decodeHeader($orig_header->subject,false,false,true));
949 $body = getforwardHeader($orig_header) . $body;
950 // the logic for calling sqUnWordWrap here would be to allow the browser to wrap the lines
951 // forwarded message text should be as undisturbed as possible, so commenting out this call
952 // sqUnWordWrap($body);
953 $composeMessage = getAttachments($message, $composeMessage, $passed_id, $entities, $imapConnection);
91c27aee 954
73ad81bf 955 //add a blank line after the forward headers
956 $body = "\n" . $body;
957 break;
958 case ('forward_as_attachment'):
959 $subject = getforwardSubject(decodeHeader($orig_header->subject,false,false,true));
960 $composeMessage = getMessage_RFC822_Attachment($message, $composeMessage, $passed_id, $passed_ent_id, $imapConnection);
f2ad47f1 961 $subject = decodeHeader($orig_header->subject,false,false,true);
962 $subject = str_replace('"', "'", $subject);
963 $subject = trim($subject);
964 if (substr(strtolower($subject), 0, 4) != 'fwd:') {
965 $subject = 'Fwd: ' . $subject;
966 }
73ad81bf 967 $body = '';
968 break;
969 case ('reply_all'):
970 if(isset($orig_header->mail_followup_to) && $orig_header->mail_followup_to) {
971 $send_to = $orig_header->getAddr_s('mail_followup_to');
b268e66b 972 } else {
73ad81bf 973 $send_to_cc = replyAllString($orig_header);
974 $send_to_cc = decodeHeader($send_to_cc,false,false,true);
a9b9e5d3 975 $send_to_cc = str_replace('""', '"', $send_to_cc);
b268e66b 976 }
73ad81bf 977 case ('reply'):
978 // skip this if send_to was already set right above here
979 if(!$send_to) {
980 $send_to = $orig_header->reply_to;
981 if (is_array($send_to) && count($send_to)) {
a9b9e5d3 982 $send_to = $orig_header->getAddr_s('reply_to', ',', FALSE, TRUE);
73ad81bf 983 } else if (is_object($send_to)) { /* unneccesarry, just for failsafe purpose */
a9b9e5d3 984 $send_to = $orig_header->getAddr_s('reply_to', ',', FALSE, TRUE);
73ad81bf 985 } else {
a9b9e5d3 986 $send_to = $orig_header->getAddr_s('from', ',', FALSE, TRUE);
73ad81bf 987 }
dd4a44cd 988 }
73ad81bf 989 $send_to = decodeHeader($send_to,false,false,true);
a9b9e5d3 990 $send_to = str_replace('""', '"', $send_to);
ace75dcb 991
992
993 // If user doesn't want replies to her own messages
994 // going back to herself (instead send again to the
995 // original recipient of the message being replied to),
996 // then iterate through identities, checking if the TO
997 // field is one of them (if the reply is to ourselves)
998 //
999 // Note we don't bother if the original message doesn't
1000 // have anything in the TO field itself (because that's
1001 // what we use if we change the recipient to be that of
1002 // the previous message)
1003 //
1004 if ($do_not_reply_to_self && !empty($orig_header->to)) {
1005
1006 $orig_to = '';
1007
1008 foreach($idents as $id) {
1009
1010 if (!empty($id['email_address'])
1011 && strpos($send_to, $id['email_address']) !== FALSE) {
1012
1013 // if this is a reply-all, the original recipient
1014 // is already in the CC field, so we can just blank
1015 // the recipient (TO field) (as long as the CC field
a9b6e52d 1016 // isn't empty that is)... but then move the CC into
1017 // the TO, so TO isn't empty
ace75dcb 1018 //
6fac6196 1019 if ($action == 'reply_all' && !empty($send_to_cc)) {
a9b6e52d 1020 $orig_to = $send_to_cc;
1021 $send_to_cc = '';
ace75dcb 1022 break;
1023 }
1024
1025 $orig_to = $orig_header->to;
1026 if (is_array($orig_to) && count($orig_to)) {
1027 $orig_to = $orig_header->getAddr_s('to', ',', FALSE, TRUE);
1028 } else if (is_object($orig_to)) { /* unneccesarry, just for failsafe purpose */
1029 $orig_to = $orig_header->getAddr_s('to', ',', FALSE, TRUE);
1030 } else {
1031 $orig_to = '';
1032 }
1033 $orig_to = decodeHeader($orig_to,false,false,true);
1034 $orig_to = str_replace('""', '"', $orig_to);
1035
1036 break;
1037 }
1038 }
1039
1040 // if the reply was addressed back to ourselves,
5df2efa2 1041 // we will send it to the TO of the previous message
ace75dcb 1042 //
1043 if (!empty($orig_to)) {
1044
5df2efa2 1045 $send_to = $orig_to;
5777c73d 1046
1047 // in this case, we also want to reset the FROM
1048 // identity as well (it should match the original
1049 // *FROM* header instead of TO or CC)
1050 //
1051 if (count($idents) > 1) {
1052 $identity = '';
1053 foreach($idents as $i => $id) {
1054 if (!empty($id['email_address'])
1055 && strpos($orig_from, $id['email_address']) !== FALSE) {
1056 $identity = $i;
1057 break;
1058 }
1059 }
1060 }
1061
ace75dcb 1062 }
1063
1064 }
1065
1066
73ad81bf 1067 $subject = decodeHeader($orig_header->subject,false,false,true);
1068 $subject = str_replace('"', "'", $subject);
1069 $subject = trim($subject);
1070 if (substr(strtolower($subject), 0, 3) != 're:') {
1071 $subject = 'Re: ' . $subject;
1072 }
1073 /* this corrects some wrapping/quoting problems on replies */
1074 $rewrap_body = explode("\n", $body);
3aaa3214 1075 $from = (is_array($orig_header->from) && !empty($orig_header->from)) ? $orig_header->from[0] : $orig_header->from;
73ad81bf 1076 $body = '';
1077 $strip_sigs = getPref($data_dir, $username, 'strip_sigs');
1078 foreach ($rewrap_body as $line) {
3673a2de 1079 if ($strip_sigs && rtrim($line, "\r\n") == '-- ') {
73ad81bf 1080 break;
1081 }
1082 if (preg_match("/^(>+)/", $line, $matches)) {
1083 $gt = $matches[1];
1084 $body .= $body_quote . str_replace("\n", "\n$body_quote$gt ", rtrim($line)) ."\n";
1085 } else {
1086 $body .= $body_quote . (!empty($body_quote) ? ' ' : '') . str_replace("\n", "\n$body_quote" . (!empty($body_quote) ? ' ' : ''), rtrim($line)) . "\n";
1087 }
a61878d0 1088 }
c9d61baf 1089
73ad81bf 1090 //rewrap the body to clean up quotations and line lengths
1091 $body = sqBodyWrap ($body, $editor_size);
c9d61baf 1092
73ad81bf 1093 $body = getReplyCitation($from , $orig_header->date) . $body;
1094 $composeMessage->reply_rfc822_header = $orig_header;
12a0ed01 1095
73ad81bf 1096 break;
1097 default:
1098 break;
41b94d65 1099 }
b4e7df34 1100//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 1101 session_write_close();
a61878d0 1102 sqimap_logout($imapConnection);
41b94d65 1103 }
a61878d0 1104 $ret = array( 'send_to' => $send_to,
73ad81bf 1105 'send_to_cc' => $send_to_cc,
1106 'send_to_bcc' => $send_to_bcc,
1107 'subject' => $subject,
1108 'mailprio' => $mailprio,
1109 'body' => $body,
1110 'identity' => $identity );
a61878d0 1111
41b94d65 1112 return ($ret);
48985d59 1113} /* function newMail() */
1114
50706f77 1115/**
1116 * downloads attachments from original message, stores them in attachment directory and adds
1117 * them to composed message.
1118 * @param object $message
1119 * @param object $composeMessage
1120 * @param integer $passed_id
1121 * @param mixed $entities
1122 * @param mixed $imapConnection
91c27aee 1123 * @return object
50706f77 1124 */
a43e4b90 1125function getAttachments($message, &$composeMessage, $passed_id, $entities, $imapConnection) {
1f270d3c 1126 global $squirrelmail_language, $languages, $username, $attachment_dir;
628bce99 1127
1c044820 1128 if (!count($message->entities) ||
73ad81bf 1129 ($message->type0 == 'message' && $message->type1 == 'rfc822')) {
41b94d65 1130 if ( !in_array($message->entity_id, $entities) && $message->entity_id) {
73ad81bf 1131 switch ($message->type0) {
1132 case 'message':
1133 if ($message->type1 == 'rfc822') {
1134 $filename = $message->rfc822_header->subject;
1135 if ($filename == "") {
1136 $filename = "untitled-".$message->entity_id;
1137 }
6f71f6e6 1138 $filename .= '.eml';
73ad81bf 1139 } else {
1140 $filename = $message->getFilename();
181538ac 1141 }
73ad81bf 1142 break;
1143 default:
1144 if (!$message->mime_header) { /* temporary hack */
1145 $message->mime_header = $message->header;
1146 }
1147 $filename = $message->getFilename();
1148 break;
1149 }
117aa0c5 1150//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
1151 $filename = str_replace('&#32;', ' ', decodeHeader($filename, true, true, true));
73ad81bf 1152 if (isset($languages[$squirrelmail_language]['XTRA_CODE']) &&
1153 function_exists($languages[$squirrelmail_language]['XTRA_CODE'] . '_encode')) {
f4bb5d22 1154 $filename = call_user_func($languages[$squirrelmail_language]['XTRA_CODE'] . '_encode', $filename);
73ad81bf 1155 }
1f270d3c 1156
1157 $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
628bce99 1158 $localfilename = sq_get_attach_tempfile();
1159 $message->att_local_name = $localfilename;
73ad81bf 1160
1161 $composeMessage->initAttachment($message->type0.'/'.$message->type1,$filename,
628bce99 1162 $localfilename);
73ad81bf 1163
1164 /* Write Attachment to file */
1f270d3c 1165 $fp = fopen ($hashed_attachment_dir . '/' . $localfilename, 'wb');
91c27aee 1166 mime_print_body_lines ($imapConnection, $passed_id, $message->entity_id, $message->header->encoding, $fp);
73ad81bf 1167 fclose ($fp);
48985d59 1168 }
734f4ee6 1169 } else {
a43e4b90 1170 for ($i=0, $entCount=count($message->entities); $i<$entCount;$i++) {
1171 $composeMessage=getAttachments($message->entities[$i], $composeMessage, $passed_id, $entities, $imapConnection);
48985d59 1172 }
1173 }
a43e4b90 1174 return $composeMessage;
48985d59 1175}
1176
1c044820 1177function getMessage_RFC822_Attachment($message, $composeMessage, $passed_id,
73ad81bf 1178 $passed_ent_id='', $imapConnection) {
756406df 1179 if (!$passed_ent_id) {
1c044820 1180 $body_a = sqimap_run_command($imapConnection,
73ad81bf 1181 'FETCH '.$passed_id.' RFC822',
1182 TRUE, $response, $readmessage,
1183 TRUE);
756406df 1184 } else {
1c044820 1185 $body_a = sqimap_run_command($imapConnection,
73ad81bf 1186 'FETCH '.$passed_id.' BODY['.$passed_ent_id.']',
1187 TRUE, $response, $readmessage, TRUE);
a61878d0 1188 $message = $message->parent;
756406df 1189 }
d0519c03 1190 if ($response == 'OK') {
a61878d0 1191 $subject = encodeHeader($message->rfc822_header->subject);
1192 array_shift($body_a);
1c044820 1193 array_pop($body_a);
a61878d0 1194 $body = implode('', $body_a) . "\r\n";
1c044820 1195
1f270d3c 1196 global $username, $attachment_dir;
1197 $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
628bce99 1198 $localfilename = sq_get_attach_tempfile();
1f270d3c 1199 $fp = fopen($hashed_attachment_dir . '/' . $localfilename, 'wb');
a61878d0 1200 fwrite ($fp, $body);
1201 fclose($fp);
6f71f6e6 1202 $composeMessage->initAttachment('message/rfc822',$subject.'.eml',
628bce99 1203 $localfilename);
a43e4b90 1204 }
1205 return $composeMessage;
a6ec592e 1206}
1207
41b94d65 1208function showInputForm ($session, $values=false) {
856e58ef 1209 global $send_to, $send_to_cc, $send_to_bcc,
f8eb968d 1210 $body, $startMessage, $action, $attachments,
b2b614bb 1211 $use_signature, $signature, $prefix_sig, $session_expired,
8d8da447 1212 $editor_size, $editor_height, $subject, $newmail,
e506b6e5 1213 $use_javascript_addr_book, $passed_id, $mailbox, $fwduid,
73ad81bf 1214 $from_htmladdr_search, $location_of_buttons, $attachment_dir,
ce68b76b 1215 $username, $data_dir, $identity, $idents, $delete_draft,
1216 $mailprio, $compose_new_win, $saved_draft, $mail_sent, $sig_first,
b4e7df34 1217 $composeMessage, $composesession, $default_charset,
762853f4 1218 $compose_onsubmit, $oTemplate, $oErrorHandler;
a43e4b90 1219
87745b9c 1220 if (checkForJavascript()) {
1221 $onfocus = ' onfocus="alreadyFocused=true;"';
1222 $onfocus_array = array('onfocus' => 'alreadyFocused=true;');
1223 }
1224 else {
1225 $onfocus = '';
1226 $onfocus_array = array();
1227 }
1228
41b94d65 1229 if ($values) {
73ad81bf 1230 $send_to = $values['send_to'];
1231 $send_to_cc = $values['send_to_cc'];
1232 $send_to_bcc = $values['send_to_bcc'];
1233 $subject = $values['subject'];
1234 $mailprio = $values['mailprio'];
1235 $body = $values['body'];
1236 $identity = (int) $values['identity'];
676bb189 1237 } else {
73ad81bf 1238 $send_to = decodeHeader($send_to, true, false);
1239 $send_to_cc = decodeHeader($send_to_cc, true, false);
1240 $send_to_bcc = decodeHeader($send_to_bcc, true, false);
41b94d65 1241 }
1c044820 1242
48985d59 1243 if ($use_javascript_addr_book) {
c8dc86c9 1244//FIXME: NO HTML IN CORE!
2c92ea9d 1245 echo "\n". '<script type="text/javascript">'."\n<!--\n" .
73ad81bf 1246 'function open_abook() { ' . "\n" .
1247 ' var nwin = window.open("addrbook_popup.php","abookpopup",' .
1248 '"width=670,height=300,resizable=yes,scrollbars=yes");' . "\n" .
1249 ' if((!nwin.opener) && (document.windows != null))' . "\n" .
1250 ' nwin.opener = document.windows;' . "\n" .
1251 "}\n" .
1252 "// -->\n</script>\n\n";
48985d59 1253 }
1254
c8dc86c9 1255//FIXME: NO HTML IN CORE!
4a1788b3 1256 echo "\n" . '<form name="compose" action="compose.php" method="post" ' .
73ad81bf 1257 'enctype="multipart/form-data"';
a34b07a5 1258
1259 $compose_onsubmit = array();
6e515418 1260 global $null;
1261 do_hook('compose_form', $null);
1c044820 1262
a34b07a5 1263 // Plugins that use compose_form hook can add an array entry
1264 // to the globally scoped $compose_onsubmit; we add them up
5c4ff7bf 1265 // here and format the form tag's full onsubmit handler.
1266 // Each plugin should use "return false" if they need to
a34b07a5 1267 // stop form submission but otherwise should NOT use "return
1268 // true" to give other plugins the chance to do what they need
1269 // to do; SquirrelMail itself will add the final "return true".
1270 // Onsubmit text is enclosed inside of double quotes, so plugins
1271 // need to quote accordingly.
395c3216 1272 //
1273 // Also, plugin authors should try to retain compatibility with
1274 // the Compose Extras plugin by resetting its compose submit
1275 // counter when preventing form submit. Use this code:
1276 // if (your-code-here) { submit_count = 0; return false; }
1277 //
a34b07a5 1278 if (checkForJavascript()) {
5c4ff7bf 1279 if (empty($compose_onsubmit))
a34b07a5 1280 $compose_onsubmit = array();
5c4ff7bf 1281 else if (!is_array($compose_onsubmit))
a34b07a5 1282 $compose_onsubmit = array($compose_onsubmit);
1283
82dcbb1e 1284 $onsubmit_text = '';
a34b07a5 1285 foreach ($compose_onsubmit as $text) {
1286 $text = trim($text);
82dcbb1e 1287 if (!empty($text)) {
1288 if (substr($text, -1) != ';' && substr($text, -1) != '}')
1289 $text .= '; ';
1290 $onsubmit_text .= $text;
1291 }
a34b07a5 1292 }
1293
82dcbb1e 1294 if (!empty($onsubmit_text))
c8dc86c9 1295//FIXME: DON'T ECHO HTML FROM CORE!
82dcbb1e 1296 echo ' onsubmit="' . $onsubmit_text . ' return true;"';
a34b07a5 1297 }
5c4ff7bf 1298
a34b07a5 1299
c8dc86c9 1300//FIXME: NO HTML IN CORE!
48985d59 1301 echo ">\n";
1302
c8dc86c9 1303//FIXME: DON'T ECHO HTML FROM CORE!
199a9ab8 1304 echo addHidden('smtoken', sm_generate_security_token());
1305
1306//FIXME: DON'T ECHO HTML FROM CORE!
df96b37a 1307 echo addHidden('startMessage', $startMessage);
4a1788b3 1308
41b94d65 1309 if ($action == 'draft') {
c8dc86c9 1310//FIXME: DON'T ECHO HTML FROM CORE!
df96b37a 1311 echo addHidden('delete_draft', $passed_id);
48985d59 1312 }
1313 if (isset($delete_draft)) {
c8dc86c9 1314//FIXME: DON'T ECHO HTML FROM CORE!
df96b37a 1315 echo addHidden('delete_draft', $delete_draft);
48985d59 1316 }
da95c4b6 1317 if (isset($session)) {
c8dc86c9 1318//FIXME: DON'T ECHO HTML FROM CORE!
df96b37a 1319 echo addHidden('session', $session);
da95c4b6 1320 }
1c044820 1321
08bad2b1 1322 if (isset($passed_id)) {
c8dc86c9 1323//FIXME: DON'T ECHO HTML FROM CORE!
df96b37a 1324 echo addHidden('passed_id', $passed_id);
08bad2b1 1325 }
44560457 1326
e506b6e5 1327 if (isset($fwduid)) {
1328//FIXME: DON'T ECHO HTML FROM CORE!
1329 echo addHidden('fwduid', $fwduid);
1330 }
1331
9c3e6cd4 1332 if ($saved_draft == 'yes') {
774d79cc 1333 $oTemplate->assign('note', _("Your draft has been saved."));
762853f4 1334 $oTemplate->display('note.tpl');
9c3e6cd4 1335 }
1336 if ($mail_sent == 'yes') {
774d79cc 1337 $oTemplate->assign('note', _("Your mail has been sent."));
762853f4 1338 $oTemplate->display('note.tpl');
9c3e6cd4 1339 }
9c3e6cd4 1340 if ($compose_new_win == '1') {
762853f4 1341 $oTemplate->display('compose_newwin_close.tpl');
9c3e6cd4 1342 }
1638beb6 1343
78a35fcd 1344 if ($location_of_buttons == 'top') {
c8dc86c9 1345//FIXME: DON'T ECHO HTML FROM CORE!
78a35fcd 1346 showComposeButtonRow();
1347 }
48985d59 1348
762853f4 1349 $identities = array();
1e2a6ff6 1350 if (count($idents) > 1) {
762853f4 1351 reset($idents);
73ad81bf 1352 foreach($idents as $id => $data) {
762853f4 1353 $identities[$id] = $data['full_name'].' &lt;'.$data['email_address'].'&gt;';
73ad81bf 1354 }
762853f4 1355 }
1638beb6 1356
762853f4 1357 $oTemplate->assign('identities', $identities);
1358 $oTemplate->assign('identity_def', $identity);
1359 $oTemplate->assign('input_onfocus', 'onfocus="'.join(' ', $onfocus_array).'"');
1638beb6 1360
3047e291 1361 $oTemplate->assign('to', sm_encode_html_special_chars($send_to));
1362 $oTemplate->assign('cc', sm_encode_html_special_chars($send_to_cc));
1363 $oTemplate->assign('bcc', sm_encode_html_special_chars($send_to_bcc));
1364 $oTemplate->assign('subject', sm_encode_html_special_chars($subject));
1638beb6 1365
8949acd6 1366 // access keys...
1367 //
1368 global $accesskey_compose_to, $accesskey_compose_cc,
5f20677e 1369 $accesskey_compose_identity, $accesskey_compose_bcc,
1370 $accesskey_compose_subject;
1371 $oTemplate->assign('accesskey_compose_identity', $accesskey_compose_identity);
8949acd6 1372 $oTemplate->assign('accesskey_compose_to', $accesskey_compose_to);
1373 $oTemplate->assign('accesskey_compose_cc', $accesskey_compose_cc);
1374 $oTemplate->assign('accesskey_compose_bcc', $accesskey_compose_bcc);
1375 $oTemplate->assign('accesskey_compose_subject', $accesskey_compose_subject);
1376
762853f4 1377 $oTemplate->display('compose_header.tpl');
48985d59 1378
78a35fcd 1379 if ($location_of_buttons == 'between') {
c8dc86c9 1380//FIXME: DON'T ECHO HTML FROM CORE!
78a35fcd 1381 showComposeButtonRow();
1382 }
4dfb9db7 1383
762853f4 1384 $body_str = '';
48985d59 1385 if ($use_signature == true && $newmail == true && !isset($from_htmladdr_search)) {
1e2a6ff6 1386 $signature = $idents[$identity]['signature'];
d3c13a51 1387
3b17e952 1388 if ($sig_first == '1') {
50706f77 1389 /*
1390 * FIXME: test is specific to ja_JP translation implementation.
1391 * This test might apply incorrect conversion to other translations, but
91c27aee 1392 * use of 7bit iso-2022-jp charset in other translations might have other
50706f77 1393 * issues too.
1394 */
ab4700c3 1395 if ($default_charset == 'iso-2022-jp') {
762853f4 1396 $body_str = "\n\n".($prefix_sig==true? "-- \n":'').mb_convert_encoding($signature, 'EUC-JP');
83be314a 1397 } else {
762853f4 1398 $body_str = "\n\n".($prefix_sig==true? "-- \n":'').decodeHeader($signature,false,false);
83be314a 1399 }
3047e291 1400 $body_str .= "\n\n".sm_encode_html_special_chars(decodeHeader($body,false,false));
762853f4 1401 } else {
3047e291 1402 $body_str = "\n\n".sm_encode_html_special_chars(decodeHeader($body,false,false));
50706f77 1403 // FIXME: test is specific to ja_JP translation implementation. See above comments.
ab4700c3 1404 if ($default_charset == 'iso-2022-jp') {
762853f4 1405 $body_str .= "\n\n".($prefix_sig==true? "-- \n":'').mb_convert_encoding($signature, 'EUC-JP');
1406 } else {
1407 $body_str .= "\n\n".($prefix_sig==true? "-- \n":'').decodeHeader($signature,false,false);
73ad81bf 1408 }
3b17e952 1409 }
73ad81bf 1410 } else {
3047e291 1411 $body_str = sm_encode_html_special_chars(decodeHeader($body,false,false));
48985d59 1412 }
12a0ed01 1413
762853f4 1414 $oTemplate->assign('editor_width', (int)$editor_size);
1415 $oTemplate->assign('editor_height', (int)$editor_height);
1416 $oTemplate->assign('input_onfocus', 'onfocus="'.join(' ', $onfocus_array).'"');
1417 $oTemplate->assign('body', $body_str);
1418 $oTemplate->assign('show_bottom_send', $location_of_buttons!='bottom');
1638beb6 1419
8949acd6 1420 // access keys...
1421 //
1422 global $accesskey_compose_body, $accesskey_compose_send;
1423 $oTemplate->assign('accesskey_compose_body', $accesskey_compose_body);
1424 $oTemplate->assign('accesskey_compose_send', $accesskey_compose_send);
1425
762853f4 1426 $oTemplate->display ('compose_body.tpl');
1638beb6 1427
48985d59 1428 if ($location_of_buttons == 'bottom') {
c8dc86c9 1429//FIXME: DON'T ECHO HTML FROM CORE!
48985d59 1430 showComposeButtonRow();
48985d59 1431 }
46bb8da8 1432
f8eb968d 1433 // composeMessage can be empty when coming from a restored session
1434 if (is_object($composeMessage) && $composeMessage->entities)
1435 $attach_array = $composeMessage->entities;
1436 if ($session_expired && !empty($attachments) && is_array($attachments))
1437 $attach_array = $attachments;
1438
48985d59 1439 /* This code is for attachments */
73ad81bf 1440 if ((bool) ini_get('file_uploads')) {
1441
1442 /* Calculate the max size for an uploaded file.
1443 * This is advisory for the user because we can't actually prevent
1444 * people to upload too large files. */
1445 $sizes = array();
1446 /* php.ini vars which influence the max for uploads */
1447 $configvars = array('post_max_size', 'memory_limit', 'upload_max_filesize');
1448 foreach($configvars as $var) {
4f21ba00 1449 /* skip 0 or empty values, and -1 which means 'unlimited' */
73ad81bf 1450 if( $size = getByteSize(ini_get($var)) ) {
4f21ba00 1451 if ( $size != '-1' ) {
1452 $sizes[] = $size;
1453 }
73ad81bf 1454 }
0a2c3218 1455 }
0a2c3218 1456
762853f4 1457 $attach = array();
1f270d3c 1458 global $username, $attachment_dir;
1459 $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
f8eb968d 1460 if (!empty($attach_array)) {
1461 foreach ($attach_array as $key => $attachment) {
73ad81bf 1462 $attached_file = $attachment->att_local_name;
1463 if ($attachment->att_local_name || $attachment->body_part) {
1464 $attached_filename = decodeHeader($attachment->mime_header->getParameter('name'));
1465 $type = $attachment->mime_header->type0.'/'.
a91189d6 1466 $attachment->mime_header->type1;
1638beb6 1467
762853f4 1468 $a = array();
1469 $a['Key'] = $key;
1470 $a['FileName'] = $attached_filename;
1471 $a['ContentType'] = $type;
1f270d3c 1472 $a['Size'] = filesize($hashed_attachment_dir . '/' . $attached_file);
762853f4 1473 $attach[$key] = $a;
73ad81bf 1474 }
1475 }
4dfb9db7 1476 }
1638beb6 1477
762853f4 1478 $max = min($sizes);
1479 $oTemplate->assign('max_file_size', empty($max) ? -1 : $max);
1480 $oTemplate->assign('attachments', $attach);
1638beb6 1481
8949acd6 1482 // access keys...
1483 //
1484 global $accesskey_compose_attach_browse, $accesskey_compose_attach,
1485 $accesskey_compose_delete_attach;
1486 $oTemplate->assign('accesskey_compose_attach_browse', $accesskey_compose_attach_browse);
1487 $oTemplate->assign('accesskey_compose_attach', $accesskey_compose_attach);
1488 $oTemplate->assign('accesskey_compose_delete_attach', $accesskey_compose_delete_attach);
1489
762853f4 1490 $oTemplate->display('compose_attachments.tpl');
73ad81bf 1491 } // End of file_uploads if-block
41b94d65 1492 /* End of attachment code */
762853f4 1493
253ad942 1494 $oTemplate->assign('username', $username);
1495 $oTemplate->assign('smaction', $action);
1496 $oTemplate->assign('mailbox', $mailbox);
953fa718 1497 sqgetGlobalVar('QUERY_STRING', $queryString, SQ_SERVER);
253ad942 1498 $oTemplate->assign('querystring', $queryString);
1499 $oTemplate->assign('composesession', $composesession);
1500 $oTemplate->assign('send_button_count', unique_widget_name('send', TRUE));
1501 if (!empty($attach_array))
1502 $oTemplate->assign('attachments', urlencode(serialize($attach_array)));
1503
1504 $aUserNotices = array();
1505
1506 // File uploads are off, so we didn't show that part of the form.
1507 // To avoid bogus bug reports, tell the user why.
a64f47e7 1508 if (!(bool) ini_get('file_uploads')) {
253ad942 1509 $aUserNotices[] = _("Because PHP file uploads are turned off, you can not attach files to this message. Please see your system administrator for details.");
a64f47e7 1510 }
1511
253ad942 1512 $oTemplate->assign('user_notices', $aUserNotices);
1513
1514 $oTemplate->display('compose_form_close.tpl');
1515
762853f4 1516 if ($compose_new_win=='1') {
1517 $oTemplate->display('compose_newwin_close.tpl');
1518 }
1638beb6 1519
762853f4 1520 $oErrorHandler->setDelayedErrors(false);
5c4ff7bf 1521 $oTemplate->display('footer.tpl');
48985d59 1522}
1523
1524
70c4fd84 1525function showComposeButtonRow() {
78a35fcd 1526 global $use_javascript_addr_book, $save_as_draft,
73ad81bf 1527 $default_use_priority, $mailprio, $default_use_mdn,
1528 $request_mdn, $request_dr,
1529 $data_dir, $username;
70c4fd84 1530
762853f4 1531 global $oTemplate, $buffer_hook;
1638beb6 1532
1533 if ($default_use_priority) {
762853f4 1534 $priorities = array('1'=>_("High"), '3'=>_("Normal"), '5'=>_("Low"));
1535 $priority = isset($mailprio) ? $mailprio : 3;
1536 } else {
1537 $priorities = array();
1538 $priority = NULL;
ae25968c 1539 }
1638beb6 1540
ae25968c 1541 $mdn_user_support=getPref($data_dir, $username, 'mdn_user_support',$default_use_mdn);
48985d59 1542
8949acd6 1543 $address_book_button_attribs = array();
1544 global $accesskey_compose_addresses;
1545 if ($accesskey_compose_addresses != 'NONE')
1546 $address_book_button_attribs['accesskey'] = $accesskey_compose_addresses;
c40a269e 1547 if ($use_javascript_addr_book && checkForJavascript()) {
8949acd6 1548 $addr_book = addButton(_("Addresses"),
1549 null,
1550 array_merge($address_book_button_attribs, array('onclick' => 'javascript:open_abook();')));
734f4ee6 1551 } else {
8949acd6 1552 $addr_book = addSubmit(_("Addresses"), 'html_addr_search', $address_book_button_attribs);
78a35fcd 1553 }
48985d59 1554
762853f4 1555 $oTemplate->assign('allow_priority', $default_use_priority==1);
1556 $oTemplate->assign('priority_list', $priorities);
1557 $oTemplate->assign('current_priority', $priority);
1638beb6 1558
762853f4 1559 $oTemplate->assign('notifications_enabled', $mdn_user_support==1);
1560 $oTemplate->assign('read_receipt', $request_mdn=='1');
1561 $oTemplate->assign('delivery_receipt', $request_dr=='1');
1638beb6 1562
762853f4 1563 $oTemplate->assign('drafts_enabled', $save_as_draft);
1564 $oTemplate->assign('address_book_button', $addr_book);
441f2d33 1565
8949acd6 1566 // access keys...
1567 //
1568 global $accesskey_compose_priority, $accesskey_compose_on_read,
1569 $accesskey_compose_on_delivery, $accesskey_compose_signature,
1570 $accesskey_compose_save_draft, $accesskey_compose_send;
1571 $oTemplate->assign('accesskey_compose_priority', $accesskey_compose_priority);
1572 $oTemplate->assign('accesskey_compose_on_read', $accesskey_compose_on_read);
1573 $oTemplate->assign('accesskey_compose_on_delivery', $accesskey_compose_on_delivery);
1574 $oTemplate->assign('accesskey_compose_signature', $accesskey_compose_signature);
1575 $oTemplate->assign('accesskey_compose_save_draft', $accesskey_compose_save_draft);
1576 $oTemplate->assign('accesskey_compose_send', $accesskey_compose_send);
1577
762853f4 1578 $oTemplate->display('compose_buttons.tpl');
78a35fcd 1579}
b278172f 1580
70c4fd84 1581function checkInput ($show) {
78a35fcd 1582 /*
1583 * I implemented the $show variable because the error messages
1584 * were getting sent before the page header. So, I check once
1585 * using $show=false, and then when i'm ready to display the error
1586 * message, show=true
1587 */
1356041d 1588 global $send_to, $send_to_cc, $send_to_bcc;
78a35fcd 1589
1356041d 1590 $send_to = trim($send_to);
1591 $send_to_cc = trim($send_to_cc);
1592 $send_to_bcc = trim($send_to_bcc);
1593 if (empty($send_to) && empty($send_to_cc) && empty($send_to_bcc)) {
78a35fcd 1594 if ($show) {
cb34dbd0 1595 plain_error_message(_("You have not filled in the \"To:\" field."));
78a35fcd 1596 }
1597 return false;
1598 }
1599 return true;
1600} /* function checkInput() */
df15de21 1601
3806fa52 1602
00793a25 1603/* True if FAILURE */
da95c4b6 1604function saveAttachedFiles($session) {
b4e7df34 1605 global $composeMessage, $username, $attachment_dir;
bfa54da7 1606
45cdd1b5 1607 /* get out of here if no file was attached at all */
1608 if (! is_uploaded_file($_FILES['attachfile']['tmp_name']) ) {
1609 return true;
1610 }
1611
1f270d3c 1612 $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
628bce99 1613 $localfilename = sq_get_attach_tempfile();
1f270d3c 1614 $fullpath = $hashed_attachment_dir . '/' . $localfilename;
4c9d2242 1615
a42c236f 1616 // m_u_f works better with restricted PHP installs (safe_mode, open_basedir),
1617 // if that doesn't work, try a simple rename.
8442ecb9 1618 if (!sq_call_function_suppress_errors('move_uploaded_file', array($_FILES['attachfile']['tmp_name'], $fullpath))) {
1619 if (!sq_call_function_suppress_errors('rename', array($_FILES['attachfile']['tmp_name'], $fullpath))) {
73ad81bf 1620 return true;
1621 }
a61878d0 1622 }
0b97a708 1623 $type = strtolower($_FILES['attachfile']['type']);
1624 $name = $_FILES['attachfile']['name'];
b4e7df34 1625 $composeMessage->initAttachment($type, $name, $localfilename);
4c9d2242 1626}
1627
5fe7d683 1628/**
1629 * Parse strings such as "8M" and "2k" into their corresponding size in bytes
1630 *
1631 * NOTE: This function only recognizes the suffixes "K", "M" and "G"
1632 * and will probably break very easily if the given size is in
1633 * some completely different format.
1634 *
1635 * @param string $ini_size The input string to be converted
1636 *
1637 * @return mixed Boolean FALSE if something went wrong (the value passed in
1638 * was empty?, the suffix was not recognized?), otherwise, the
1639 * converted size in bytes (just the number (as an integer),
1640 * no unit identifier included)
1641 *
1642 */
0a2c3218 1643function getByteSize($ini_size) {
1644
4d30dc83 1645 if(!$ini_size) {
1646 return FALSE;
1647 }
da95c4b6 1648
0a2c3218 1649 $ini_size = trim($ini_size);
1650
5b9716de 1651 // if there's some kind of letter at the end of the string we need to multiply.
1652 if(!is_numeric(substr($ini_size, -1))) {
1653
1654 switch(strtoupper(substr($ini_size, -1))) {
1655 case 'G':
73ad81bf 1656 $bytesize = 1073741824;
1657 break;
5b9716de 1658 case 'M':
73ad81bf 1659 $bytesize = 1048576;
1660 break;
5b9716de 1661 case 'K':
73ad81bf 1662 $bytesize = 1024;
1663 break;
5fe7d683 1664 default:
1665 return FALSE;
5b9716de 1666 }
1667
4d30dc83 1668 return ($bytesize * (int)substr($ini_size, 0, -1));
0a2c3218 1669 }
1c044820 1670
4d30dc83 1671 return $ini_size;
0a2c3218 1672}
a43e4b90 1673
4c9d2242 1674
50706f77 1675/**
1676 * temporary function to make use of the deliver class.
a42c236f 1677 * In the future the responsible backend should be automaticly loaded
50706f77 1678 * and conf.pl should show a list of available backends.
1679 * The message also should be constructed by the message class.
b67d61ee 1680 *
10adeb76 1681 * @param object $composeMessage The message being sent. Please note
1682 * that it is passed by reference and
1683 * will be returned modified, with additional
1684 * headers, such as Message-ID, Date, In-Reply-To,
1685 * References, and so forth.
1686 *
b67d61ee 1687 * @return boolean FALSE if delivery failed, or some non-FALSE value
1688 * upon success.
1689 *
73ad81bf 1690 */
10adeb76 1691function deliverMessage(&$composeMessage, $draft=false) {
a43e4b90 1692 global $send_to, $send_to_cc, $send_to_bcc, $mailprio, $subject, $body,
10adeb76 1693 $username, $identity, $idents, $data_dir,
856e58ef 1694 $request_mdn, $request_dr, $default_charset, $useSendmail,
1695 $domain, $action, $default_move_to_sent, $move_to_sent,
a9805897 1696 $imapServerAddress, $imapPort, $imap_stream_options, $sent_folder, $key;
a43e4b90 1697
1698 $rfc822_header = $composeMessage->rfc822_header;
24192f77 1699
1700 $abook = addressbook_init(false, true);
310dfeb6 1701 $rfc822_header->to = $rfc822_header->parseAddress($send_to,true, array(), '', $domain, array(&$abook,'lookup'));
1702 $rfc822_header->cc = $rfc822_header->parseAddress($send_to_cc,true,array(), '',$domain, array(&$abook,'lookup'));
1703 $rfc822_header->bcc = $rfc822_header->parseAddress($send_to_bcc,true, array(), '',$domain, array(&$abook,'lookup'));
a43e4b90 1704 $rfc822_header->priority = $mailprio;
1705 $rfc822_header->subject = $subject;
310dfeb6 1706
a43e4b90 1707 $special_encoding='';
1708 if (strtolower($default_charset) == 'iso-2022-jp') {
1709 if (mb_detect_encoding($body) == 'ASCII') {
a91189d6 1710 $special_encoding = '8bit';
a43e4b90 1711 } else {
1712 $body = mb_convert_encoding($body, 'JIS');
1713 $special_encoding = '7bit';
1714 }
1715 }
1716 $composeMessage->setBody($body);
1717
a43e4b90 1718 $reply_to = '';
1e2a6ff6 1719 $reply_to = $idents[$identity]['reply_to'];
52ead32b 1720 if ($reply_to && strpos($reply_to, '@') === FALSE)
8b213268 1721 $reply_to .= '@' . $domain;
40e07136 1722
1723 $from_addr = build_from_header($identity);
1724 $rfc822_header->from = $rfc822_header->parseAddress($from_addr,true);
a43e4b90 1725 if ($reply_to) {
73ad81bf 1726 $rfc822_header->reply_to = $rfc822_header->parseAddress($reply_to,true);
a43e4b90 1727 }
1728 /* Receipt: On Read */
1729 if (isset($request_mdn) && $request_mdn) {
40e07136 1730 $rfc822_header->dnt = $rfc822_header->parseAddress($from_addr,true);
762853f4 1731 } elseif (isset($rfc822_header->dnt)) {
1732 unset($rfc822_header->dnt);
a43e4b90 1733 }
1638beb6 1734
a43e4b90 1735 /* Receipt: On Delivery */
657fe1bd 1736 if (!empty($request_dr)) {
1737//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 1738 $rfc822_header->more_headers['Return-Receipt-To'] = $from_addr;
762853f4 1739 } elseif (isset($rfc822_header->more_headers['Return-Receipt-To'])) {
1740 unset($rfc822_header->more_headers['Return-Receipt-To']);
a43e4b90 1741 }
762853f4 1742
a43e4b90 1743 /* multipart messages */
1744 if (count($composeMessage->entities)) {
1745 $message_body = new Message();
a91189d6 1746 $message_body->body_part = $composeMessage->body_part;
1747 $composeMessage->body_part = '';
1748 $mime_header = new MessageHeader;
1749 $mime_header->type0 = 'text';
1750 $mime_header->type1 = 'plain';
1751 if ($special_encoding) {
1752 $mime_header->encoding = $special_encoding;
1c044820 1753 } else {
12a0ed01 1754 $mime_header->encoding = '8bit';
a91189d6 1755 }
1756 if ($default_charset) {
1757 $mime_header->parameters['charset'] = $default_charset;
1758 }
1c044820 1759 $message_body->mime_header = $mime_header;
a43e4b90 1760 array_unshift($composeMessage->entities, $message_body);
a91189d6 1761 $content_type = new ContentType('multipart/mixed');
a43e4b90 1762 } else {
1e2026df 1763 $content_type = new ContentType('text/plain');
1764 if ($special_encoding) {
1765 $rfc822_header->encoding = $special_encoding;
1c044820 1766 } else {
1e2026df 1767 $rfc822_header->encoding = '8bit';
1c044820 1768 }
426e0b72 1769 if ($default_charset) {
1770 $content_type->properties['charset']=$default_charset;
73ad81bf 1771 }
181538ac 1772 }
1c044820 1773
a43e4b90 1774 $rfc822_header->content_type = $content_type;
1775 $composeMessage->rfc822_header = $rfc822_header;
0fdb0aa1 1776 if ($action == 'reply' || $action == 'reply_all') {
1777 global $passed_id, $passed_ent_id;
1778 $reply_id = $passed_id;
1779 $reply_ent_id = $passed_ent_id;
1780 } else {
1781 $reply_id = '';
1782 $reply_ent_id = '';
1783 }
1638beb6 1784
1c044820 1785 /* Here you can modify the message structure just before we hand
6e515418 1786 it over to deliver; plugin authors note that $composeMessage
1787 is sent and modified by reference since 1.5.2 */
1788 do_hook('compose_send', $composeMessage);
66540988 1789//TODO: need to migrate to the following, but it neessitates changes in existing plugins, since the args are now an array
1790 //$temp = array(&$composeMessage, &$draft);
1791 //do_hook('compose_send', $temp);
a43e4b90 1792
aff28a6d 1793 // remove special header if present and prepare to mark
1794 // a message that a draft was composed in reply to
1795 if (!empty($composeMessage->rfc822_header->x_sm_flag_reply) && !$draft) {
1796 global $passed_id, $mailbox;
1797 // tricks the code below that marks the reply
1798 list($action, $passed_id, $mailbox) = explode('::', $rfc822_header->x_sm_flag_reply, 3);
1799 unset($composeMessage->rfc822_header->x_sm_flag_reply);
1800 unset($composeMessage->rfc822_header->more_headers['X-SM-Flag-Reply']);
1801 }
1802
b48d3c53 1803 if (!$useSendmail && !$draft) {
a91189d6 1804 require_once(SM_PATH . 'class/deliver/Deliver_SMTP.class.php');
1805 $deliver = new Deliver_SMTP();
a9805897 1806 global $smtpServerAddress, $smtpPort, $smtp_stream_options, $pop_before_smtp, $pop_before_smtp_host;
a91189d6 1807
a91189d6 1808 $authPop = (isset($pop_before_smtp) && $pop_before_smtp) ? true : false;
783e926e 1809 if (empty($pop_before_smtp_host)) $pop_before_smtp_host = $smtpServerAddress;
9bd3b1e6 1810 get_smtp_user($user, $pass);
a91189d6 1811 $stream = $deliver->initStream($composeMessage,$domain,0,
a9805897 1812 $smtpServerAddress, $smtpPort, $user, $pass, $authPop, $pop_before_smtp_host, $smtp_stream_options);
b48d3c53 1813 } elseif (!$draft) {
73ad81bf 1814 require_once(SM_PATH . 'class/deliver/Deliver_SendMail.class.php');
fd7ab795 1815 global $sendmail_path, $sendmail_args;
f3dc9c62 1816 // Check for outdated configuration
1817 if (!isset($sendmail_args)) {
1818 if ($sendmail_path=='/var/qmail/bin/qmail-inject') {
1819 $sendmail_args = '';
1820 } else {
1821 $sendmail_args = '-i -t';
1822 }
1823 }
fd7ab795 1824 $deliver = new Deliver_SendMail(array('sendmail_args'=>$sendmail_args));
73ad81bf 1825 $stream = $deliver->initStream($composeMessage,$sendmail_path);
b48d3c53 1826 } elseif ($draft) {
73ad81bf 1827 global $draft_folder;
906f7e9f 1828 $imap_stream = sqimap_login($username, false, $imapServerAddress,
a9805897 1829 $imapPort, 0, $imap_stream_options);
73ad81bf 1830 if (sqimap_mailbox_exists ($imap_stream, $draft_folder)) {
aff28a6d 1831//TODO: this can leak private information about folders and message IDs if messages are accessed/sent from another client --- should this feature be optional?
1832 // make note of the message to mark as having been replied to
1833 global $passed_id, $mailbox;
1834 if ($action == 'reply' || $action == 'reply_all' || $action == 'forward' || $action == 'forward_as_attachment') {
1835 $composeMessage->rfc822_header->more_headers['X-SM-Flag-Reply'] = $action . '::' . $passed_id . '::' . $mailbox;
1836 }
1837
73ad81bf 1838 require_once(SM_PATH . 'class/deliver/Deliver_IMAP.class.php');
1839 $imap_deliver = new Deliver_IMAP();
a90d951c 1840 $success = $imap_deliver->mail($composeMessage, $imap_stream, $reply_id, $reply_ent_id, $imap_stream, $draft_folder);
73ad81bf 1841 sqimap_logout($imap_stream);
1842 unset ($imap_deliver);
c077ffeb 1843 $composeMessage->purgeAttachments();
b67d61ee 1844 return $success;
4dfb9db7 1845 } else {
3047e291 1846 $msg = '<br />'.sprintf(_("Error: Draft folder %s does not exist."), sm_encode_html_special_chars($draft_folder));
cb34dbd0 1847 plain_error_message($msg);
73ad81bf 1848 return false;
a91189d6 1849 }
a43e4b90 1850 }
0c59bbe1 1851 $success = false;
a43e4b90 1852 if ($stream) {
10adeb76 1853 $deliver->mail($composeMessage, $stream, $reply_id, $reply_ent_id);
0c59bbe1 1854 $success = $deliver->finalizeStream($stream);
a43e4b90 1855 }
0c59bbe1 1856 if (!$success) {
fd7ab795 1857 // $deliver->dlv_server_msg is not always server's reply
32433689 1858 $msg = _("Message not sent.")
1859 . "<br />\n"
1860 . (isset($deliver->dlv_msg) ? $deliver->dlv_msg : '');
a15f9d93 1861 if (!empty($deliver->dlv_server_msg)) {
1862 // add 'server replied' part only when it is not empty.
1863 // Delivery error can be generated by delivery class itself
32433689 1864 $msg .= '<br />'
1865 . _("Server replied:") . ' '
1866 . (isset($deliver->dlv_ret_nr) ? $deliver->dlv_ret_nr . ' ' : '')
3047e291 1867 . nl2br(sm_encode_html_special_chars($deliver->dlv_server_msg));
a15f9d93 1868 }
cb34dbd0 1869 plain_error_message($msg);
a43e4b90 1870 } else {
1871 unset ($deliver);
a9805897 1872 $imap_stream = sqimap_login($username, false, $imapServerAddress, $imapPort, 0, $imap_stream_options);
e4a1f097 1873
8780308f 1874
414303b8 1875 // mark as replied or forwarded if applicable
1876 //
e506b6e5 1877 global $what, $iAccount, $startMessage, $passed_id, $fwduid, $mailbox;
8780308f 1878
bc29bf70 1879 if ($action=='reply' || $action=='reply_all' || $action=='forward' || $action=='forward_as_attachment') {
202bcbcc 1880 require(SM_PATH . 'functions/mailbox_display.php');
aff28a6d 1881 // select errors here could be due to a draft reply being sent
1882 // after the original message's mailbox is moved or deleted
1883 $aMailbox = sqm_api_mailbox_select($imap_stream, $iAccount, $mailbox,array('setindex' => $what, 'offset' => $startMessage),array(), false);
1884 // a non-empty return from above means we can proceed
1885 if (!empty($aMailbox)) {
1886 switch($action) {
1887 case 'reply':
1888 case 'reply_all':
1889 // check if we are allowed to set the \\Answered flag
1890 if (in_array('\\answered',$aMailbox['PERMANENTFLAGS'], true)) {
1891 $aUpdatedMsgs = sqimap_toggle_flag($imap_stream, array($passed_id), '\\Answered', true, false);
1892 if (isset($aUpdatedMsgs[$passed_id]['FLAGS'])) {
1893 /**
1894 * Only update the cached headers if the header is
1895 * cached.
1896 */
1897 if (isset($aMailbox['MSG_HEADERS'][$passed_id])) {
1898 $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS'] = $aMsg['FLAGS'];
1899 }
bc29bf70 1900 }
1901 }
aff28a6d 1902 break;
1903 case 'forward':
1904 case 'forward_as_attachment':
1905 // check if we are allowed to set the $Forwarded flag (RFC 4550 paragraph 2.8)
1906 if (in_array('$forwarded',$aMailbox['PERMANENTFLAGS'], true) ||
1907 in_array('\\*',$aMailbox['PERMANENTFLAGS'])) {
1908
1909 // when forwarding as an attachment from the message
1910 // list, passed_id is not used, need to get UID(s)
1911 // from the query string
1912 //
1913 if (empty($passed_id) && !empty($fwduid))
1914 $ids = explode('_', $fwduid);
1915 else
1916 $ids = array($passed_id);
e506b6e5 1917
aff28a6d 1918 $aUpdatedMsgs = sqimap_toggle_flag($imap_stream, $ids, '$Forwarded', true, false);
e506b6e5 1919
aff28a6d 1920 foreach ($ids as $id) {
1921 if (isset($aUpdatedMsgs[$id]['FLAGS'])) {
1922 if (isset($aMailbox['MSG_HEADERS'][$id])) {
1923 $aMailbox['MSG_HEADERS'][$id]['FLAGS'] = $aMsg['FLAGS'];
1924 }
e506b6e5 1925 }
bc29bf70 1926 }
bda07b93 1927 }
aff28a6d 1928 break;
8780308f 1929 }
bc29bf70 1930
aff28a6d 1931 /**
1932 * Write mailbox with updated seen flag information back to cache.
1933 */
1934 if(isset($aUpdatedMsgs[$passed_id])) {
1935 $mailbox_cache[$iAccount.'_'.$aMailbox['NAME']] = $aMailbox;
1936 sqsession_register($mailbox_cache,'mailbox_cache');
1937 }
bc29bf70 1938 }
a91189d6 1939 }
414303b8 1940
1941
1942 // move to sent folder
1943 //
1944 $move_to_sent = getPref($data_dir,$username,'move_to_sent');
1945 if (isset($default_move_to_sent) && ($default_move_to_sent != 0)) {
1946 $svr_allow_sent = true;
1947 } else {
1948 $svr_allow_sent = false;
1949 }
1950
1951 if (isset($sent_folder) && (($sent_folder != '') || ($sent_folder != 'none'))
1952 && sqimap_mailbox_exists( $imap_stream, $sent_folder)) {
1953 $fld_sent = true;
1954 } else {
1955 $fld_sent = false;
1956 }
1957
1958 if ((isset($move_to_sent) && ($move_to_sent != 0)) || (!isset($move_to_sent))) {
1959 $lcl_allow_sent = true;
1960 } else {
1961 $lcl_allow_sent = false;
1962 }
1963
1964 if (($fld_sent && $svr_allow_sent && !$lcl_allow_sent) || ($fld_sent && $lcl_allow_sent)) {
1965 if ($action == 'reply' || $action == 'reply_all') {
1966 $save_reply_with_orig=getPref($data_dir,$username,'save_reply_with_orig');
1967 if ($save_reply_with_orig) {
1968 $sent_folder = $mailbox;
1969 }
1970 }
414303b8 1971 require_once(SM_PATH . 'class/deliver/Deliver_IMAP.class.php');
1972 $imap_deliver = new Deliver_IMAP();
33f0da43 1973 $imap_deliver->mail($composeMessage, $imap_stream, $reply_id, $reply_ent_id, $imap_stream, $sent_folder);
414303b8 1974 unset ($imap_deliver);
1975 }
1976
1977
1978 // final cleanup
1979 //
1980 $composeMessage->purgeAttachments();
1981 sqimap_logout($imap_stream);
1982
a43e4b90 1983 }
0c59bbe1 1984 return $success;
a43e4b90 1985}