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