Fix broken default value for 'save as draft' and fix explanation of 'move to sent...
[squirrelmail.git] / src / read_body.php
1 <?php
2
3 /**
4 * read_body.php
5 *
6 * This file is used for reading the msgs array and displaying
7 * the resulting emails in the right frame.
8 *
9 * @copyright &copy; 1999-2007 The SquirrelMail Project Team
10 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
11 * @version $Id$
12 * @package squirrelmail
13 */
14
15 /** This is the read_body page */
16 define('PAGE_NAME', 'read_body');
17
18 /**
19 * Include the SquirrelMail initialization file.
20 */
21 require('../include/init.php');
22
23 /* SquirrelMail required files. */
24 require_once(SM_PATH . 'functions/imap.php');
25 require_once(SM_PATH . 'functions/imap_asearch.php'); // => move to mailbox_display
26 require_once(SM_PATH . 'functions/mime.php');
27 require_once(SM_PATH . 'functions/date.php');
28 require_once(SM_PATH . 'functions/url_parser.php');
29 require_once(SM_PATH . 'functions/identity.php');
30 require_once(SM_PATH . 'functions/mailbox_display.php');
31 require_once(SM_PATH . 'functions/forms.php');
32 require_once(SM_PATH . 'functions/attachment_common.php');
33 require_once(SM_PATH . 'functions/compose.php');
34
35 /**
36 * Given an IMAP message id number, this will look it up in the cached
37 * and sorted msgs array and return the index of the next message
38 *
39 * @param int $passed_id The current message UID
40 * @return the index of the next valid message from the array
41 */
42 function findNextMessage($uidset,$passed_id='backwards') {
43 if (!is_array($uidset)) {
44 return -1;
45 }
46 if ($passed_id=='backwards' || !is_array($uidset)) { // check for backwards compattibilty gpg plugin
47 $passed_id = $uidset;
48 }
49 $result = sqm_array_get_value_by_offset($uidset,$passed_id,1);
50 if ($result === false) {
51 return -1;
52 } else {
53 return $result;
54 }
55 }
56
57 /**
58 * Given an IMAP message id number, this will look it up in the cached
59 * and sorted msgs array and return the index of the previous message
60 *
61 * @param int $passed_id The current message UID
62 * @return the index of the next valid message from the array
63 */
64
65 function findPreviousMessage($uidset, $passed_id) {
66 if (!is_array($uidset)) {
67 return -1;
68 }
69 $result = sqm_array_get_value_by_offset($uidset,$passed_id,-1);
70 if ($result === false) {
71 return -1;
72 } else {
73 return $result;
74 }
75 }
76
77 function html_toggle_href ($mailbox, $passed_id, $passed_ent_id, $message) {
78 global $base_uri, $show_html_default;
79
80 $has_html = false;
81 if ($message->header->type0 == 'message' && $message->header->type1 == 'rfc822') {
82 $type0 = $message->rfc822_header->content_type->type0;
83 $type1 = $message->rfc822_header->content_type->type1;
84 } else {
85 $type0 = $message->header->type0;
86 $type1 = $message->header->type1;
87 }
88 if($type0 == 'multipart' &&
89 ($type1 == 'alternative' || $type1 == 'mixed' || $type1 == 'related' || $type1=='signed')) {
90 if ($message->findDisplayEntity(array(), array('text/html'), true)) {
91 $has_html = true;
92 }
93 }
94 /*
95 * Normal single part message so check its type.
96 */
97 else {
98 if($type0 == 'text' && $type1 == 'html') {
99 $has_html = true;
100 }
101 }
102 if($has_html == true) {
103 $vars = array('passed_ent_id', 'show_more', 'show_more_cc', 'override_type0', 'override_type1', 'startMessage','where', 'what');
104
105 $new_link = $base_uri . 'src/read_body.php?passed_id=' . urlencode($passed_id) .
106 '&amp;passed_ent_id=' . urlencode($passed_ent_id) .
107 '&amp;mailbox=' . urlencode($mailbox);
108 foreach($vars as $var) {
109 if(sqgetGlobalVar($var, $temp)) {
110 $new_link .= '&amp;' . $var . '=' . urlencode($temp);
111 }
112 }
113
114 if($show_html_default == 1) {
115 $new_link .= '&amp;show_html_default=0';
116 } else {
117 $new_link .= '&amp;show_html_default=1';
118 }
119 return $new_link;
120 }
121 return '';
122 }
123
124 function ServerMDNSupport($aFlags) {
125 /* escaping $ doesn't work -> \x36 */
126 return ( in_array('$mdnsent',$aFlags,true) ||
127 in_array('\\*',$aFlags,true) ) ;
128 }
129
130 function SendMDN ( $mailbox, $passed_id, $message, $imapConnection) {
131 global $squirrelmail_language, $default_charset,
132 $languages, $useSendmail, $domain, $sent_folder;
133
134 sqgetGlobalVar('SERVER_NAME', $SERVER_NAME, SQ_SERVER);
135
136 $header = $message->rfc822_header;
137
138 $rfc822_header = new Rfc822Header();
139 $content_type = new ContentType('multipart/report');
140 $content_type->properties['report-type']='disposition-notification';
141
142 set_my_charset();
143 if ($default_charset) {
144 $content_type->properties['charset']=$default_charset;
145 }
146 $rfc822_header->content_type = $content_type;
147 $rfc822_header->to[] = $header->dnt;
148 $rfc822_header->subject = _("Read:") . ' ' . decodeHeader($header->subject,true,false);
149
150 $idents = get_identities();
151 $needles = array();
152 if ($header->to) {
153 foreach ($header->to as $message_to) {
154 $needles[] = $message_to->mailbox.'@'.$message_to->host;
155 }
156 }
157 $identity = find_identity($needles);
158 $from_addr = build_from_header($identity);
159 $reply_to = isset($idents[$identity]['reply_to']) ? $idents[$identity]['reply_to'] : '';
160 // FIXME: this must actually be the envelope address of the orginal message,
161 // but do we have that information? For now the first identity is our best guess.
162 $final_recipient = $idents[0]['email_address'];
163
164 $rfc822_header->from = $rfc822_header->parseAddress($from_addr,true);
165 if ($reply_to) {
166 $rfc822_header->reply_to = $rfc822_header->parseAddress($reply_to,true);
167 }
168
169 // part 1 (RFC2298)
170 $senton = getLongDateString( $header->date, $header->date_unparsed );
171 $to_array = $header->to;
172 $to = '';
173 foreach ($to_array as $line) {
174 $to .= ' '.$line->getAddress();
175 }
176 $now = getLongDateString( time() );
177 set_my_charset();
178 $body = _("Your message") . "\r\n\r\n" .
179 "\t" . _("To") . ': ' . decodeHeader($to,false,false) . "\r\n" .
180 "\t" . _("Subject") . ': ' . decodeHeader($header->subject,false,false) . "\r\n" .
181 "\t" . _("Sent") . ': ' . $senton . "\r\n" .
182 "\r\n" .
183 sprintf( _("Was displayed on %s"), $now );
184
185 $special_encoding = '';
186 if (isset($languages[$squirrelmail_language]['XTRA_CODE']) &&
187 function_exists($languages[$squirrelmail_language]['XTRA_CODE'] . '_encode')) {
188 $body = call_user_func($languages[$squirrelmail_language]['XTRA_CODE'] . '_encode', $body);
189 if (strtolower($default_charset) == 'iso-2022-jp') {
190 if (mb_detect_encoding($body) == 'ASCII') {
191 $special_encoding = '8bit';
192 } else {
193 $body = mb_convert_encoding($body, 'JIS');
194 $special_encoding = '7bit';
195 }
196 }
197 } elseif (sq_is8bit($body)) {
198 $special_encoding = '8bit';
199 }
200 $part1 = new Message();
201 $part1->setBody($body);
202 $mime_header = new MessageHeader;
203 $mime_header->type0 = 'text';
204 $mime_header->type1 = 'plain';
205 if ($special_encoding) {
206 $mime_header->encoding = $special_encoding;
207 } else {
208 $mime_header->encoding = 'us-ascii';
209 }
210 if ($default_charset) {
211 $mime_header->parameters['charset'] = $default_charset;
212 }
213 $part1->mime_header = $mime_header;
214
215 // part2 (RFC2298)
216 $original_recipient = $to;
217 $original_message_id = $header->message_id;
218
219 $report = "Reporting-UA : $SERVER_NAME ; SquirrelMail (version " . SM_VERSION . ") \r\n";
220 if ($original_recipient != '') {
221 $report .= "Original-Recipient : $original_recipient\r\n";
222 }
223 $report .= "Final-Recipient: rfc822; $final_recipient\r\n" .
224 "Original-Message-ID : $original_message_id\r\n" .
225 "Disposition: manual-action/MDN-sent-manually; displayed\r\n";
226
227 $part2 = new Message();
228 $part2->setBody($report);
229 $mime_header = new MessageHeader;
230 $mime_header->type0 = 'message';
231 $mime_header->type1 = 'disposition-notification';
232 $mime_header->encoding = 'us-ascii';
233 $part2->mime_header = $mime_header;
234
235 $composeMessage = new Message();
236 $composeMessage->rfc822_header = $rfc822_header;
237 $composeMessage->addEntity($part1);
238 $composeMessage->addEntity($part2);
239
240
241 if ($useSendmail) {
242 require_once(SM_PATH . 'class/deliver/Deliver_SendMail.class.php');
243 global $sendmail_path, $sendmail_args;
244 // Check for outdated configuration
245 if (!isset($sendmail_args)) {
246 if ($sendmail_path=='/var/qmail/bin/qmail-inject') {
247 $sendmail_args = '';
248 } else {
249 $sendmail_args = '-i -t';
250 }
251 }
252 $deliver = new Deliver_SendMail(array('sendmail_args'=>$sendmail_args));
253 $stream = $deliver->initStream($composeMessage,$sendmail_path);
254 } else {
255 require_once(SM_PATH . 'class/deliver/Deliver_SMTP.class.php');
256 $deliver = new Deliver_SMTP();
257 global $smtpServerAddress, $smtpPort, $pop_before_smtp;
258 $authPop = (isset($pop_before_smtp) && $pop_before_smtp) ? true : false;
259 get_smtp_user($user, $pass);
260 $stream = $deliver->initStream($composeMessage,$domain,0,
261 $smtpServerAddress, $smtpPort, $user, $pass, $authPop);
262 }
263 $success = false;
264 if ($stream) {
265 $length = $deliver->mail($composeMessage, $stream);
266 $success = $deliver->finalizeStream($stream);
267 }
268 if (!$success) {
269 $msg = _("Message not sent.") . "<br />\n" .
270 $deliver->dlv_msg;
271 if (! empty($deliver->dlv_server_msg)) {
272 $msg.= '<br />' .
273 _("Server replied:") . ' ' . $deliver->dlv_ret_nr . ' ' .
274 nl2br(htmlspecialchars($deliver->dlv_server_msg));
275 }
276 plain_error_message($msg);
277 } else {
278 unset ($deliver);
279 if (sqimap_mailbox_exists ($imapConnection, $sent_folder)) {
280 $sid = sqimap_append ($imapConnection, $sent_folder, $length);
281 require_once(SM_PATH . 'class/deliver/Deliver_IMAP.class.php');
282 $imap_deliver = new Deliver_IMAP();
283 $imap_deliver->mail($composeMessage, $imapConnection);
284 sqimap_append_done ($imapConnection, $sent_folder);
285 unset ($imap_deliver);
286 }
287 }
288 return $success;
289 }
290
291 function ToggleMDNflag ($set ,$imapConnection, $mailbox, $passed_id) {
292 $sg = $set?'+':'-';
293 $cmd = 'STORE ' . $passed_id . ' ' . $sg . 'FLAGS ($MDNSent)';
294 $read = sqimap_run_command ($imapConnection, $cmd, true, $response,
295 $readmessage, TRUE);
296 }
297
298 function formatRecipientString($recipients, $item ) {
299 global $show_more, $show_more_cc, $show_more_bcc,
300 $PHP_SELF, $oTemplate;
301
302 $string = '';
303 if ((is_array($recipients)) && (isset($recipients[0]))) {
304 $show = false;
305
306 if ($item == 'to') {
307 if ($show_more) {
308 $show = true;
309 $url = set_url_var($PHP_SELF, 'show_more',0);
310 } else {
311 $url = set_url_var($PHP_SELF, 'show_more',1);
312 }
313 } else if ($item == 'cc') {
314 if ($show_more_cc) {
315 $show = true;
316 $url = set_url_var($PHP_SELF, 'show_more_cc',0);
317 } else {
318 $url = set_url_var($PHP_SELF, 'show_more_cc',1);
319 }
320 } else if ($item == 'bcc') {
321 if ($show_more_bcc) {
322 $show = true;
323 $url = set_url_var($PHP_SELF, 'show_more_bcc',0);
324 } else {
325 $url = set_url_var($PHP_SELF, 'show_more_bcc',1);
326 }
327 }
328
329 $a = array();
330 foreach ($recipients as $r) {
331 $a[] = array(
332 'Name' => htmlspecialchars($r->getAddress(false)),
333 'Email' => htmlspecialchars($r->getEmail()),
334 'Full' => htmlspecialchars($r->getAddress(true))
335 );
336 }
337
338 $oTemplate->assign('which_field', $item);
339 $oTemplate->assign('recipients', $a);
340 $oTemplate->assign('more_less_toggle_href', $url);
341 $oTemplate->assign('show_more', $show);
342
343 $string = $oTemplate->fetch('read_recipient_list.tpl');
344 }
345 return $string;
346 }
347
348 function formatEnvheader($aMailbox, $passed_id, $passed_ent_id, $message,
349 $color, $FirstTimeSee) {
350 global $default_use_mdn, $default_use_priority,
351 $show_xmailer_default, $mdn_user_support, $PHP_SELF,
352 $squirrelmail_language, $oTemplate;
353
354 $mailbox = $aMailbox['NAME'];
355
356 $header = $message->rfc822_header;
357 $env = array();
358 $env[_("Subject")] = str_replace("&nbsp;"," ",decodeHeader($header->subject));
359
360 $from_name = $header->getAddr_s('from');
361 if (!$from_name)
362 $from_name = $header->getAddr_s('sender');
363 if (!$from_name)
364 $env[_("From")] = _("Unknown sender");
365 else
366 $env[_("From")] = decodeHeader($from_name);
367 $env[_("Date")] = getLongDateString($header->date, $header->date_unparsed);
368 $env[_("To")] = formatRecipientString($header->to, "to");
369 $env[_("Cc")] = formatRecipientString($header->cc, "cc");
370 $env[_("Bcc")] = formatRecipientString($header->bcc, "bcc");
371 if ($default_use_priority) {
372 $oTemplate->assign('message_priority', $header->priority);
373 $env[_("Priority")] = $oTemplate->fetch('read_message_priority.tpl');
374 }
375 if ($show_xmailer_default) {
376 $oTemplate->assign('xmailer', decodeHeader($header->xmailer));
377 $env[_("Mailer")] = $oTemplate->fetch('read_xmailer.tpl');
378 }
379
380 // this is used for both mdn and also general use for plugins, etc
381 $oTemplate->assign('first_time_reading', $FirstTimeSee);
382
383 if ($default_use_mdn) {
384 if ($mdn_user_support) {
385 if ($header->dnt) {
386 $mdn_url = $PHP_SELF;
387 $mdn_url = set_url_var($mdn_url, 'mailbox', urlencode($mailbox));
388 $mdn_url = set_url_var($mdn_url, 'passed_id', $passed_id);
389 $mdn_url = set_url_var($mdn_url, 'passed_ent_id', $passed_ent_id);
390 $mdn_url = set_url_var($mdn_url, 'sendreceipt', 1);
391
392 $oTemplate->assign('read_receipt_sent', $message->is_mdnsent);
393 $oTemplate->assign('send_receipt_href', $mdn_url);
394
395 $env[_("Read Receipt")] = $oTemplate->fetch('read_handle_receipt.tpl');
396 }
397 }
398 }
399
400 $statuses = array();
401 if (isset($aMailbox['MSG_HEADERS'][$passed_id]['FLAGS'])) {
402 if (isset($aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\deleted']) &&
403 $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\deleted'] === true) {
404 $statuses[] = _("deleted");
405 }
406 if (isset($aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\answered']) &&
407 $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\answered'] === true) {
408 $statuses[] = _("answered");
409 }
410 if (isset($aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\draft']) &&
411 $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\draft'] === true) {
412 $statuses[] = _("draft");
413 }
414 if (isset($aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\flagged']) &&
415 $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\flagged'] === true) {
416 $statuses[] = _("flagged");
417 }
418 if ( count($statuses) ) {
419 $env[_("Status")] = implode(', ', $statuses);
420 }
421 }
422
423 $env[_("Options")] = formatToolbar($mailbox, $passed_id, $passed_ent_id, $message, $color);
424
425
426 $oTemplate->assign('headers_to_display', $env);
427
428 $oTemplate->display('read_headers.tpl');
429 }
430
431 /**
432 * Format message toolbar
433 *
434 * @param array $aMailbox Current mailbox information array
435 * @param int $passed_id UID of current message
436 * @param int $passed_ent_id Id of entity within message
437 * @param object $message Current message object
438 * @param object $mbx_response
439 */
440 function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message, $removedVar, $nav_on_top = TRUE) {
441 global $base_uri, $draft_folder, $where, $what, $sort,
442 $startMessage, $PHP_SELF, $save_as_draft,
443 $enable_forward_as_attachment, $imapConnection, $lastTargetMailbox,
444 $delete_prev_next_display, $show_copy_buttons,
445 $compose_new_win, $compose_width, $compose_height,
446 $oTemplate;
447
448 //FIXME cleanup argument list, use $aMailbox where possible
449 $mailbox = $aMailbox['NAME'];
450
451 $urlMailbox = urlencode($mailbox);
452
453 // Create Prev & Next links
454 // Handle nested entities first (i.e. Mime Attach parts)
455 $prev_href = $next_href = $up_href = $del_href = $del_prev_href = $del_next_href = '';
456 $msg_list_href = $search_href = $view_msg_href = '';
457 if (isset($passed_ent_id) && $passed_ent_id) {
458 // code for navigating through attached message/rfc822 messages
459 $url = set_url_var($PHP_SELF, 'passed_ent_id',0);
460 $entities = array();
461 $entity_count = array();
462 $c = 0;
463
464 foreach($message->parent->entities as $ent) {
465 if ($ent->type0 == 'message' && $ent->type1 == 'rfc822') {
466
467 $c++;
468 $entity_count[$c] = $ent->entity_id;
469 $entities[$ent->entity_id] = $c;
470 }
471 }
472
473 if(isset($entities[$passed_ent_id]) && $entities[$passed_ent_id] > 1) {
474 $prev_ent_id = $entity_count[$entities[$passed_ent_id] - 1];
475 $prev_href = set_url_var($PHP_SELF, 'passed_ent_id', $prev_ent_id);
476 }
477
478 if(isset($entities[$passed_ent_id]) && $entities[$passed_ent_id] < $c) {
479 $next_ent_id = $entity_count[$entities[$passed_ent_id] + 1];
480 $next_href = set_url_var($PHP_SELF, 'passed_ent_id', $next_ent_id);
481 }
482
483 $par_ent_id = $message->parent->entity_id;
484 if ($par_ent_id) {
485 $par_ent_id = substr($par_ent_id,0,-2);
486 if ( $par_ent_id != 0 ) {
487 $up_href = set_url_var($PHP_SELF, 'passed_ent_id',$par_ent_id);
488 }
489 }
490
491 $view_msg_href = $url;
492
493 // Prev/Next links for regular messages
494 } else if ( true ) { //!(isset($where) && isset($what)) ) {
495 $prev = findPreviousMessage($aMailbox['UIDSET'][$what], $passed_id);
496 $next = findNextMessage($aMailbox['UIDSET'][$what],$passed_id);
497
498 if ($prev >= 0) {
499 $prev_href = $base_uri . 'src/read_body.php?passed_id='.$prev.
500 '&amp;mailbox='.$urlMailbox.'&amp;sort='.$sort.
501 "&amp;where=$where&amp;what=$what" .
502 '&amp;startMessage='.$startMessage.'&amp;show_more=0';
503 }
504
505 if ($next >= 0) {
506 $next_href = $base_uri . 'src/read_body.php?passed_id='.$next.
507 '&amp;mailbox='.$urlMailbox.'&amp;sort='.$sort.
508 "&amp;where=$where&amp;what=$what" .
509 '&amp;startMessage='.$startMessage.'&amp;show_more=0';
510 }
511
512 // Only bother with Delete & Prev and Delete & Next IF
513 // top display is enabled.
514 if ( $delete_prev_next_display == 1 &&
515 in_array('\\deleted', $aMailbox['PERMANENTFLAGS'],true) ) {
516 if ($prev >= 0) {
517 $del_prev_href = $base_uri . 'src/read_body.php?passed_id='.$prev.
518 '&amp;mailbox='.$urlMailbox.'&amp;sort='.$sort.
519 '&amp;startMessage='.$startMessage.'&amp;show_more=0'.
520 "&amp;where=$where&amp;what=$what" .
521 '&amp;delete_id='.$passed_id;
522 }
523
524 if ($next >= 0) {
525 $del_next_href = $base_uri . 'src/read_body.php?passed_id='.$next.
526 '&amp;mailbox='.$urlMailbox.'&amp;sort='.$sort.
527 '&amp;startMessage='.$startMessage.'&amp;show_more=0'.
528 "&amp;where=$where&amp;what=$what" .
529 '&amp;delete_id='.$passed_id;
530 }
531 }
532 }
533
534 $msg_list_href = get_message_list_uri($aMailbox['NAME'], $startMessage, $what);
535 if ($where == 'search.php')
536 $search_href = str_replace('read_body.php', 'search.php', $msg_list_href);
537 else
538 $search_href = '';
539
540 $comp_uri = $base_uri.'src/compose.php' .
541 '?passed_id=' . $passed_id .
542 '&amp;mailbox=' . $urlMailbox .
543 '&amp;startMessage=' . $startMessage .
544 (isset($passed_ent_id) ? '&amp;passed_ent_id='.$passed_ent_id : '');
545
546 // Start form for reply/reply all/forward..
547 $target = '';
548 $on_click='';
549 $method='post';
550 $onsubmit='';
551 if ($compose_new_win == '1') {
552 if (!preg_match("/^[0-9]{3,4}$/", $compose_width)) {
553 $compose_width = '640';
554 }
555 if (!preg_match("/^[0-9]{3,4}$/", $compose_height)) {
556 $compose_height = '550';
557 }
558 if ( checkForJavascript() ) {
559 $on_click='comp_in_new_form(\''.$comp_uri.'\', this, this.form,'. $compose_width .',' . $compose_height .')';
560 $comp_uri = 'javascript:void(0)';
561 $method='get';
562 $onsubmit = 'return false';
563 } else {
564 $target = '_blank';
565 }
566 }
567
568 $oTemplate->assign('nav_on_top', $nav_on_top);
569
570 $oTemplate->assign('prev_href', $prev_href);
571 $oTemplate->assign('up_href', $up_href);
572 $oTemplate->assign('next_href', $next_href);
573 $oTemplate->assign('del_prev_href', $del_prev_href);
574 $oTemplate->assign('del_next_href', $del_next_href);
575 $oTemplate->assign('view_msg_href', $view_msg_href);
576
577 $oTemplate->assign('message_list_href', $msg_list_href);
578 $oTemplate->assign('search_href', $search_href);
579
580 $oTemplate->assign('form_extra', '');
581 $oTemplate->assign('form_method', $method);
582 $oTemplate->assign('form_target', $target);
583 $oTemplate->assign('form_onsubmit', $onsubmit);
584 $oTemplate->assign('compose_href', $comp_uri);
585 $oTemplate->assign('button_onclick', $on_click);
586 $oTemplate->assign('forward_as_attachment_enabled', $enable_forward_as_attachment==1);
587
588 //FIXME: I am surprised these aren't already given to the template; probably needs to be given at a higher level, so I have NO IDEA if this is the right place to do this... adding them so template can construct its own API calls... we can build those herein too if preferrable
589 $oTemplate->assign('mailbox', $aMailbox['NAME']);
590 $oTemplate->assign('passed_id', $passed_id);
591 $oTemplate->assign('what', $what);
592
593 // If Draft folder - create Resume link
594 $resume_draft = $edit_as_new = false;
595 if (($mailbox == $draft_folder) && ($save_as_draft)) {
596 $resume_draft = true; 'smaction_draft';
597 } else if (handleAsSent($mailbox)) {
598 $edit_as_new = true;
599 }
600 $oTemplate->assign('can_resume_draft', $resume_draft);
601 $oTemplate->assign('can_edit_as_new', $edit_as_new);
602
603 $oTemplate->assign('mailboxes', sqimap_mailbox_option_array($imapConnection));
604 if (in_array('\\deleted', $aMailbox['PERMANENTFLAGS'],true)) {
605 $delete_url = $base_uri . "src/$where";
606 $oTemplate->assign('can_be_deleted', true);
607 $oTemplate->assign('move_delete_form_action', $base_uri.'src/'.$where);
608 $oTemplate->assign('delete_form_extra', addHidden('mailbox', $aMailbox['NAME'])."\n" .
609 addHidden('msg[0]', $passed_id)."\n" .
610 addHidden('startMessage', $startMessage)."\n" );
611 if (!(isset($passed_ent_id) && $passed_ent_id)) {
612 $oTemplate->assign('can_be_moved', true);
613 $oTemplate->assign('move_form_extra', addHidden('mailbox', $aMailbox['NAME'])."\n" .
614 addHidden('msg[0]', $passed_id)."\n" );
615 $oTemplate->assign('last_move_target', isset($lastTargetMailbox) && !empty($lastTargetMailbox) ? $lastTargetMailbox : '');
616 $oTemplate->assign('can_be_copied', $show_copy_buttons==1);
617 } else {
618 $oTemplate->assign('can_be_moved', false);
619 $oTemplate->assign('move_form_extra', '');
620 $oTemplate->assign('last_move_target', '');
621 $oTemplate->assign('can_be_copied', false);
622 }
623 } else {
624 $oTemplate->assign('can_be_deleted', false);
625 $oTemplate->assign('move_delete_form_action', '');
626 $oTemplate->assign('delete_form_extra', '');
627 $oTemplate->assign('can_be_moved', false);
628 $oTemplate->assign('move_form_extra', '');
629 $oTemplate->assign('last_move_target', '');
630 $oTemplate->assign('can_be_copied', false);
631 }
632
633 global $null;
634 do_hook('read_body_menu', $null);
635
636 if ($nav_on_top) {
637 $oTemplate->display('read_menubar_nav.tpl');
638 $oTemplate->display('read_menubar_buttons.tpl');
639 } else {
640 $oTemplate->display('read_menubar_buttons.tpl');
641 $oTemplate->display('read_menubar_nav.tpl');
642 }
643
644 }
645
646 function formatToolbar($mailbox, $passed_id, $passed_ent_id, $message, $color) {
647 global $base_uri, $where, $what, $show_html_default,
648 $oTemplate, $download_href,
649 $unsafe_image_toggle_href, $unsafe_image_toggle_text;
650
651 $urlMailbox = urlencode($mailbox);
652 $urlPassed_id = urlencode($passed_id);
653 $urlPassed_ent_id = urlencode($passed_ent_id);
654
655 $query_string = 'mailbox=' . $urlMailbox . '&amp;passed_id=' . $urlPassed_id . '&amp;passed_ent_id=' . $urlPassed_ent_id;
656 if (!empty($where)) {
657 $query_string .= '&amp;where=' . urlencode($where);
658 }
659 if (!empty($what)) {
660 $query_string .= '&amp;what=' . urlencode($what);
661 }
662 $url = $base_uri.'src/view_header.php?'.$query_string;
663
664
665 // Build the printer friend link
666 /* hackydiehack */
667 if( !sqgetGlobalVar('view_unsafe_images', $view_unsafe_images, SQ_GET) ) {
668 $view_unsafe_images = false;
669 } else {
670 $view_unsafe_images = true;
671 }
672 $pf_params = '?passed_ent_id=' . $urlPassed_ent_id .
673 '&mailbox=' . $urlMailbox .
674 '&passed_id=' . $urlPassed_id .
675 '&view_unsafe_images='. (bool) $view_unsafe_images .
676 '&show_html_default=' . $show_html_default;
677 $links = array();
678 $links[] = array (
679 'URL' => $url,
680 'Text' => _("View Full Header")
681 );
682 $links[] = array (
683 'URL' => $pf_params,
684 'Text' => _("View Printable Version")
685 );
686 $links[] = array (
687 'URL' => $download_href,
688 'Text' => _("Download this as a file")
689 );
690 $toggle = html_toggle_href($mailbox, $passed_id, $passed_ent_id, $message);
691 if (!empty($toggle)) {
692 $links[] = array (
693 'URL' => $toggle,
694 'Text' => $show_html_default==1 ? _("View as plain text") : _("View as HTML")
695 );
696 }
697 if (!empty($unsafe_image_toggle_href)) {
698 $links[] = array (
699 'URL' => $unsafe_image_toggle_href,
700 'Text' => $unsafe_image_toggle_text
701 );
702 }
703
704 do_hook('read_body_header_right', $links);
705
706 $oTemplate->assign('links', $links);
707
708 return $oTemplate->fetch('read_toolbar.tpl');
709 }
710
711 /***************************/
712 /* Main of read_body.php */
713 /***************************/
714
715 /* get the globals we may need */
716
717 sqgetGlobalVar('delimiter', $delimiter, SQ_SESSION);
718 sqgetGlobalVar('lastTargetMailbox', $lastTargetMailbox, SQ_SESSION);
719 if (!sqgetGlobalVar('messages', $messages, SQ_SESSION) ) {
720 $messages = array();
721 }
722 sqgetGlobalVar('delayed_errors', $delayed_errors, SQ_SESSION);
723 if (is_array($delayed_errors)) {
724 $oErrorHandler->AssignDelayedErrors($delayed_errors);
725 sqsession_unregister("delayed_errors");
726 }
727 /** GET VARS */
728 sqgetGlobalVar('sendreceipt', $sendreceipt, SQ_GET);
729 if (!sqgetGlobalVar('where', $where, SQ_GET) ) {
730 $where = 'right_main.php';
731 }
732 /*
733 * Used as entry key to the list of uid's cached in the mailbox cache
734 * we use the cached uid's to get the next and prev message.
735 */
736 if (!sqgetGlobalVar('what', $what, SQ_GET) ){
737 $what = 0;
738 }
739 if ( sqgetGlobalVar('show_more', $temp, SQ_GET) ) {
740 $show_more = (int) $temp;
741 }
742 if ( sqgetGlobalVar('show_more_cc', $temp, SQ_GET) ) {
743 $show_more_cc = (int) $temp;
744 }
745 if ( sqgetGlobalVar('show_more_bcc', $temp, SQ_GET) ) {
746 $show_more_bcc = (int) $temp;
747 }
748 if ( sqgetGlobalVar('view_hdr', $temp, SQ_GET) ) {
749 $view_hdr = (int) $temp;
750 }
751
752 if ( sqgetGlobalVar('account', $temp, SQ_GET) ) {
753 $iAccount = (int) $temp;
754 } else {
755 $iAccount = 0;
756 }
757
758 /** GET/POST VARS */
759 sqgetGlobalVar('passed_ent_id', $passed_ent_id);
760 sqgetGlobalVar('mailbox', $mailbox);
761
762 if ( sqgetGlobalVar('passed_id', $temp) ) {
763 $passed_id = (int) $temp;
764 }
765 if ( sqgetGlobalVar('sort', $temp) ) {
766 $sort = (int) $temp;
767 }
768 if ( sqgetGlobalVar('startMessage', $temp) ) {
769 $startMessage = (int) $temp;
770 } else {
771 $startMessage = 1;
772 }
773 if(sqgetGlobalVar('show_html_default', $temp)) {
774 $show_html_default = (int) $temp;
775 }
776
777 if(sqgetGlobalVar('view_unsafe_images', $temp)) {
778 $view_unsafe_images = (int) $temp;
779 if($view_unsafe_images == 1) {
780 $show_html_default = 1;
781 }
782 } else {
783 $view_unsafe_images = 0;
784 }
785 /**
786 * Retrieve mailbox cache
787 */
788 sqgetGlobalVar('mailbox_cache',$mailbox_cache,SQ_SESSION);
789
790 /* end of get globals */
791
792 $imapConnection = sqimap_login($username, false, $imapServerAddress, $imapPort, 0);
793 $aMailbox = sqm_api_mailbox_select($imapConnection, $iAccount, $mailbox,array('setindex' => $what, 'offset' => $startMessage),array());
794
795
796 /**
797 Start code to set the columns to fetch in case of hitting the next/prev link
798 The reason for this is the fact that the cache can be invalidated which means that the headers
799 to fetch aren't there anymore. Before they got calculated when the messagelist was shown.
800
801 Todo, better central handling of setting the mailbox options so we do not need to do the stuff below
802 */
803
804 /**
805 * Replace From => To in case it concerns a draft or sent folder
806 */
807 $aColumns = array();
808 if (($mailbox == $sent_folder || $mailbox == $draft_folder) &&
809 !in_array(SQM_COL_TO,$index_order)) {
810 $aNewOrder = array(); // nice var name ;)
811 foreach($index_order as $iCol) {
812 if ($iCol == SQM_COL_FROM) {
813 $iCol = SQM_COL_TO;
814 }
815 $aColumns[$iCol] = array();
816 }
817 } else {
818 foreach ($index_order as $iCol) {
819 $aColumns[$iCol] = array();
820 }
821 }
822
823 $aProps = array(
824 'columns' => $aColumns, // columns bound settings
825 'config' => array(
826 'highlight_list' => $message_highlight_list, // row highlighting rules
827 'trash_folder' => $trash_folder,
828 'sent_folder' => $sent_folder,
829 'draft_folder' => $draft_folder));
830
831 calcFetchColumns($aMailbox,$aProps);
832
833 /**
834 End code to set the columns to fetch in case of hitting the next/prev link
835 */
836
837
838
839 /**
840 * Check if cache is still valid, $what contains the key
841 * which gives us acces to the array with uid's. At this moment
842 * 0 is used for a normal message list and search uses 1 as key. This can be
843 * changed / extended in the future.
844 * If on a select of a mailbox we detect that the cache should be invalidated due to
845 * the delete of messages or due to new messages we empty the list with uid's and
846 * that's what we detect below.
847 */
848 if (!is_array($aMailbox['UIDSET'][$what])) {
849 fetchMessageHeaders($imapConnection, $aMailbox);
850 }
851
852 $iSetIndex = $aMailbox['SETINDEX'];
853 $aMailbox['CURRENT_MSG'][$iSetIndex] = $passed_id;
854
855 /**
856 * Update the seen state
857 * and ignore in_array('\\seen',$aMailbox['PERMANENTFLAGS'],true)
858 */
859 if (isset($aMailbox['MSG_HEADERS'][$passed_id]['FLAGS'])) {
860 $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\seen'] = true;
861 }
862
863 /**
864 * Process Delete from delete-move-next
865 * but only if delete_id was set
866 */
867 if ( sqgetGlobalVar('delete_id', $delete_id, SQ_GET) ) {
868 handleMessageListForm($imapConnection,$aMailbox,$sButton='setDeleted', array($delete_id));
869 }
870
871 /**
872 * $message contains all information about the message
873 * including header and body
874 */
875
876 if (isset($aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT'])) {
877 $message = $aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT'];
878 $FirstTimeSee = !$message->is_seen;
879 } else {
880 $message = sqimap_get_message($imapConnection, $passed_id, $mailbox);
881 $FirstTimeSee = !$message->is_seen;
882 }
883
884 /**
885 * update message seen status and put in cache
886 */
887 $message->is_seen = true;
888 $aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT'] = $message;
889
890 if (isset($passed_ent_id) && $passed_ent_id) {
891 $message = $message->getEntity($passed_ent_id);
892 if ($message->type0 != 'message' && $message->type1 != 'rfc822') {
893 $message = $message->parent;
894 }
895 $read = sqimap_run_command ($imapConnection, "FETCH $passed_id BODY[$passed_ent_id.HEADER]", true, $response, $msg, TRUE);
896 $rfc822_header = new Rfc822Header();
897 $rfc822_header->parseHeader($read);
898 $message->rfc822_header = $rfc822_header;
899 } else if ($message->type0 == 'message' && $message->type1 == 'rfc822' && isset($message->entities[0])) {
900 $read = sqimap_run_command ($imapConnection, "FETCH $passed_id BODY[1.HEADER]", true, $response, $msg, TRUE);
901 $rfc822_header = new Rfc822Header();
902 $rfc822_header->parseHeader($read);
903 $message->rfc822_header = $rfc822_header;
904 } else {
905 $passed_ent_id = 0;
906 }
907 $header = $message->header;
908
909
910 /****************************************/
911 /* Block for handling incoming url vars */
912 /****************************************/
913
914 if (isset($sendreceipt)) {
915 if ( !$message->is_mdnsent ) {
916 $supportMDN = ServerMDNSupport($aMailbox["PERMANENTFLAGS"]);
917 if ( SendMDN( $mailbox, $passed_id, $message, $imapConnection ) > 0 && $supportMDN ) {
918 ToggleMDNflag( true, $imapConnection, $mailbox, $passed_id);
919 $message->is_mdnsent = true;
920 $aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT'] = $message;
921 }
922 }
923 }
924 /***********************************************/
925 /* End of block for handling incoming url vars */
926 /***********************************************/
927
928 $messagebody = '';
929 do_hook('read_body_top', $null);
930 if ($show_html_default == 1) {
931 $ent_ar = $message->findDisplayEntity(array());
932 } else {
933 $ent_ar = $message->findDisplayEntity(array(), array('text/plain'));
934 }
935 $cnt = count($ent_ar);
936 for ($i = 0; $i < $cnt; $i++) {
937 $messagebody .= formatBody($imapConnection, $message, $color, $wrap_at, $ent_ar[$i], $passed_id, $mailbox);
938 if ($i != $cnt-1) {
939 $messagebody .= '<hr />';
940 }
941 }
942
943 /**
944 * Write mailbox with updated seen flag information back to cache.
945 */
946 $mailbox_cache[$iAccount.'_'.$aMailbox['NAME']] = $aMailbox;
947 sqsession_register($mailbox_cache,'mailbox_cache');
948 $_SESSION['mailbox_cache'] = $mailbox_cache;
949
950 // message list URI is used in page header when on read_body
951 $oTemplate->assign('message_list_href', get_message_list_uri($aMailbox['NAME'], $startMessage, $what));
952
953 displayPageHeader($color, $mailbox,'','');
954 formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message,false);
955 formatEnvheader($aMailbox, $passed_id, $passed_ent_id, $message, $color, $FirstTimeSee);
956
957 $oTemplate->assign('message_body', $messagebody);
958 $oTemplate->display('read_message_body.tpl');
959
960 formatAttachments($message,$ent_ar,$mailbox, $passed_id);
961
962 /* show attached images inline -- if pref'fed so */
963 if ($attachment_common_show_images && is_array($attachment_common_show_images_list)) {
964 $images = array();
965 foreach ($attachment_common_show_images_list as $img) {
966 $imgurl = SM_PATH . 'src/download.php' .
967 '?' .
968 'passed_id=' . urlencode($img['passed_id']) .
969 '&amp;mailbox=' . urlencode($mailbox) .
970 '&amp;ent_id=' . urlencode($img['ent_id']) .
971 '&amp;absolute_dl=true';
972 $a = array();
973 $a['Name'] = $img['name'];
974 $a['DisplayURL'] = $imgurl;
975 $a['DownloadURL'] = $img['download_href'];
976 $images[] = $a;
977 }
978
979 $oTemplate->assign('images', $images);
980 $oTemplate->display('read_display_images_inline.tpl');
981 }
982
983 formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message, false, FALSE);
984
985 do_hook('read_body_bottom', $null);
986 sqimap_logout($imapConnection);
987 $oTemplate->display('footer.tpl');