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