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