Allowing display of unsafe images when viewing HTML attachments and when HTML is...
[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-2006 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 * Path for SquirrelMail required files.
17 * @ignore
18 */
19 define('SM_PATH','../');
20
21 /* SquirrelMail required files. */
22 include_once(SM_PATH . 'include/validate.php');
23 //require_once(SM_PATH . 'functions/global.php');
24 require_once(SM_PATH . 'functions/imap.php');
25 require_once(SM_PATH . 'functions/mime.php');
26 require_once(SM_PATH . 'functions/date.php');
27 require_once(SM_PATH . 'functions/url_parser.php');
28 require_once(SM_PATH . 'functions/html.php');
29 //require_once(SM_PATH . 'functions/global.php');
30 require_once(SM_PATH . 'functions/identity.php');
31 include_once(SM_PATH . 'functions/arrays.php');
32 include_once(SM_PATH . 'functions/mailbox_display.php');
33
34 /**
35 * Given an IMAP message id number, this will look it up in the cached
36 * and sorted msgs array and return the index of the next message
37 *
38 * @param int $passed_id The current message UID
39 * @return the index of the next valid message from the array
40 */
41 function findNextMessage($uidset,$passed_id='backwards') {
42 if (!is_array($uidset)) {
43 return -1;
44 }
45 if ($passed_id=='backwards' || !is_array($uidset)) { // check for backwards compattibilty gpg plugin
46 $passed_id = $uidset;
47 }
48 $result = sqm_array_get_value_by_offset($uidset,$passed_id,1);
49 if ($result === false) {
50 return -1;
51 } else {
52 return $result;
53 }
54 }
55
56 /**
57 * Given an IMAP message id number, this will look it up in the cached
58 * and sorted msgs array and return the index of the previous message
59 *
60 * @param int $passed_id The current message UID
61 * @return the index of the next valid message from the array
62 */
63
64 function findPreviousMessage($uidset, $passed_id) {
65 if (!is_array($uidset)) {
66 return -1;
67 }
68 $result = sqm_array_get_value_by_offset($uidset,$passed_id,-1);
69 if ($result === false) {
70 return -1;
71 } else {
72 return $result;
73 }
74 }
75
76 /**
77 * Displays a link to a page where the message is displayed more
78 * "printer friendly".
79 * @param string $mailbox Name of current mailbox
80 * @param int $passed_id
81 */
82 function printer_friendly_link($mailbox, $passed_id, $passed_ent_id) {
83 global $javascript_on, $show_html_default;
84
85 /* hackydiehack */
86 if( !sqgetGlobalVar('view_unsafe_images', $view_unsafe_images, SQ_GET) ) {
87 $view_unsafe_images = false;
88 } else {
89 $view_unsafe_images = true;
90 }
91 $params = '?passed_ent_id=' . urlencode($passed_ent_id) .
92 '&mailbox=' . urlencode($mailbox) .
93 '&passed_id=' . urlencode($passed_id) .
94 '&view_unsafe_images='. (bool) $view_unsafe_images .
95 '&show_html_default=' . $show_html_default;
96
97 $print_text = _("View Printable Version");
98
99 $result = '';
100 /* Output the link. */
101 if ($javascript_on) {
102 $result = '<script type="text/javascript">' . "\n" .
103 '<!--' . "\n" .
104 " function printFormat() {\n" .
105 ' window.open("../src/printer_friendly_main.php' .
106 $params . '","Print","width=800,height=600");' . "\n".
107 " }\n" .
108 "// -->\n" .
109 "</script>\n" .
110 "<a href=\"javascript:printFormat();\">$print_text</a>\n";
111 } else {
112 $result = '<a target="_blank" href="../src/printer_friendly_bottom.php' .
113 "$params\">$print_text</a>\n";
114 }
115 return $result;
116 }
117
118 function view_as_html_link($mailbox, $passed_id, $passed_ent_id, $message) {
119 global $base_uri, $show_html_default;
120
121 $has_html = false;
122 if ($message->header->type0 == 'message' && $message->header->type1 == 'rfc822') {
123 $type0 = $message->rfc822_header->content_type->type0;
124 $type1 = $message->rfc822_header->content_type->type1;
125 } else {
126 $type0 = $message->header->type0;
127 $type1 = $message->header->type1;
128 }
129 if($type0 == 'multipart' &&
130 ($type1 == 'alternative' || $type1 == 'mixed' || $type1 == 'related')) {
131 if ($message->findDisplayEntity(array(), array('text/html'), true)) {
132 $has_html = true;
133 }
134 }
135 /*
136 * Normal single part message so check its type.
137 */
138 else {
139 if($type0 == 'text' && $type1 == 'html') {
140 $has_html = true;
141 }
142 }
143 if($has_html == true) {
144 $vars = array('passed_ent_id', 'show_more', 'show_more_cc', 'override_type0', 'override_type1', 'startMessage', 'where', 'what');
145
146 $new_link = $base_uri . 'src/read_body.php?passed_id=' . urlencode($passed_id) .
147 '&amp;passed_ent_id=' . urlencode($passed_ent_id) .
148 '&amp;mailbox=' . urlencode($mailbox);
149 foreach($vars as $var) {
150 if(sqgetGlobalVar($var, $temp)) {
151 $new_link .= '&amp;' . $var . '=' . urlencode($temp);
152 }
153 }
154
155 if($show_html_default == 1) {
156 $new_link .= '&amp;show_html_default=0';
157 $link = _("View as plain text");
158 } else {
159 $new_link .= '&amp;show_html_default=1';
160 $link = _("View as HTML");
161 }
162 return '&nbsp;|&nbsp<a href="' . $new_link . '">' . $link . '</a>';
163 }
164 return '';
165 }
166
167 function ServerMDNSupport($aFlags) {
168 /* escaping $ doesn't work -> \x36 */
169 return ( in_array('$mdnsent',$aFlags,true) ||
170 in_array('\\*',$aFlags,true) ) ;
171 }
172
173 function SendMDN ( $mailbox, $passed_id, $sender, $message, $imapConnection) {
174 global $username, $attachment_dir, $popuser, $username, $color,
175 $version, $squirrelmail_language, $default_charset,
176 $languages, $useSendmail, $domain, $sent_folder;
177
178 sqgetGlobalVar('SERVER_NAME', $SERVER_NAME, SQ_SERVER);
179
180 $header = $message->rfc822_header;
181
182 $rfc822_header = new Rfc822Header();
183 $content_type = new ContentType('multipart/report');
184 $content_type->properties['report-type']='disposition-notification';
185
186 set_my_charset();
187 if ($default_charset) {
188 $content_type->properties['charset']=$default_charset;
189 }
190 $rfc822_header->content_type = $content_type;
191 $rfc822_header->to[] = $header->dnt;
192 $rfc822_header->subject = _("Read:") . ' ' . encodeHeader($header->subject);
193
194 // Patch #793504 Return Receipt Failing with <@> from Tim Craig (burny_md)
195 // This merely comes from compose.php and only happens when there is no
196 // email_addr specified in user's identity (which is the startup config)
197 if (ereg("^([^@%/]+)[@%/](.+)$", $username, $usernamedata)) {
198 $popuser = $usernamedata[1];
199 $domain = $usernamedata[2];
200 unset($usernamedata);
201 } else {
202 $popuser = $username;
203 }
204
205 $reply_to = '';
206 $ident = get_identities();
207 if(!isset($identity)) $identity = 0;
208 $full_name = $ident[$identity]['full_name'];
209 $from_mail = $ident[$identity]['email_address'];
210 $from_addr = '"'.$full_name.'" <'.$from_mail.'>';
211 $reply_to = $ident[$identity]['reply_to'];
212
213 if (!$from_mail) {
214 $from_mail = "$popuser@$domain";
215 $from_addr = $from_mail;
216 }
217 $rfc822_header->from = $rfc822_header->parseAddress($from_addr,true);
218 if ($reply_to) {
219 $rfc822_header->reply_to = $rfc822_header->parseAddress($reply_to,true);
220 }
221
222 // part 1 (RFC2298)
223 $senton = getLongDateString( $header->date );
224 $to_array = $header->to;
225 $to = '';
226 foreach ($to_array as $line) {
227 $to .= ' '.$line->getAddress();
228 }
229 $now = getLongDateString( time() );
230 set_my_charset();
231 $body = _("Your message") . "\r\n\r\n" .
232 "\t" . _("To") . ': ' . decodeHeader($to,false,false) . "\r\n" .
233 "\t" . _("Subject") . ': ' . decodeHeader($header->subject,false,false) . "\r\n" .
234 "\t" . _("Sent") . ': ' . $senton . "\r\n" .
235 "\r\n" .
236 sprintf( _("Was displayed on %s"), $now );
237
238 $special_encoding = '';
239 if (isset($languages[$squirrelmail_language]['XTRA_CODE']) &&
240 function_exists($languages[$squirrelmail_language]['XTRA_CODE'] . '_encode')) {
241 $body = call_user_func($languages[$squirrelmail_language]['XTRA_CODE'] . '_encode', $body);
242 if (strtolower($default_charset) == 'iso-2022-jp') {
243 if (mb_detect_encoding($body) == 'ASCII') {
244 $special_encoding = '8bit';
245 } else {
246 $body = mb_convert_encoding($body, 'JIS');
247 $special_encoding = '7bit';
248 }
249 }
250 } elseif (sq_is8bit($body)) {
251 $special_encoding = '8bit';
252 }
253 $part1 = new Message();
254 $part1->setBody($body);
255 $mime_header = new MessageHeader;
256 $mime_header->type0 = 'text';
257 $mime_header->type1 = 'plain';
258 if ($special_encoding) {
259 $mime_header->encoding = $special_encoding;
260 } else {
261 $mime_header->encoding = 'us-ascii';
262 }
263 if ($default_charset) {
264 $mime_header->parameters['charset'] = $default_charset;
265 }
266 $part1->mime_header = $mime_header;
267
268 // part2 (RFC2298)
269 $original_recipient = $to;
270 $original_message_id = $header->message_id;
271
272 $report = "Reporting-UA : $SERVER_NAME ; SquirrelMail (version $version) \r\n";
273 if ($original_recipient != '') {
274 $report .= "Original-Recipient : $original_recipient\r\n";
275 }
276 $final_recipient = $sender;
277 $report .= "Final-Recipient: rfc822; $final_recipient\r\n" .
278 "Original-Message-ID : $original_message_id\r\n" .
279 "Disposition: manual-action/MDN-sent-manually; displayed\r\n";
280
281 $part2 = new Message();
282 $part2->setBody($report);
283 $mime_header = new MessageHeader;
284 $mime_header->type0 = 'message';
285 $mime_header->type1 = 'disposition-notification';
286 $mime_header->encoding = 'us-ascii';
287 $part2->mime_header = $mime_header;
288
289 $composeMessage = new Message();
290 $composeMessage->rfc822_header = $rfc822_header;
291 $composeMessage->addEntity($part1);
292 $composeMessage->addEntity($part2);
293
294
295 if ($useSendmail) {
296 require_once(SM_PATH . 'class/deliver/Deliver_SendMail.class.php');
297 global $sendmail_path;
298 $deliver = new Deliver_SendMail();
299 $stream = $deliver->initStream($composeMessage,$sendmail_path);
300 } else {
301 require_once(SM_PATH . 'class/deliver/Deliver_SMTP.class.php');
302 $deliver = new Deliver_SMTP();
303 global $smtpServerAddress, $smtpPort, $pop_before_smtp;
304 $authPop = (isset($pop_before_smtp) && $pop_before_smtp) ? true : false;
305 get_smtp_user($user, $pass);
306 $stream = $deliver->initStream($composeMessage,$domain,0,
307 $smtpServerAddress, $smtpPort, $user, $pass, $authPop);
308 }
309 $success = false;
310 if ($stream) {
311 $length = $deliver->mail($composeMessage, $stream);
312 $success = $deliver->finalizeStream($stream);
313 }
314 if (!$success) {
315 $msg = $deliver->dlv_msg;
316 if (! empty($deliver->dlv_server_msg)) {
317 $msg.= '<br />' .
318 _("Server replied:") . ' ' . $deliver->dlv_ret_nr . ' ' .
319 nl2br(htmlspecialchars($deliver->dlv_server_msg));
320 }
321 require_once(SM_PATH . 'functions/display_messages.php');
322 plain_error_message($msg, $color);
323 } else {
324 unset ($deliver);
325 if (sqimap_mailbox_exists ($imapConnection, $sent_folder)) {
326 $sid = sqimap_append ($imapConnection, $sent_folder, $length);
327 require_once(SM_PATH . 'class/deliver/Deliver_IMAP.class.php');
328 $imap_deliver = new Deliver_IMAP();
329 $imap_deliver->mail($composeMessage, $imapConnection);
330 sqimap_append_done ($imapConnection, $sent_folder);
331 unset ($imap_deliver);
332 }
333 }
334 return $success;
335 }
336
337 function ToggleMDNflag ($set ,$imapConnection, $mailbox, $passed_id) {
338 $sg = $set?'+':'-';
339 $cmd = 'STORE ' . $passed_id . ' ' . $sg . 'FLAGS ($MDNSent)';
340 $read = sqimap_run_command ($imapConnection, $cmd, true, $response,
341 $readmessage, TRUE);
342 }
343
344 function formatRecipientString($recipients, $item ) {
345 global $show_more_cc, $show_more, $show_more_bcc,
346 $PHP_SELF;
347
348 $string = '';
349 if ((is_array($recipients)) && (isset($recipients[0]))) {
350 $show = false;
351
352 if ($item == 'to') {
353 if ($show_more) {
354 $show = true;
355 $url = set_url_var($PHP_SELF, 'show_more',0);
356 } else {
357 $url = set_url_var($PHP_SELF, 'show_more',1);
358 }
359 } else if ($item == 'cc') {
360 if ($show_more_cc) {
361 $show = true;
362 $url = set_url_var($PHP_SELF, 'show_more_cc',0);
363 } else {
364 $url = set_url_var($PHP_SELF, 'show_more_cc',1);
365 }
366 } else if ($item == 'bcc') {
367 if ($show_more_bcc) {
368 $show = true;
369 $url = set_url_var($PHP_SELF, 'show_more_bcc',0);
370 } else {
371 $url = set_url_var($PHP_SELF, 'show_more_bcc',1);
372 }
373 }
374
375 $cnt = count($recipients);
376 foreach($recipients as $r) {
377 $add = decodeHeader($r->getAddress(true));
378 if ($string) {
379 $string .= '<br />' . $add;
380 } else {
381 $string = $add;
382 if ($cnt > 1) {
383 $string .= '&nbsp;(<a href="'.$url;
384 if ($show) {
385 $string .= '">'._("less").'</a>)';
386 } else {
387 $string .= '">'._("more").'</a>)';
388 break;
389 }
390 }
391 }
392 }
393 }
394 return $string;
395 }
396
397 function formatEnvheader($aMailbox, $passed_id, $passed_ent_id, $message,
398 $color, $FirstTimeSee) {
399 global $default_use_mdn, $default_use_priority,
400 $show_xmailer_default, $mdn_user_support, $PHP_SELF, $javascript_on,
401 $squirrelmail_language;
402
403 $mailbox = $aMailbox['NAME'];
404
405 $header = $message->rfc822_header;
406 $env = array();
407 $env[_("Subject")] = str_replace("&nbsp;"," ",decodeHeader($header->subject));
408
409 $from_name = $header->getAddr_s('from');
410 if (!$from_name)
411 $from_name = $header->getAddr_s('sender');
412 if (!$from_name)
413 $env[_("From")] = _("Unknown sender");
414 else
415 $env[_("From")] = decodeHeader($from_name);
416 $env[_("Date")] = getLongDateString($header->date);
417 $env[_("To")] = formatRecipientString($header->to, "to");
418 $env[_("Cc")] = formatRecipientString($header->cc, "cc");
419 $env[_("Bcc")] = formatRecipientString($header->bcc, "bcc");
420 if ($default_use_priority) {
421 $env[_("Priority")] = htmlspecialchars(getPriorityStr($header->priority));
422 }
423 if ($show_xmailer_default) {
424 $env[_("Mailer")] = decodeHeader($header->xmailer);
425 }
426 if ($default_use_mdn) {
427 if ($mdn_user_support) {
428 if ($header->dnt) {
429 if ($message->is_mdnsent) {
430 $env[_("Read receipt")] = _("sent");
431 } else {
432 $env[_("Read receipt")] = _("requested");
433 if (!(handleAsSent($mailbox) ||
434 $message->is_deleted ||
435 $passed_ent_id)) {
436 $mdn_url = $PHP_SELF . '&sendreceipt=1';
437 if ($FirstTimeSee && $javascript_on) {
438 $script = '<script type="text/javascript">' . "\n";
439 $script .= '<!--'. "\n";
440 $script .= 'if(window.confirm("' .
441 _("The message sender has requested a response to indicate that you have read this message. Would you like to send a receipt?") .
442 '")) { '."\n" .
443 ' sendMDN()'.
444 '}' . "\n";
445 $script .= '// -->'. "\n";
446 $script .= '</script>'. "\n";
447 echo $script;
448 }
449 $env[_("Read receipt")] .= '&nbsp;<a href="' . $mdn_url . '">[' .
450 _("Send read receipt now") . ']</a>';
451 }
452 }
453 }
454 }
455 }
456
457 $s = '<table width="100%" cellpadding="0" cellspacing="2" border="0"';
458 $s .= ' align="center" bgcolor="'.$color[0].'">';
459 foreach ($env as $key => $val) {
460 if ($val) {
461 $s .= '<tr>';
462 $s .= html_tag('td', '<b>' . $key . ':&nbsp;&nbsp;</b>', 'right', '', 'valign="top" width="20%"') . "\n";
463 $s .= html_tag('td', $val, 'left', '', 'valign="top" width="80%"') . "\n";
464 $s .= '</tr>';
465 }
466 }
467 echo '<table bgcolor="'.$color[9].'" width="100%" cellpadding="1"'.
468 ' cellspacing="0" border="0" align="center">'."\n";
469 echo '<tr><td height="5" colspan="2" bgcolor="'.
470 $color[4].'"></td></tr><tr><td align="center">'."\n";
471 echo $s;
472 do_hook('read_body_header');
473 formatToolbar($mailbox, $passed_id, $passed_ent_id, $message, $color);
474 echo '</table>';
475 echo '</td></tr><tr><td height="5" colspan="2" bgcolor="'.$color[4].'"></td></tr>'."\n";
476 echo '</table>';
477 }
478
479 /**
480 * Format message toolbar
481 *
482 * @param string $mailbox Name of current mailbox
483 * @param int $passed_id UID of current message
484 * @param int $passed_ent_id Id of entity within message
485 * @param object $message Current message object
486 * @param object $mbx_response
487 */
488 function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message, $removedVar, $nav_on_top = TRUE) {
489 global $base_uri, $draft_folder, $where, $what, $color, $sort,
490 $startMessage, $PHP_SELF, $save_as_draft,
491 $enable_forward_as_attachment, $imapConnection, $lastTargetMailbox,
492 $username, $delete_prev_next_display,
493 $compose_new_win, $javascript_on, $compose_width, $compose_height;
494
495 //FIXME cleanup argument list, use $aMailbox where possible
496 $mailbox = $aMailbox['NAME'];
497
498 $topbar_delimiter = '&nbsp;|&nbsp;';
499 $double_delimiter = '&nbsp;&nbsp;&nbsp;&nbsp;';
500 $urlMailbox = urlencode($mailbox);
501
502 $msgs_url = $base_uri . 'src/';
503
504 // BEGIN NAV ROW - PREV/NEXT, DEL PREV/NEXT, LINKS TO INDEX, etc.
505 $nav_row = '<tr><td align="left" colspan="2" style="border: 1px solid '.$color[9].';"><small>';
506
507 // Create Prev & Next links
508 // Handle nested entities first (i.e. Mime Attach parts)
509 if (isset($passed_ent_id) && $passed_ent_id) {
510 // code for navigating through attached message/rfc822 messages
511 $url = set_url_var($PHP_SELF, 'passed_ent_id',0);
512 $entities = array();
513 $entity_count = array();
514 $c = 0;
515
516 foreach($message->parent->entities as $ent) {
517 if ($ent->type0 == 'message' && $ent->type1 == 'rfc822') {
518 $c++;
519 $entity_count[$c] = $ent->entity_id;
520 $entities[$ent->entity_id] = $c;
521 }
522 }
523
524 $prev_link = _("Previous");
525 if(isset($entities[$passed_ent_id]) && $entities[$passed_ent_id] > 1) {
526 $prev_ent_id = $entity_count[$entities[$passed_ent_id] - 1];
527 $prev_link = '<a href="'
528 . set_url_var($PHP_SELF, 'passed_ent_id', $prev_ent_id)
529 . '">' . $prev_link . '</a>';
530 }
531
532 $next_link = _("Next");
533 if(isset($entities[$passed_ent_id]) && $entities[$passed_ent_id] < $c) {
534 $next_ent_id = $entity_count[$entities[$passed_ent_id] + 1];
535 $next_link = '<a href="'
536 . set_url_var($PHP_SELF, 'passed_ent_id', $next_ent_id)
537 . '">' . $next_link . '</a>';
538 }
539
540 $par_ent_id = $message->parent->entity_id;
541 $up_link = '';
542 if ($par_ent_id) {
543 $par_ent_id = substr($par_ent_id,0,-2);
544 if ( $par_ent_id != 0 ) {
545 $up_link = $topbar_delimiter;
546 $url = set_url_var($PHP_SELF, 'passed_ent_id',$par_ent_id);
547 $up_link .= '<a href="'.$url.'">'._("Up").'</a>';
548 }
549 }
550
551 $nav_row .= $prev_link . $up_link . $topbar_delimiter . $next_link;
552 $nav_row .= $double_delimiter . '[<a href="'.$url.'">'._("View Message").'</a>]';
553
554 // Prev/Next links for regular messages
555 } else if ( true ) { //!(isset($where) && isset($what)) ) {
556 $prev = findPreviousMessage($aMailbox['UIDSET'][$what], $passed_id);
557 $next = findNextMessage($aMailbox['UIDSET'][$what],$passed_id);
558
559 $prev_link = _("Previous");
560 if ($prev >= 0) {
561 $uri = $base_uri . 'src/read_body.php?passed_id='.$prev.
562 '&amp;mailbox='.$urlMailbox.'&amp;sort='.$sort.
563 "&amp;where=$where&amp;what=$what" .
564 '&amp;startMessage='.$startMessage.'&amp;show_more=0';
565 $prev_link = '<a href="'.$uri.'">'.$prev_link.'</a>';
566 }
567
568 $next_link = _("Next");
569 if ($next >= 0) {
570 $uri = $base_uri . 'src/read_body.php?passed_id='.$next.
571 '&amp;mailbox='.$urlMailbox.'&amp;sort='.$sort.
572 "&amp;where=$where&amp;what=$what" .
573 '&amp;startMessage='.$startMessage.'&amp;show_more=0';
574 $next_link = '<a href="'.$uri.'">'.$next_link.'</a>';
575 }
576
577 // Only bother with Delete & Prev and Delete & Next IF
578 // top display is enabled.
579 if ( $delete_prev_next_display == 1 &&
580 in_array('\\deleted', $aMailbox['PERMANENTFLAGS'],true) ) {
581 $del_prev_link = _("Delete & Prev");
582 if ($prev >= 0) {
583 $uri = $base_uri . 'src/read_body.php?passed_id='.$prev.
584 '&amp;mailbox='.$urlMailbox.'&amp;sort='.$sort.
585 '&amp;startMessage='.$startMessage.'&amp;show_more=0'.
586 "&amp;where=$where&amp;what=$what" .
587 '&amp;delete_id='.$passed_id;
588 $del_prev_link = '<a href="'.$uri.'">'.$del_prev_link.'</a>';
589 }
590
591 $del_next_link = _("Delete & Next");
592 if ($next >= 0) {
593 $uri = $base_uri . 'src/read_body.php?passed_id='.$next.
594 '&amp;mailbox='.$urlMailbox.'&amp;sort='.$sort.
595 '&amp;startMessage='.$startMessage.'&amp;show_more=0'.
596 "&amp;where=$where&amp;what=$what" .
597 '&amp;delete_id='.$passed_id;
598 $del_next_link = '<a href="'.$uri.'">'.$del_next_link.'</a>';
599 }
600 }
601
602 $nav_row .= '['.$prev_link.$topbar_delimiter.$next_link.']';
603 if ( isset($del_prev_link) && isset($del_next_link) )
604 $nav_row .= $double_delimiter.'['.$del_prev_link.$topbar_delimiter.$del_next_link.']';
605 }
606
607 // Start with Search Results or Message List link.
608 $msgs_url .= "$where?where=read_body.php&amp;what=$what&amp;mailbox=" . $urlMailbox.
609 "&amp;startMessage=$startMessage";
610 if ($where == 'search.php') {
611 $msgs_str = _("Search Results");
612 } else {
613 $msgs_str = _("Message List");
614 }
615 $nav_row .= $double_delimiter .
616 '[<a href="' . $msgs_url . '">' . $msgs_str . '</a>]';
617
618 $nav_row .= '</small></td></tr>';
619
620
621 // BEGIN MENU ROW - DELETE/REPLY/FORWARD/MOVE/etc.
622 $menu_row = '<tr bgcolor="'.$color[0].'"><td><small>';
623 $comp_uri = $base_uri.'src/compose.php' .
624 '?passed_id=' . $passed_id .
625 '&amp;mailbox=' . $urlMailbox .
626 '&amp;startMessage=' . $startMessage .
627 (isset($passed_ent_id) ? '&amp;passed_ent_id='.$passed_ent_id : '');
628
629 // Start form for reply/reply all/forward..
630 $target = '';
631 $on_click='';
632 $method='method="post" ';
633 $onsubmit='';
634 if ($compose_new_win == '1') {
635 if (!preg_match("/^[0-9]{3,4}$/", $compose_width)) {
636 $compose_width = '640';
637 }
638 if (!preg_match("/^[0-9]{3,4}$/", $compose_height)) {
639 $compose_height = '550';
640 }
641 if ( $javascript_on ) {
642 $on_click=' onclick="comp_in_new_form(\''.$comp_uri.'\', this, this.form,'. $compose_width .',' . $compose_height .')"';
643 $comp_uri = 'javascript:void(0)';
644 $method='method="get" ';
645 $onsubmit = 'onsubmit="return false" ';
646 } else {
647 $target = 'target="_blank"';
648 }
649 }
650
651 $menu_row .= "\n".'<form name="composeForm" action="'.$comp_uri.'" '
652 . $method.$target.$onsubmit.' style="display: inline">'."\n";
653
654 // If Draft folder - create Resume link
655 if (($mailbox == $draft_folder) && ($save_as_draft)) {
656 $new_button = 'smaction_draft';
657 $comp_alt_string = _("Resume Draft");
658 } else if (handleAsSent($mailbox)) {
659 // If in Sent folder, edit as new
660 $new_button = 'smaction_edit_new';
661 $comp_alt_string = _("Edit Message as New");
662 }
663 // Show Alt URI for Draft/Sent
664 if (isset($comp_alt_string))
665 $menu_row .= getButton('submit', $new_button, $comp_alt_string, $on_click) . "\n";
666
667 $menu_row .= getButton('submit', 'smaction_reply', _("Reply"), $on_click) . "\n";
668 $menu_row .= getButton('submit', 'smaction_reply_all', _("Reply All"), $on_click) ."\n";
669 $menu_row .= getButton('submit', 'smaction_forward', _("Forward"), $on_click);
670 if ($enable_forward_as_attachment)
671 $menu_row .= '<input type="checkbox" name="smaction_attache" />' . _("As Attachment") .'&nbsp;&nbsp;'."\n";
672
673 $menu_row .= '</form>&nbsp;';
674
675 if ( in_array('\\deleted', $aMailbox['PERMANENTFLAGS'],true) ) {
676 // Form for deletion. Form is handled by the originating display in $where. This is right_main.php or search.php
677 $delete_url = $base_uri . "src/$where";
678 $menu_row .= '<form name="deleteMessageForm" action="'.$delete_url.'" method="post" style="display: inline">';
679
680 if (!(isset($passed_ent_id) && $passed_ent_id)) {
681 $menu_row .= addHidden('mailbox', $aMailbox['NAME']);
682 $menu_row .= addHidden('msg[0]', $passed_id);
683 $menu_row .= addHidden('startMessage', $startMessage);
684 $menu_row .= getButton('submit', 'delete', _("Delete"));
685 $menu_row .= '<input type="checkbox" name="bypass_trash" />' . _("Bypass Trash");
686 } else {
687 $menu_row .= getButton('submit', 'delete', _("Delete"), '', FALSE) . "\n"; // delete button is disabled
688 }
689
690 $menu_row .= '</form>';
691 }
692
693 // Add top move link
694 $menu_row .= '</small></td><td align="right">';
695 if ( !(isset($passed_ent_id) && $passed_ent_id) &&
696 in_array('\\deleted', $aMailbox['PERMANENTFLAGS'],true) ) {
697
698 $menu_row .= '<form name="moveMessageForm" action="'.$base_uri.'src/'.$where.'?'.'" method="post" style="display: inline">'.
699 '<small>'.
700
701 addHidden('mailbox',$aMailbox['NAME']) .
702 addHidden('msg[0]', $passed_id) . _("Move to:") .
703 '<select name="targetMailbox" style="padding: 0px; margin: 0px">';
704
705 if (isset($lastTargetMailbox) && !empty($lastTargetMailbox)) {
706 $menu_row .= sqimap_mailbox_option_list($imapConnection, array(strtolower($lastTargetMailbox)));
707 } else {
708 $menu_row .= sqimap_mailbox_option_list($imapConnection);
709 }
710 $menu_row .= '</select> ';
711
712 $menu_row .= getButton('submit', 'moveButton',_("Move")) . "\n" . '</form>';
713 }
714 $menu_row .= '</td></tr>';
715
716 // echo rows, with hooks
717 $ret = do_hook_function('read_body_menu_top', array($nav_row, $menu_row));
718 if (is_array($ret)) {
719 if (isset($ret[0]) && !empty($ret[0])) {
720 $nav_row = $ret[0];
721 }
722 if (isset($ret[1]) && !empty($ret[1])) {
723 $menu_row = $ret[1];
724 }
725 }
726 echo '<table width="100%" cellpadding="3" cellspacing="0" align="center" border="0">';
727 echo $nav_on_top ? $nav_row . $menu_row : $menu_row . $nav_row;
728 echo '</table>'."\n";
729 do_hook('read_body_menu_bottom');
730 }
731
732 function formatToolbar($mailbox, $passed_id, $passed_ent_id, $message, $color) {
733 global $base_uri, $where, $what, $download_and_unsafe_link;
734
735 $urlMailbox = urlencode($mailbox);
736 $urlPassed_id = urlencode($passed_id);
737 $urlPassed_ent_id = urlencode($passed_ent_id);
738
739 $query_string = 'mailbox=' . $urlMailbox . '&amp;passed_id=' . $urlPassed_id . '&amp;passed_ent_id=' . $urlPassed_ent_id;
740
741 if (!empty($where)) {
742 $query_string .= '&amp;where=' . urlencode($where);
743 }
744
745 if (!empty($what)) {
746 $query_string .= '&amp;what=' . urlencode($what);
747 }
748
749 $url = $base_uri.'src/view_header.php?'.$query_string;
750
751 $s = "<tr>\n" .
752 html_tag( 'td', '', 'right', '', 'valign="middle" width="20%"' ) . '<b>' . _("Options") . ":&nbsp;&nbsp;</b></td>\n" .
753 html_tag( 'td', '', 'left', '', 'valign="middle" width="80%"' ) . '<small>' .
754 '<a href="'.$url.'">'._("View Full Header").'</a>';
755
756 /* Output the printer friendly link if we are in subtle mode. */
757 $s .= '&nbsp;|&nbsp;' .
758 printer_friendly_link($mailbox, $passed_id, $passed_ent_id);
759 echo $s;
760 echo view_as_html_link($mailbox, $passed_id, $passed_ent_id, $message);
761
762 /* Output the download and/or unsafe images link/-s, if any. */
763 if ($download_and_unsafe_link) {
764 echo $download_and_unsafe_link;
765 }
766
767 do_hook("read_body_header_right");
768 $s = "</small></td>\n" .
769 "</tr>\n";
770 echo $s;
771
772 }
773
774 /**
775 * Creates button
776 *
777 * @deprecated see form functions available in 1.5.1 and 1.4.3.
778 * @param string $type
779 * @param string $name
780 * @param string $value
781 * @param string $js
782 * @param bool $enabled
783 */
784 function getButton($type, $name, $value, $js = '', $enabled = TRUE) {
785 $disabled = ( $enabled ? '' : 'disabled ' );
786 $js = ( $js ? $js.' ' : '' );
787 return '<input '.$disabled.$js.
788 'type="'.$type.
789 '" name="'.$name.
790 '" value="'.$value .
791 '" style="padding: 0px; margin: 0px" />';
792 }
793
794
795 /***************************/
796 /* Main of read_body.php */
797 /***************************/
798
799 /* get the globals we may need */
800
801 sqgetGlobalVar('key', $key, SQ_COOKIE);
802 sqgetGlobalVar('username', $username, SQ_SESSION);
803 sqgetGlobalVar('onetimepad',$onetimepad, SQ_SESSION);
804 sqgetGlobalVar('delimiter', $delimiter, SQ_SESSION);
805 sqgetGlobalVar('base_uri', $base_uri, SQ_SESSION);
806 sqgetGlobalVar('lastTargetMailbox', $lastTargetMailbox, SQ_SESSION);
807 if (!sqgetGlobalVar('messages', $messages, SQ_SESSION) ) {
808 $messages = array();
809 }
810 sqgetGlobalVar('delayed_errors', $delayed_errors, SQ_SESSION);
811 if (is_array($delayed_errors)) {
812 $oErrorHandler->AssignDelayedErrors($delayed_errors);
813 sqsession_unregister("delayed_errors");
814 }
815 /** GET VARS */
816 sqgetGlobalVar('sendreceipt', $sendreceipt, SQ_GET);
817 if (!sqgetGlobalVar('where', $where, SQ_GET) ) {
818 $where = 'right_main.php';
819 }
820 /*
821 * Used as entry key to the list of uid's cached in the mailbox cache
822 * we use the cached uid's to get the next and prev message.
823 */
824 if (!sqgetGlobalVar('what', $what, SQ_GET) ){
825 $what = 0;
826 }
827 if ( sqgetGlobalVar('show_more', $temp, SQ_GET) ) {
828 $show_more = (int) $temp;
829 }
830 if ( sqgetGlobalVar('show_more_cc', $temp, SQ_GET) ) {
831 $show_more_cc = (int) $temp;
832 }
833 if ( sqgetGlobalVar('show_more_bcc', $temp, SQ_GET) ) {
834 $show_more_bcc = (int) $temp;
835 }
836 if ( sqgetGlobalVar('view_hdr', $temp, SQ_GET) ) {
837 $view_hdr = (int) $temp;
838 }
839
840 if ( sqgetGlobalVar('account', $temp, SQ_GET) ) {
841 $iAccount = (int) $temp;
842 } else {
843 $iAccount = 0;
844 }
845
846 /** GET/POST VARS */
847 sqgetGlobalVar('passed_ent_id', $passed_ent_id);
848 sqgetGlobalVar('mailbox', $mailbox);
849
850 if ( sqgetGlobalVar('passed_id', $temp) ) {
851 $passed_id = (int) $temp;
852 }
853 if ( sqgetGlobalVar('sort', $temp) ) {
854 $sort = (int) $temp;
855 }
856 if ( sqgetGlobalVar('startMessage', $temp) ) {
857 $startMessage = (int) $temp;
858 } else {
859 $startMessage = 1;
860 }
861 if(sqgetGlobalVar('show_html_default', $temp)) {
862 $show_html_default = (int) $temp;
863 }
864
865 if(sqgetGlobalVar('view_unsafe_images', $temp)) {
866 $view_unsafe_images = (int) $temp;
867 if($view_unsafe_images == 1) {
868 $show_html_default = 1;
869 }
870 } else {
871 $view_unsafe_images = 0;
872 }
873 /**
874 * Retrieve mailbox cache
875 */
876 sqgetGlobalVar('mailbox_cache',$mailbox_cache,SQ_SESSION);
877
878 /* end of get globals */
879 global $sqimap_capabilities, $lastTargetMailbox;
880
881 $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0);
882 $aMailbox = sqm_api_mailbox_select($imapConnection, $iAccount, $mailbox,array('setindex' => $what, 'offset' => $startMessage),array());
883
884
885 /**
886 Start code to set the columns to fetch in case of hitting the next/prev link
887 The reason for this is the fact that the cache can be invalidated which means that the headers
888 to fetch aren't there anymore. Before they got calculated when the messagelist was shown.
889
890 Todo, better central handling of setting the mailbox options so we do not need to do the stuff below
891 */
892
893 /**
894 * Replace From => To in case it concerns a draft or sent folder
895 */
896 $aColumns = array();
897 if (($mailbox == $sent_folder || $mailbox == $draft_folder) &&
898 !in_array(SQM_COL_TO,$index_order)) {
899 $aNewOrder = array(); // nice var name ;)
900 foreach($index_order as $iCol) {
901 if ($iCol == SQM_COL_FROM) {
902 $iCol = SQM_COL_TO;
903 }
904 $aColumns[$iCol] = array();
905 }
906 } else {
907 foreach ($index_order as $iCol) {
908 $aColumns[$iCol] = array();
909 }
910 }
911
912 $aProps = array(
913 'columns' => $aColumns, // columns bound settings
914 'config' => array(
915 'highlight_list' => $message_highlight_list, // row highlighting rules
916 'trash_folder' => $trash_folder,
917 'sent_folder' => $sent_folder,
918 'draft_folder' => $draft_folder));
919
920 calcFetchColumns($aMailbox,$aProps);
921
922 /**
923 End code to set the columns to fetch in case of hitting the next/prev link
924 */
925
926
927
928 /**
929 * Check if cache is still valid, $what contains the key
930 * which gives us acces to the array with uid's. At this moment
931 * 0 is used for a normal message list and search uses 1 as key. This can be
932 * changed / extended in the future.
933 * If on a select of a mailbox we detect that the cache should be invalidated due to
934 * the delete of messages or due to new messages we empty the list with uid's and
935 * that's what we detect below.
936 */
937 if (!is_array($aMailbox['UIDSET'][$what])) {
938 fetchMessageHeaders($imapConnection, $aMailbox);
939 }
940
941 $iSetIndex = $aMailbox['SETINDEX'];
942 $aMailbox['CURRENT_MSG'][$iSetIndex] = $passed_id;
943
944 /**
945 * Update the seen state
946 * and ignore in_array('\\seen',$aMailbox['PERMANENTFLAGS'],true)
947 */
948 if (isset($aMailbox['MSG_HEADERS'][$passed_id]['FLAGS'])) {
949 $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\seen'] = true;
950 }
951
952 /**
953 * Process Delete from delete-move-next
954 * but only if delete_id was set
955 */
956 if ( sqgetGlobalVar('delete_id', $delete_id, SQ_GET) ) {
957 handleMessageListForm($imapConnection,$aMailbox,$sButton='setDeleted', array($delete_id));
958 }
959
960 /**
961 * $message contains all information about the message
962 * including header and body
963 */
964
965 if (isset($aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT'])) {
966 $message = $aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT'];
967 $FirstTimeSee = !$message->is_seen;
968 } else {
969 $message = sqimap_get_message($imapConnection, $passed_id, $mailbox);
970 $FirstTimeSee = !$message->is_seen;
971 $message->is_seen = true;
972 $aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT'] = $message;
973 }
974 if (isset($passed_ent_id) && $passed_ent_id) {
975 $message = $message->getEntity($passed_ent_id);
976 if ($message->type0 != 'message' && $message->type1 != 'rfc822') {
977 $message = $message->parent;
978 }
979 $read = sqimap_run_command ($imapConnection, "FETCH $passed_id BODY[$passed_ent_id.HEADER]", true, $response, $msg, TRUE);
980 $rfc822_header = new Rfc822Header();
981 $rfc822_header->parseHeader($read);
982 $message->rfc822_header = $rfc822_header;
983 } else if ($message->type0 == 'message' && $message->type1 == 'rfc822' && isset($message->entities[0])) {
984 $read = sqimap_run_command ($imapConnection, "FETCH $passed_id BODY[1.HEADER]", true, $response, $msg, TRUE);
985 $rfc822_header = new Rfc822Header();
986 $rfc822_header->parseHeader($read);
987 $message->rfc822_header = $rfc822_header;
988 } else {
989 $passed_ent_id = 0;
990 }
991 $header = $message->header;
992
993
994 /****************************************/
995 /* Block for handling incoming url vars */
996 /****************************************/
997
998 if (isset($sendreceipt)) {
999 if ( !$message->is_mdnsent ) {
1000 $final_recipient = '';
1001 if ((isset($identity)) && ($identity != 0)) //Main identity
1002 $final_recipient = trim(getPref($data_dir, $username, 'email_address' . $identity, '' ));
1003 if ($final_recipient == '' )
1004 $final_recipient = trim(getPref($data_dir, $username, 'email_address', '' ));
1005 $supportMDN = ServerMDNSupport($aMailbox["PERMANENTFLAGS"]);
1006 if ( SendMDN( $mailbox, $passed_id, $final_recipient, $message, $imapConnection ) > 0 && $supportMDN ) {
1007 ToggleMDNflag( true, $imapConnection, $mailbox, $passed_id);
1008 $message->is_mdnsent = true;
1009 $aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT'] = $message;
1010 }
1011 }
1012 }
1013 /***********************************************/
1014 /* End of block for handling incoming url vars */
1015 /***********************************************/
1016
1017 $messagebody = '';
1018 do_hook('read_body_top');
1019 if ($show_html_default == 1) {
1020 $ent_ar = $message->findDisplayEntity(array());
1021 } else {
1022 $ent_ar = $message->findDisplayEntity(array(), array('text/plain'));
1023 }
1024 $cnt = count($ent_ar);
1025 for ($i = 0; $i < $cnt; $i++) {
1026 $messagebody .= formatBody($imapConnection, $message, $color, $wrap_at, $ent_ar[$i], $passed_id, $mailbox);
1027 if ($i != $cnt-1) {
1028 $messagebody .= '<hr style="height: 1px;" />';
1029 }
1030 }
1031
1032 displayPageHeader($color, $mailbox,'','');
1033 formatMenuBar($aMailbox, $passed_id, $passed_ent_id, $message,false);
1034 formatEnvheader($aMailbox, $passed_id, $passed_ent_id, $message, $color, $FirstTimeSee);
1035 echo '<table width="100%" cellpadding="0" cellspacing="0" align="center" border="0">';
1036 echo ' <tr><td>';
1037 echo ' <table width="100%" cellpadding="1" cellspacing="0" align="center" border="0" bgcolor="'.$color[9].'">';
1038 echo ' <tr><td>';
1039 echo ' <table width="100%" cellpadding="3" cellspacing="0" align="center" border="0">';
1040 echo ' <tr bgcolor="'.$color[4].'"><td>';
1041 // echo ' <table cellpadding="1" cellspacing="5" align="left" border="0">';
1042 echo html_tag( 'table' ,'' , 'left', '', 'width="100%" cellpadding="1" cellspacing="5" border="0"' );
1043 echo ' <tr>' . html_tag( 'td', '<br />'. $messagebody."\n", 'left')
1044 . '</tr>';
1045 echo ' </table>';
1046 echo ' </td></tr>';
1047 echo ' </table></td></tr>';
1048 echo ' </table>';
1049 echo ' </td></tr>';
1050
1051 echo '<tr><td height="5" colspan="2" bgcolor="'.
1052 $color[4].'"></td></tr>'."\n";
1053
1054 $attachmentsdisplay = formatAttachments($message,$ent_ar,$mailbox, $passed_id);
1055 if ($attachmentsdisplay) {
1056 echo ' </table>';
1057 echo ' <table width="100%" cellpadding="1" cellspacing="0" align="center"'.' border="0" bgcolor="'.$color[9].'">';
1058 echo ' <tr><td>';
1059 echo ' <table width="100%" cellpadding="0" cellspacing="0" align="center" border="0" bgcolor="'.$color[4].'">';
1060 echo ' <tr>' . html_tag( 'td', '', 'left', $color[9] );
1061 echo ' <b>' . _("Attachments") . ':</b>';
1062 echo ' </td></tr>';
1063 echo ' <tr><td>';
1064 echo ' <table width="100%" cellpadding="2" cellspacing="2" align="center"'.' border="0" bgcolor="'.$color[0].'"><tr><td>';
1065 echo $attachmentsdisplay;
1066 echo ' </td></tr></table>';
1067 echo ' </td></tr></table>';
1068 echo ' </td></tr>';
1069 echo '<tr><td height="5" colspan="2" bgcolor="'.
1070 $color[4].'"></td></tr>';
1071 }
1072 echo '</table>';
1073
1074 /* show attached images inline -- if pref'fed so */
1075 if (($attachment_common_show_images) &&
1076 is_array($attachment_common_show_images_list)) {
1077 foreach ($attachment_common_show_images_list as $img) {
1078 $imgurl = SM_PATH . 'src/download.php' .
1079 '?' .
1080 'passed_id=' . urlencode($img['passed_id']) .
1081 '&amp;mailbox=' . urlencode($mailbox) .
1082 '&amp;ent_id=' . urlencode($img['ent_id']) .
1083 '&amp;absolute_dl=true';
1084
1085 echo html_tag( 'table', "\n" .
1086 html_tag( 'tr', "\n" .
1087 html_tag( 'td', '<img src="' . $imgurl . '" />' ."\n", 'left'
1088 )
1089 ) ,
1090 'center', '', 'cellspacing="0" border="0" cellpadding="2"');
1091 }
1092 }
1093
1094 formatMenuBar($aMailbox, $passed_id, $passed_ent_id, $message, false, FALSE);
1095
1096 do_hook('read_body_bottom');
1097 sqimap_logout($imapConnection);
1098
1099 /**
1100 * Write mailbox with updated seen flag information back to cache.
1101 */
1102 $mailbox_cache[$iAccount.'_'.$aMailbox['NAME']] = $aMailbox;
1103 sqsession_register($mailbox_cache,'mailbox_cache');
1104 $oTemplate->display('footer.tpl');
1105 ?>