alecpl
2008-10-06 a164a2e64b65fbe0729f6d4326b0219f1914c139
commit | author | age
4e17e6 1 <?php
T 2
3 /*
4  +-----------------------------------------------------------------------+
5  | program/steps/mail/func.inc                                           |
6  |                                                                       |
7  | This file is part of the RoundCube Webmail client                     |
8fa58e 8  | Copyright (C) 2005-2008, RoundCube Dev. - Switzerland                 |
30233b 9  | Licensed under the GNU GPL                                            |
4e17e6 10  |                                                                       |
T 11  | PURPOSE:                                                              |
12  |   Provide webmail functionality and GUI objects                       |
13  |                                                                       |
14  +-----------------------------------------------------------------------+
15  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
16  +-----------------------------------------------------------------------+
17
18  $Id$
19
20 */
21
22 require_once('lib/enriched.inc');
fba1f5 23 require_once('include/rcube_smtp.inc');
4e17e6 24
T 25
26 $EMAIL_ADDRESS_PATTERN = '/([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9]\\.[a-z]{2,5})/i';
27
f11541 28 if (empty($_SESSION['mbox']))
c5ac07 29   $_SESSION['mbox'] = $IMAP->get_mailbox_name();
S 30
4e17e6 31 // set imap properties and session vars
b3ce79 32 if ($mbox = get_input_value('_mbox', RCUBE_INPUT_GPC))
c57996 33   $IMAP->set_mailbox(($_SESSION['mbox'] = $mbox));
4e17e6 34
b3ce79 35 if (!empty($_GET['_page']))
c57996 36   $IMAP->set_page(($_SESSION['page'] = intval($_GET['_page'])));
4e17e6 37
fecb03 38 // set mailbox to INBOX if not set
T 39 if (empty($_SESSION['mbox']))
40   $_SESSION['mbox'] = $IMAP->get_mailbox_name();
4e17e6 41
6a35c8 42 // set default sort col/order to session
T 43 if (!isset($_SESSION['sort_col']))
44   $_SESSION['sort_col'] = $CONFIG['message_sort_col'];
45 if (!isset($_SESSION['sort_order']))
46   $_SESSION['sort_order'] = $CONFIG['message_sort_order'];
2bca6e 47
T 48 // set message set for search result
8d0758 49 if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']]))
1f020b 50   {
8d0758 51   $IMAP->set_search_set($_SESSION['search'][$_REQUEST['_search']]);
1f020b 52   $OUTPUT->set_env('search_request', $_REQUEST['_search']);
S 53   $OUTPUT->set_env('search_text', $_SESSION['last_text_search']);
54   }
4e17e6 55
528514 56 // set main env variables, labels and page title
197601 57 if (empty($RCMAIL->action) || $RCMAIL->action == 'list')
528514 58   {
A 59   // set current mailbox in client environment
60   $OUTPUT->set_env('mailbox', $IMAP->get_mailbox_name());
61   $OUTPUT->set_env('quota', $IMAP->get_capability('quota'));
62   $OUTPUT->set_env('delimiter', $IMAP->get_hierarchy_delimiter());
63
64   if ($CONFIG['trash_mbox'])
65     $OUTPUT->set_env('trash_mailbox', $CONFIG['trash_mbox']);
66   if ($CONFIG['drafts_mbox'])
67     $OUTPUT->set_env('drafts_mailbox', $CONFIG['drafts_mbox']);
68   if ($CONFIG['junk_mbox'])
69     $OUTPUT->set_env('junk_mailbox', $CONFIG['junk_mbox']);
70
71   if (!$OUTPUT->ajax_call)
112c91 72     $OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash', 'movingmessage');
528514 73
fed22f 74   $OUTPUT->set_pagetitle(rcmail_localize_foldername($IMAP->get_mailbox_name()));
a86204 75   }
5eee00 76
4e17e6 77
45f56c 78 /**
T 79  * return the message list as HTML table
80  */
4e17e6 81 function rcmail_message_list($attrib)
T 82   {
f11541 83   global $IMAP, $CONFIG, $COMM_PATH, $OUTPUT;
b076a4 84
4e17e6 85   $skin_path = $CONFIG['skin_path'];
e189a6 86   $image_tag = '<img src="%s%s" alt="%s" />';
b076a4 87
f3b659 88   // check to see if we have some settings for sorting
6a35c8 89   $sort_col   = $_SESSION['sort_col'];
T 90   $sort_order = $_SESSION['sort_order'];
24053e 91   
T 92   // add some labels to client
112c91 93   $OUTPUT->add_label('from', 'to');
f3b659 94
4e17e6 95   // get message headers
f3b659 96   $a_headers = $IMAP->list_headers('', '', $sort_col, $sort_order);
4e17e6 97
T 98   // add id to message list table if not specified
99   if (!strlen($attrib['id']))
100     $attrib['id'] = 'rcubemessagelist';
101
102   // allow the following attributes to be added to the <table> tag
103   $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary'));
104
105   $out = '<table' . $attrib_str . ">\n";
e0ddd4 106
4e17e6 107   // define list of cols to be displayed
T 108   $a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject');
c8c1e0 109   $a_sort_cols = array('subject', 'date', 'from', 'to', 'size');
41bece 110
T 111   $mbox = $IMAP->get_mailbox_name();
4e17e6 112   
T 113   // show 'to' instead of from in sent messages
41bece 114   if (($mbox==$CONFIG['sent_mbox'] || $mbox==$CONFIG['drafts_mbox']) && ($f = array_search('from', $a_show_cols))
8c2e58 115       && !array_search('to', $a_show_cols))
4e17e6 116     $a_show_cols[$f] = 'to';
8c2e58 117   
e0ddd4 118   // add col definition
T 119   $out .= '<colgroup>';
01c86f 120   $out .= '<col class="icon" />';
e0ddd4 121
T 122   foreach ($a_show_cols as $col)
01c86f 123     $out .= sprintf('<col class="%s" />', $col);
e0ddd4 124
01c86f 125   $out .= '<col class="icon" />';
e0ddd4 126   $out .= "</colgroup>\n";
4e17e6 127
T 128   // add table title
129   $out .= "<thead><tr>\n<td class=\"icon\">&nbsp;</td>\n";
b076a4 130
f3b659 131   $javascript = '';
4e17e6 132   foreach ($a_show_cols as $col)
f3b659 133     {
T 134     // get column name
e189a6 135     $col_name = $col != 'flag' ? Q(rcube_label($col)) : sprintf($image_tag, $skin_path, $attrib['unflaggedicon'], '');
f3b659 136
T 137     // make sort links
138     $sort = '';
2a9cb3 139     if (in_array($col, $a_sort_cols))
f3b659 140       {
1cded8 141       // have buttons configured
T 142       if (!empty($attrib['sortdescbutton']) || !empty($attrib['sortascbutton']))
143         {
144         $sort = '&nbsp;&nbsp;';
b076a4 145
1cded8 146         // asc link
T 147         if (!empty($attrib['sortascbutton']))
148           {
f11541 149           $sort .= $OUTPUT->button(array(
T 150             'command' => 'sort',
151             'prop' => $col.'_ASC',
152             'image' => $attrib['sortascbutton'],
153             'align' => 'absmiddle',
154             'title' => 'sortasc'));
1cded8 155           }       
b076a4 156         
1cded8 157         // desc link
T 158         if (!empty($attrib['sortdescbutton']))
159           {
f11541 160           $sort .= $OUTPUT->button(array(
T 161             'command' => 'sort',
162             'prop' => $col.'_DESC',
163             'image' => $attrib['sortdescbutton'],
164             'align' => 'absmiddle',
165             'title' => 'sortdesc'));
1cded8 166           }
T 167         }
168       // just add a link tag to the header
169       else
b076a4 170         {
41bece 171         $col_name = sprintf(
T 172           '<a href="./#sort" onclick="return %s.command(\'sort\',\'%s\',this)" title="%s">%s</a>',
173           JS_OBJECT_NAME,
174           $col,
175           rcube_label('sortby'),
176           $col_name);
b076a4 177         }
f3b659 178       }
b076a4 179       
T 180     $sort_class = $col==$sort_col ? " sorted$sort_order" : '';
f3b659 181
T 182     // put it all together
b076a4 183     $out .= '<td class="'.$col.$sort_class.'" id="rcmHead'.$col.'">' . "$col_name$sort</td>\n";    
f3b659 184     }
4e17e6 185
a86204 186   $out .= '<td class="icon">'.($attrib['attachmenticon'] ? sprintf($image_tag, $skin_path, $attrib['attachmenticon'], '') : '&nbsp;')."</td>\n";
4e17e6 187   $out .= "</tr></thead>\n<tbody>\n";
T 188
189   // no messages in this mailbox
190   if (!sizeof($a_headers))
5eee00 191     $OUTPUT->show_message('nomessagesfound', 'notice');
4e17e6 192
T 193
194   $a_js_message_arr = array();
195
196   // create row for each message
197   foreach ($a_headers as $i => $header)  //while (list($i, $header) = each($a_headers))
198     {
e189a6 199     $message_icon = $attach_icon = $flagged_icon = '';
4e17e6 200     $js_row_arr = array();
a164a2 201     $zebra_class = $i%2 ? ' even' : ' odd';
4e17e6 202
T 203     // set messag attributes to javascript array
6ec0a8 204     if ($header->deleted)
S 205       $js_row_arr['deleted'] = true;
4e17e6 206     if (!$header->seen)
T 207       $js_row_arr['unread'] = true;
208     if ($header->answered)
209       $js_row_arr['replied'] = true;
d73404 210     if ($header->forwarded)
A 211       $js_row_arr['forwarded'] = true;
e189a6 212     if ($header->flagged)
A 213       $js_row_arr['flagged'] = true;
214
6ec0a8 215     // set message icon  
S 216     if ($attrib['deletedicon'] && $header->deleted)
217       $message_icon = $attrib['deletedicon'];
d73404 218     else if ($attrib['repliedicon'] && $header->answered)
A 219       {
220       if ($attrib['forwardedrepliedicon'] && $header->forwarded)
221         $message_icon = $attrib['forwardedrepliedicon'];
222       else
223         $message_icon = $attrib['repliedicon'];
224       }
225     else if ($attrib['forwardedicon'] && $header->forwarded)
226       $message_icon = $attrib['forwardedicon'];
6ec0a8 227     else if ($attrib['unreadicon'] && !$header->seen)
4e17e6 228       $message_icon = $attrib['unreadicon'];
T 229     else if ($attrib['messageicon'])
230       $message_icon = $attrib['messageicon'];
e189a6 231
A 232     if ($attrib['flaggedicon'] && $header->flagged)
233       $flagged_icon = $attrib['flaggedicon'];
234     else if ($attrib['unflaggedicon'] && !$header->flagged)
235       $flagged_icon = $attrib['unflaggedicon'];
4e17e6 236     
f11541 237     // set attachment icon
8d4bcd 238     if ($attrib['attachmenticon'] && preg_match("/multipart\/[mr]/i", $header->ctype))
4e17e6 239       $attach_icon = $attrib['attachmenticon'];
T 240         
a164a2 241     $out .= sprintf('<tr id="rcmrow%d" class="message%s%s%s%s">'."\n",
15a9d1 242                     $header->uid,
T 243                     $header->seen ? '' : ' unread',
244                     $header->deleted ? ' deleted' : '',
e189a6 245                     $header->flagged ? ' flagged' : '',
a164a2 246                     $zebra_class);
15a9d1 247     
4e17e6 248     $out .= sprintf("<td class=\"icon\">%s</td>\n", $message_icon ? sprintf($image_tag, $skin_path, $message_icon, '') : '');
e189a6 249
1088d6 250
583850 251     if (!empty($header->charset))
A 252       $IMAP->set_charset($header->charset);
253   
4e17e6 254     // format each col
T 255     foreach ($a_show_cols as $col)
256       {
257       if ($col=='from' || $col=='to')
8e44f4 258         $cont = Q(rcmail_address_string($header->$col, 3, false, $attrib['addicon']), 'show');
4e17e6 259       else if ($col=='subject')
b4b081 260         {
41bece 261         $action = $mbox==$CONFIG['drafts_mbox'] ? 'compose' : 'show';
2b962c 262         $uid_param = $mbox==$CONFIG['drafts_mbox'] ? '_draft_uid' : '_uid';
44385f 263         $cont = abbreviate_string(trim($IMAP->decode_header($header->$col)), 160);
T 264         if (empty($cont)) $cont = rcube_label('nosubject');
265         $cont = sprintf('<a href="%s" onclick="return rcube_event.cancel(event)">%s</a>', Q(rcmail_url($action, array($uid_param=>$header->uid, '_mbox'=>$mbox))), Q($cont));
b4b081 266         }
e189a6 267       else if ($col=='flag')
A 268         $cont = $flagged_icon ? sprintf($image_tag, $skin_path, $flagged_icon, '') : '';
4e17e6 269       else if ($col=='size')
T 270         $cont = show_bytes($header->$col);
271       else if ($col=='date')
f11541 272         $cont = format_date($header->date);
4e17e6 273       else
2bca6e 274         $cont = Q($header->$col);
4e17e6 275         
2bca6e 276       $out .= '<td class="'.$col.'">' . $cont . "</td>\n";
4e17e6 277       }
T 278
279     $out .= sprintf("<td class=\"icon\">%s</td>\n", $attach_icon ? sprintf($image_tag, $skin_path, $attach_icon, '') : '');
280     $out .= "</tr>\n";
281     
282     if (sizeof($js_row_arr))
283       $a_js_message_arr[$header->uid] = $js_row_arr;
284     }
285   
286   // complete message table
287   $out .= "</tbody></table>\n";
288   
289   
290   $message_count = $IMAP->messagecount();
291   
292   // set client env
f11541 293   $OUTPUT->add_gui_object('mailcontframe', 'mailcontframe');
T 294   $OUTPUT->add_gui_object('messagelist', $attrib['id']);
295   $OUTPUT->set_env('messagecount', $message_count);
296   $OUTPUT->set_env('current_page', $IMAP->list_page);
297   $OUTPUT->set_env('pagecount', ceil($message_count/$IMAP->page_size));
298   $OUTPUT->set_env('sort_col', $sort_col);
299   $OUTPUT->set_env('sort_order', $sort_order);
4e17e6 300   
T 301   if ($attrib['messageicon'])
f11541 302     $OUTPUT->set_env('messageicon', $skin_path . $attrib['messageicon']);
6ec0a8 303   if ($attrib['deletedicon'])
f11541 304     $OUTPUT->set_env('deletedicon', $skin_path . $attrib['deletedicon']);
4e17e6 305   if ($attrib['unreadicon'])
f11541 306     $OUTPUT->set_env('unreadicon', $skin_path . $attrib['unreadicon']);
4e17e6 307   if ($attrib['repliedicon'])
f11541 308     $OUTPUT->set_env('repliedicon', $skin_path . $attrib['repliedicon']);
d73404 309   if ($attrib['forwardedicon'])
A 310     $OUTPUT->set_env('forwardedicon', $skin_path . $attrib['forwardedicon']);
311   if ($attrib['forwardedrepliedicon'])
312     $OUTPUT->set_env('forwardedrepliedicon', $skin_path . $attrib['forwardedrepliedicon']);
4e17e6 313   if ($attrib['attachmenticon'])
f11541 314     $OUTPUT->set_env('attachmenticon', $skin_path . $attrib['attachmenticon']);
e189a6 315   if ($attrib['flaggedicon'])
A 316     $OUTPUT->set_env('flaggedicon', $skin_path . $attrib['flaggedicon']);
317   if ($attrib['unflaggedicon'])
318     $OUTPUT->set_env('unflaggedicon', $skin_path . $attrib['unflaggedicon']);
4e17e6 319   
ae895a 320   $OUTPUT->set_env('messages', $a_js_message_arr);
d24d20 321   $OUTPUT->set_env('coltypes', $a_show_cols);
f11541 322   
6b47de 323   $OUTPUT->include_script('list.js');
4e17e6 324   
T 325   return $out;
326   }
327
328
45f56c 329 /**
T 330  * return javascript commands to add rows to the message list
331  */
4e17e6 332 function rcmail_js_message_list($a_headers, $insert_top=FALSE)
T 333   {
f11541 334   global $CONFIG, $IMAP, $OUTPUT;
4e17e6 335
T 336   $a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject');
41bece 337   $mbox = $IMAP->get_mailbox_name();
4e17e6 338
T 339   // show 'to' instead of from in sent messages
41bece 340   if (($mbox == $CONFIG['sent_mbox'] || $mbox == $CONFIG['drafts_mbox'])
f11541 341       && (($f = array_search('from', $a_show_cols)) !== false) && array_search('to', $a_show_cols) === false)
4e17e6 342     $a_show_cols[$f] = 'to';
T 343
f11541 344   $OUTPUT->command('set_message_coltypes', $a_show_cols);
25d8ba 345
4e17e6 346   // loop through message headers
ecd2e7 347   foreach ($a_headers as $n => $header)
4e17e6 348     {
T 349     $a_msg_cols = array();
350     $a_msg_flags = array();
ecd2e7 351     
T 352     if (empty($header))
353       continue;
f11541 354
583850 355     if (!empty($header->charset))
A 356       $IMAP->set_charset($header->charset);
357
4e17e6 358     // format each col; similar as in rcmail_message_list()
T 359     foreach ($a_show_cols as $col)
360       {
361       if ($col=='from' || $col=='to')
583850 362         $cont = Q(rcmail_address_string($header->$col, 3), 'show');
4e17e6 363       else if ($col=='subject')
7bbd5f 364         {
41bece 365         $action = $mbox==$CONFIG['drafts_mbox'] ? 'compose' : 'show';
2b962c 366         $uid_param = $mbox==$CONFIG['drafts_mbox'] ? '_draft_uid' : '_uid';
44385f 367         $cont = abbreviate_string(trim($IMAP->decode_header($header->$col)), 160);
T 368         if (!$cont) $cont = rcube_label('nosubject');
369         $cont = sprintf('<a href="%s" onclick="return rcube_event.cancel(event)">%s</a>', Q(rcmail_url($action, array($uid_param=>$header->uid, '_mbox'=>$mbox))), Q($cont));
7bbd5f 370         }
4e17e6 371       else if ($col=='size')
T 372         $cont = show_bytes($header->$col);
373       else if ($col=='date')
f11541 374         $cont = format_date($header->date);
4e17e6 375       else
2bca6e 376         $cont = Q($header->$col);
4e17e6 377           
T 378       $a_msg_cols[$col] = $cont;
379       }
380
6ec0a8 381     $a_msg_flags['deleted'] = $header->deleted ? 1 : 0;
4e17e6 382     $a_msg_flags['unread'] = $header->seen ? 0 : 1;
T 383     $a_msg_flags['replied'] = $header->answered ? 1 : 0;
d73404 384     $a_msg_flags['forwarded'] = $header->forwarded ? 1 : 0;
e189a6 385     $a_msg_flags['flagged'] = $header->flagged ? 1 : 0;
A 386     
f11541 387     $OUTPUT->command('add_message_row',
T 388       $header->uid,
389       $a_msg_cols,
390       $a_msg_flags,
391       preg_match("/multipart\/m/i", $header->ctype),
392       $insert_top);
4e17e6 393     }
T 394   }
395
396
45f56c 397 /**
T 398  * return an HTML iframe for loading mail content
399  */
b19097 400 function rcmail_messagecontent_frame($attrib)
T 401   {
f11541 402   global $OUTPUT;
b19097 403   
T 404   if (empty($attrib['id']))
405     $attrib['id'] = 'rcmailcontentwindow';
406
e2c610 407   $attrib['name'] = $attrib['id'];
b19097 408
e2c610 409   $OUTPUT->set_env('contentframe', $attrib['id']);
f11541 410   $OUTPUT->set_env('blankpage', $attrib['src'] ? $OUTPUT->abs_url($attrib['src']) : 'program/blank.gif');
b19097 411
95fcc3 412   return html::iframe($attrib);
b19097 413   }
T 414
4e17e6 415
45f56c 416 /**
T 417  *
418  */
4e17e6 419 function rcmail_messagecount_display($attrib)
T 420   {
f11541 421   global $IMAP, $OUTPUT;
4e17e6 422   
T 423   if (!$attrib['id'])
424     $attrib['id'] = 'rcmcountdisplay';
425
f11541 426   $OUTPUT->add_gui_object('countdisplay', $attrib['id']);
4e17e6 427
e2c610 428   return html::span($attrib, rcmail_get_messagecount_text());
4e17e6 429   }
T 430
431
45f56c 432 /**
T 433  *
434  */
58e360 435 function rcmail_quota_display($attrib)
T 436   {
f11541 437   global $OUTPUT, $COMM_PATH;
58e360 438
T 439   if (!$attrib['id'])
440     $attrib['id'] = 'rcmquotadisplay';
441
6d2714 442   if(isset($attrib['display']))
A 443     $_SESSION['quota_display'] = $attrib['display'];
444
f11541 445   $OUTPUT->add_gui_object('quotadisplay', $attrib['id']);
58e360 446
6d20d0 447   return html::span($attrib, rcmail_quota_content(NULL, $attrib));
23796e 448   }
S 449
450
45f56c 451 /**
T 452  *
453  */
6cd009 454 function rcmail_quota_content($quota=NULL, $attrib=NULL)
23796e 455   {
876b15 456   global $IMAP, $COMM_PATH, $RCMAIL;
3ea0e3 457
6d2714 458   $display = isset($_SESSION['quota_display']) ? $_SESSION['quota_display'] : '';
A 459
460   if (is_array($quota) && !empty($quota['used']) && !empty($quota['total']))
3ea0e3 461     {
6d2714 462       if (!isset($quota['percent']))
A 463         $quota['percent'] = $quota['used'] / $quota['total'];
464     }
465   elseif (!$IMAP->get_capability('QUOTA'))
466     return rcube_label('unknown');
467   else
468     $quota = $IMAP->get_quota();
469
876b15 470   if ($quota && !($quota['total']==0 && $RCMAIL->config->get('quota_zero_as_unlimited')))
6d2714 471     {
A 472     $quota_text = sprintf('%s / %s (%.0f%%)',
473                           show_bytes($quota['used'] * 1024),
474                           show_bytes($quota['total'] * 1024),
475                           $quota['percent']);
3ea0e3 476
T 477     // show quota as image (by Brett Patterson)
23796e 478     if ($display == 'image' && function_exists('imagegif'))
3ea0e3 479       {
6cd009 480       if (!$attrib['width'])
A 481         $attrib['width'] = isset($_SESSION['quota_width']) ? $_SESSION['quota_width'] : 100;
482       else
483     $_SESSION['quota_width'] = $attrib['width'];
484
485       if (!$attrib['height'])
486         $attrib['height'] = isset($_SESSION['quota_height']) ? $_SESSION['quota_height'] : 14;
487       else
488     $_SESSION['quota_height'] = $attrib['height'];
489         
f11541 490       $quota_text = sprintf('<img src="./bin/quotaimg.php?u=%s&amp;q=%d&amp;w=%d&amp;h=%d" width="%d" height="%d" alt="%s" title="%s / %s" />',
3ea0e3 491                             $quota['used'], $quota['total'],
fda695 492                             $attrib['width'], $attrib['height'],
T 493                             $attrib['width'], $attrib['height'],
494                             $quota_text,
6cd009 495                             show_bytes($quota['used'] * 1024),
A 496                             show_bytes($quota['total'] * 1024));
3ea0e3 497       }
T 498     }
499   else
4647e1 500     $quota_text = rcube_label('unlimited');
58e360 501
23796e 502   return $quota_text;
58e360 503   }
T 504
4e17e6 505
45f56c 506 /**
T 507  *
508  */
4647e1 509 function rcmail_get_messagecount_text($count=NULL, $page=NULL)
4e17e6 510   {
T 511   global $IMAP, $MESSAGE;
512   
8fa58e 513   if (isset($MESSAGE->index))
4e17e6 514     {
T 515     return rcube_label(array('name' => 'messagenrof',
8fa58e 516                              'vars' => array('nr'  => $MESSAGE->index+1,
4647e1 517                                              'count' => $count!==NULL ? $count : $IMAP->messagecount())));
4e17e6 518     }
31b2ce 519
4647e1 520   if ($page===NULL)
T 521     $page = $IMAP->list_page;
522     
523   $start_msg = ($page-1) * $IMAP->page_size + 1;
524   $max = $count!==NULL ? $count : $IMAP->messagecount();
4e17e6 525
T 526   if ($max==0)
527     $out = rcube_label('mailboxempty');
528   else
529     $out = rcube_label(array('name' => 'messagesfromto',
530                               'vars' => array('from'  => $start_msg,
531                                               'to'    => min($max, $start_msg + $IMAP->page_size - 1),
532                                               'count' => $max)));
533
2bca6e 534   return Q($out);
4e17e6 535   }
T 536
ac5d15 537 /**
T 538  *
539  */
540 function rcmail_mailbox_name_display($attrib)
541 {
542     global $RCMAIL;
543
544     if (!$attrib['id'])
545         $attrib['id'] = 'rcmmailboxname';
546
547     $RCMAIL->output->add_gui_object('mailboxname', $attrib['id']);
548
549     return html::span($attrib, rcmail_get_mailbox_name_text());
550 }
551
552 function rcmail_get_mailbox_name_text()
553 {
554     global $RCMAIL;
555     return rcmail_localize_foldername($RCMAIL->imap->get_mailbox_name());
556 }
557
4e17e6 558
45f56c 559 /**
65cc1c 560  * Convert the given message part to proper HTML
T 561  * which can be displayed the message view
45f56c 562  *
65cc1c 563  * @param object rcube_message_part Message part
T 564  * @param bool  True if external objects (ie. images ) are allowed
565  * @param bool  True if part should be converted to plaintext
566  * @return string Formatted HTML string
45f56c 567  */
21e724 568 function rcmail_print_body($part, $p = array())
45f56c 569 {
T 570   global $REMOTE_OBJECTS;
4e17e6 571   
21e724 572   $p += array('safe' => false, 'plain' => false, 'inline_html' => true);
T 573   
5cc4b1 574   // convert html to text/plain
21e724 575   if ($part->ctype_secondary == 'html' && $p['plain']) {
45f56c 576     $txt = new html2text($part->body, false, true);
5cc4b1 577     $body = $txt->get_text();
T 578     $part->ctype_secondary = 'plain';
45f56c 579   }
4e17e6 580   // text/html
45f56c 581   else if ($part->ctype_secondary == 'html') {
2cb6d4 582     $html = $part->body;
c1b81f 583
7f6258 584     // special replacements (not properly handled by washtml class)
A 585     $html_search = array(
586     '/(<\/nobr>)(\s+)(<nobr>)/i',    // space(s) between <NOBR>
587     '/(<[\/]*st1:[^>]+>)/i',    // Microsoft's Smart Tags <ST1>
2cb6d4 588     '/<title>.*<\/title>/i',    // PHP bug #32547 workaround: remove title tag
A 589     '/<html[^>]*>/im',        // malformed html: remove html tags (#1485139)
590     '/<\/html>/i',            // malformed html: remove html tags (#1485139)
7f6258 591     );
A 592     $html_replace = array(
593     '\\1'.' &nbsp; '.'\\3',
594     '',
2cb6d4 595     '',
A 596     '',
597     '',
7f6258 598     );
A 599     $html = preg_replace($html_search, $html_replace, $html);
600
2cb6d4 601     // charset was converted to UTF-8 in rcube_imap::get_message_part() -> change charset specification in HTML accordingly
A 602     if (preg_match('/(\s+content=[\'"]\w+\/\w+;\s*charset)=([a-z0-9-_]+)/i', $html)) 
603       $html = preg_replace('/(\s+content=[\'"]\w+\/\w+;\s*charset)=([a-z0-9-_]+)/i', '\\1='.RCMAIL_CHARSET, $html); 
604     else {
605       // add head for malformed messages, washtml cannot work without that
606       if (!preg_match('/<head[^>]*>(.*)<\/head>/Uims', $html))
607         $html = '<head></head>'. $html;
608       $html = substr_replace($html, '<meta http-equiv="Content-Type" content="text/html; charset='.RCMAIL_CHARSET.'" />', intval(stripos($html, '</head>')), 0);
609     }
610
45f56c 611     // clean HTML with washhtml by Frederic Motte
21e724 612     $wash_opts = array(
45f56c 613       'show_washed' => false,
21e724 614       'allow_remote' => $p['safe'],
45f56c 615       'blocked_src' => "./program/blocked.gif",
350459 616       'charset' => RCMAIL_CHARSET,
45f56c 617       'cid_map' => $part->replaces,
21e724 618       'html_elements' => array('body'),
T 619     );
620     
621     if (!$p['inline_html']) {
622       $wash_opts['html_elements'] = array('html','head','title','body');
623     }
624     
625     $washer = new washtml($wash_opts);
626     $washer->add_callback('form', 'rcmail_washtml_callback');
36c236 627     
T 628     if ($p['safe']) {  // allow CSS styles, will be sanitized by rcmail_washtml_callback()
629       $washer->add_callback('style', 'rcmail_washtml_callback');
630     }
631     
21e724 632     $body = $washer->wash($html);
T 633     $REMOTE_OBJECTS = $washer->extlinks;
4e17e6 634
45f56c 635     return $body;
T 636   }
4e17e6 637   // text/enriched
45f56c 638   else if ($part->ctype_secondary=='enriched') {
cfe4a6 639     $part->ctype_secondary = 'html';
9103d1 640     return Q(enriched_to_html($part->body), 'show');
45f56c 641   }
4e17e6 642   else
45f56c 643     $body = $part->body;
4e17e6 644
T 645
45f56c 646   /**** assert plaintext ****/
T 647
648   // make links and email-addresses clickable
649   $convert_patterns = $convert_replaces = $replace_strings = array();
650   
651   $url_chars = 'a-z0-9_\-\+\*\$\/&%=@#:;';
652   $url_chars_within = '\?\.~,!';
653
654   $convert_patterns[] = "/([\w]+):\/\/([a-z0-9\-\.]+[a-z]{2,4}([$url_chars$url_chars_within]*[$url_chars])?)/ie";
655   $convert_replaces[] = "rcmail_str_replacement('<a href=\"\\1://\\2\" target=\"_blank\">\\1://\\2</a>', \$replace_strings)";
656
657   $convert_patterns[] = "/([^\/:]|\s)(www\.)([a-z0-9\-]{2,}[a-z]{2,4}([$url_chars$url_chars_within]*[$url_chars])?)/ie";
658   $convert_replaces[] = "rcmail_str_replacement('\\1<a href=\"http://\\2\\3\" target=\"_blank\">\\2\\3</a>', \$replace_strings)";
659   
660   $convert_patterns[] = '/([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9]\\.[a-z]{2,5})/ie';
661   $convert_replaces[] = "rcmail_str_replacement('<a href=\"mailto:\\1\" onclick=\"return ".JS_OBJECT_NAME.".command(\'compose\',\'\\1\',this)\">\\1</a>', \$replace_strings)";
662   
663   // search for patterns like links and e-mail addresses
664   $body = preg_replace($convert_patterns, $convert_replaces, $body);
4e17e6 665
45f56c 666   // split body into single lines
T 667   $a_lines = preg_split('/\r?\n/', $body);
668   $quote_level = 0;
4e17e6 669
45f56c 670   // colorize quoted parts
T 671   for ($n=0; $n < sizeof($a_lines); $n++) {
672     $line = $a_lines[$n];
673     $quotation = '';
674     $q = 0;
4e17e6 675     
45f56c 676     if (preg_match('/^(>+\s*)+/', $line, $regs)) {
T 677       $q    = strlen(preg_replace('/\s/', '', $regs[0]));
678       $line = substr($line, strlen($regs[0]));
679
680       if ($q > $quote_level)
681         $quotation = str_repeat('<blockquote>', $q - $quote_level);
682       else if ($q < $quote_level)
683         $quotation = str_repeat("</blockquote>", $quote_level - $q);
4e17e6 684     }
45f56c 685     else if ($quote_level > 0)
T 686       $quotation = str_repeat("</blockquote>", $quote_level);
687
688     $quote_level = $q;
689     $a_lines[$n] = $quotation . Q($line, 'replace', false);  // htmlquote plaintext
690   }
691
692   // insert the links for urls and mailtos
693   $body = preg_replace("/##string_replacement\{([0-9]+)\}##/e", "\$replace_strings[\\1]", join("\n", $a_lines));
694   
695   return "<div class=\"pre\">".$body."\n</div>";
21e724 696 }
4e17e6 697
45f56c 698 /**
T 699  * add a string to the replacement array and return a replacement string
700  */
4e17e6 701 function rcmail_str_replacement($str, &$rep)
21e724 702 {
4e17e6 703   static $count = 0;
T 704   $rep[$count] = stripslashes($str);
705   return "##string_replacement{".($count++)."}##";
21e724 706 }
4e17e6 707
21e724 708
T 709 /**
710  * Callback function for washtml cleaning class
711  */
712 function rcmail_washtml_callback($tagname, $attrib, $content)
713 {
714   switch ($tagname) {
715     case 'form':
716       $out = html::div('form', $content);
717       break;
718       
1c499a 719     case 'style':
T 720       // decode all escaped entities and reduce to ascii strings
36c236 721       $stripped = preg_replace('/[^a-zA-Z\(:]/', '', rcmail_xss_entitiy_decode($content));
1c499a 722       
36c236 723       // now check for evil strings like expression, behavior or url()
T 724       if (!preg_match('/expression|behavior|url\(|import/', $stripped)) {
1c499a 725         $out = html::tag('style', array('type' => 'text/css'), $content);
T 726         break;
727       }
728     
21e724 729     default:
T 730       $out = '';
731   }
732   
733   return $out;
734 }
4e17e6 735
T 736
45f56c 737 /**
T 738  * return table with message headers
739  */
4e17e6 740 function rcmail_message_headers($attrib, $headers=NULL)
T 741   {
5b1de5 742   global $IMAP, $OUTPUT, $MESSAGE, $PRINT_MODE, $CONFIG;
4e17e6 743   static $sa_attrib;
T 744   
745   // keep header table attrib
746   if (is_array($attrib) && !$sa_attrib)
747     $sa_attrib = $attrib;
748   else if (!is_array($attrib) && is_array($sa_attrib))
749     $attrib = $sa_attrib;
750   
751   
752   if (!isset($MESSAGE))
753     return FALSE;
754
755   // get associative array of headers object
756   if (!$headers)
8fa58e 757     $headers = is_object($MESSAGE->headers) ? get_object_vars($MESSAGE->headers) : $MESSAGE->headers;
cfe4a6 758     
4e17e6 759   $header_count = 0;
T 760   
761   // allow the following attributes to be added to the <table> tag
762   $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary'));
763   $out = '<table' . $attrib_str . ">\n";
764
765   // show these headers
700320 766   $standard_headers = array('subject', 'from', 'organization', 'to', 'cc', 'bcc', 'replyto', 'date');
e5686f 767
4e17e6 768   foreach ($standard_headers as $hkey)
T 769     {
770     if (!$headers[$hkey])
771       continue;
772
700320 773     if ($hkey == 'date')
5b1de5 774       {
A 775       if ($PRINT_MODE)
776         $header_value = format_date($headers[$hkey], $CONFIG['date_long'] ? $CONFIG['date_long'] : 'x');
777       else
778         $header_value = format_date($headers[$hkey]);
779       }
700320 780     else if ($hkey == 'replyto')
A 781       {
782       if ($headers['replyto'] != $headers['from'])
783         $header_value = Q(rcmail_address_string($headers['replyto'], null, true, $attrib['addicon']), 'show');
784       else
785         continue;
786       }
787     else if (in_array($hkey, array('from', 'to', 'cc', 'bcc')))
8e44f4 788       $header_value = Q(rcmail_address_string($headers[$hkey], null, true, $attrib['addicon']), 'show');
6925ad 789     else if ($hkey == 'subject' && empty($headers[$hkey]))
T 790       $header_value = Q(rcube_label('nosubject'));
4e17e6 791     else
44385f 792       $header_value = Q(trim($IMAP->decode_header($headers[$hkey])));
4e17e6 793
T 794     $out .= "\n<tr>\n";
2bca6e 795     $out .= '<td class="header-title">'.Q(rcube_label($hkey)).":&nbsp;</td>\n";
4e17e6 796     $out .= '<td class="'.$hkey.'" width="90%">'.$header_value."</td>\n</tr>";
T 797     $header_count++;
798     }
799
e5686f 800   // all headers division
A 801   $out .= "\n".'<tr><td colspan="2" class="more-headers show-headers"
802     onclick="return '.JS_OBJECT_NAME.'.command(\'load-headers\', \'\', this)"></td></tr>';
803   $out .= "\n".'<tr id="all-headers"><td colspan="2" class="all"><div id="headers-source"></div></td></tr>';
804
805   $OUTPUT->add_gui_object('all_headers_row', 'all-headers');
806   $OUTPUT->add_gui_object('all_headers_box', 'headers-source');
807
4e17e6 808   $out .= "\n</table>\n\n";
T 809
810   return $header_count ? $out : '';  
811   }
812
813
45f56c 814 /**
21605c 815  * Handler for the 'messagebody' GUI object
45f56c 816  *
21605c 817  * @param array Named parameters
T 818  * @return string HTML content showing the message body
45f56c 819  */
4e17e6 820 function rcmail_message_body($attrib)
T 821   {
8fa58e 822   global $CONFIG, $OUTPUT, $MESSAGE, $IMAP, $REMOTE_OBJECTS;
5f8686 823
8fa58e 824   if (!is_array($MESSAGE->parts) && empty($MESSAGE->body))
4e17e6 825     return '';
T 826     
827   if (!$attrib['id'])
828     $attrib['id'] = 'rcmailMsgBody';
829
8fa58e 830   $safe_mode = $MESSAGE->is_safe || intval($_GET['_safe']);
21605c 831   $out = '';
4e17e6 832   
T 833   $header_attrib = array();
834   foreach ($attrib as $attr => $value)
835     if (preg_match('/^headertable([a-z]+)$/i', $attr, $regs))
836       $header_attrib[$regs[1]] = $value;
837
8fa58e 838   if (!empty($MESSAGE->parts))
4e17e6 839     {
8fa58e 840     foreach ($MESSAGE->parts as $i => $part)
4e17e6 841       {
8fa58e 842       if ($part->type == 'headers')
8d4bcd 843         $out .= rcmail_message_headers(sizeof($header_attrib) ? $header_attrib : NULL, $part->headers);
8fa58e 844       else if ($part->type == 'content')
4e17e6 845         {
8d4bcd 846         if (empty($part->ctype_parameters) || empty($part->ctype_parameters['charset']))
8fa58e 847           $part->ctype_parameters['charset'] = $MESSAGE->headers->charset;
a0109c 848
8d4bcd 849         // fetch part if not available
T 850         if (!isset($part->body))
8fa58e 851           $part->body = $MESSAGE->get_part_content($part->mime_id);
a0109c 852
21e724 853         $body = rcmail_print_body($part, array('safe' => $safe_mode, 'plain' => !$CONFIG['prefer_html']));
5f8686 854
cfe4a6 855         if ($part->ctype_secondary == 'html')
21605c 856           $out .= html::div('message-htmlpart', rcmail_html4inline($body, $attrib['id']));
a2f2c5 857         else
21605c 858           $out .= html::div('message-part', $body);
4e17e6 859         }
T 860       }
861     }
862   else
cfe4a6 863     $out .= html::div('message-part', html::div('pre', Q($MESSAGE->body)));
4e17e6 864
T 865
8fa58e 866   $ctype_primary = strtolower($MESSAGE->structure->ctype_primary);
T 867   $ctype_secondary = strtolower($MESSAGE->structure->ctype_secondary);
166b61 868
4e17e6 869   // list images after mail body
be5f03 870   if ($CONFIG['inline_images']
2da368 871       && $ctype_primary == 'multipart'
T 872       && !empty($MESSAGE->attachments) 
873       && !strstr($message_body, '<html'))
166b61 874     {
8fa58e 875     foreach ($MESSAGE->attachments as $attach_prop) {
T 876       if (strpos($attach_prop->mimetype, 'image/') === 0) {
877         $out .= html::tag('hr') . html::p(array('align' => "center"),
878           html::img(array(
879             'src' => $MESSAGE->get_part_url($attach_prop->mime_id),
880             'title' => $attach_prop->filename,
881             'alt' => $attach_prop->filename,
882           )));
883         }
4e17e6 884     }
8fa58e 885   }
4e17e6 886   
T 887   // tell client that there are blocked remote objects
888   if ($REMOTE_OBJECTS && !$safe_mode)
f11541 889     $OUTPUT->set_env('blockedobjects', true);
4e17e6 890
21605c 891   return html::div($attrib, $out);
4e17e6 892   }
T 893
894
895
45f56c 896 /**
T 897  * modify a HTML message that it can be displayed inside a HTML page
898  */
899 function rcmail_html4inline($body, $container_id)
4e17e6 900   {
97bd2c 901   $base_url = "";
4e17e6 902   $last_style_pos = 0;
T 903   $body_lc = strtolower($body);
97bd2c 904   
T 905   // check for <base href>
906   if (preg_match(($base_reg = '/(<base.*href=["\']?)([hftps]{3,5}:\/{2}[^"\'\s]+)([^<]*>)/i'), $body, $base_regs))
907     $base_url = $base_regs[2];
4e17e6 908   
T 909   // find STYLE tags
910   while (($pos = strpos($body_lc, '<style', $last_style_pos)) && ($pos2 = strpos($body_lc, '</style>', $pos)))
911     {
ea206d 912     $pos = strpos($body_lc, '>', $pos)+1;
T 913
4e17e6 914     // replace all css definitions with #container [def]
97bd2c 915     $styles = rcmail_mod_css_styles(substr($body, $pos, $pos2-$pos), $container_id, $base_url);
ea206d 916
3b12ae 917     $body = substr($body, 0, $pos) . $styles . substr($body, $pos2);
S 918     $body_lc = strtolower($body);
4e17e6 919     $last_style_pos = $pos2;
5e98e1 920     }
4e17e6 921
T 922   // resolve <base href>
97bd2c 923   if ($base_url)
4e17e6 924     {
T 925     $body = preg_replace('/(src|background|href)=(["\']?)([\.\/]+[^"\'\s]+)(\2|\s|>)/Uie', "'\\1=\"'.make_absolute_url('\\3', '$base_url').'\"'", $body);
926     $body = preg_replace('/(url\s*\()(["\']?)([\.\/]+[^"\'\)\s]+)(\2)\)/Uie', "'\\1\''.make_absolute_url('\\3', '$base_url').'\')'", $body);
927     $body = preg_replace($base_reg, '', $body);
928     }
fe79b1 929     
T 930   // modify HTML links to open a new window if clicked
97bd2c 931   $body = preg_replace('/<(a|link)\s+([^>]+)>/Uie', "rcmail_alter_html_link('\\1','\\2', '$container_id');", $body);
4e17e6 932
T 933   // add comments arround html and other tags
06895c 934   $out = preg_replace(array(
d7a411 935       '/(<!DOCTYPE[^>]*>)/i',
A 936       '/(<\?xml[^>]*>)/i',
06895c 937       '/(<\/?html[^>]*>)/i',
T 938       '/(<\/?head[^>]*>)/i',
939       '/(<title[^>]*>.*<\/title>)/Ui',
940       '/(<\/?meta[^>]*>)/i'),
941     '<!--\\1-->',
942     $body);
a0109c 943
97bd2c 944   $out = preg_replace(
45f56c 945     array('/<body([^>]*)>/i', '/<\/body>/i'),
T 946     array('<div class="rcmBody"\\1>', '</div>'),
97bd2c 947     $out);
a0109c 948
86958f 949   // quote <? of php and xml files that are specified as text/html
T 950   $out = preg_replace(array('/<\?/', '/\?>/'), array('&lt;?', '?&gt;'), $out);
951
4e17e6 952   return $out;
T 953   }
954
955
45f56c 956 /**
T 957  * parse link attributes and set correct target
958  */
97bd2c 959 function rcmail_alter_html_link($tag, $attrs, $container_id)
e5af2f 960 {
97bd2c 961   $attrib = parse_attrib_string($attrs);
e5af2f 962   $end = '>';
84f5b7 963
e5af2f 964   if ($tag == 'link' && preg_match('/^https?:\/\//i', $attrib['href'])) {
97bd2c 965     $attrib['href'] = "./bin/modcss.php?u=" . urlencode($attrib['href']) . "&amp;c=" . urlencode($container_id);
e5af2f 966     $end = ' />';
T 967   }
968   else if (stristr((string)$attrib['href'], 'mailto:')) {
97bd2c 969     $attrib['onclick'] = sprintf(
T 970       "return %s.command('compose','%s',this)",
971       JS_OBJECT_NAME,
972       JQ(substr($attrib['href'], 7)));
4e17e6 973   }
e5af2f 974   else if (!empty($attrib['href']) && $attrib['href'][0] != '#') {
T 975     $attrib['target'] = '_blank';
976   }
977
978   return "<$tag" . html::attrib_string($attrib, array('href','name','target','onclick','id','class','style','title','rel','type','media')) . $end;
979 }
4e17e6 980
T 981
45f56c 982 /**
T 983  * decode address string and re-format it as HTML links
984  */
8e44f4 985 function rcmail_address_string($input, $max=null, $linked=false, $addicon=null)
T 986 {
f11541 987   global $IMAP, $PRINT_MODE, $CONFIG, $OUTPUT, $EMAIL_ADDRESS_PATTERN;
1088d6 988
4e17e6 989   $a_parts = $IMAP->decode_address_list($input);
T 990
991   if (!sizeof($a_parts))
992     return $input;
993
994   $c = count($a_parts);
995   $j = 0;
996   $out = '';
997
8e44f4 998   foreach ($a_parts as $part) {
4e17e6 999     $j++;
8e44f4 1000     if ($PRINT_MODE) {
90cd45 1001       $out .= sprintf('%s &lt;%s&gt;', Q($part['name']), $part['mailto']);
8e44f4 1002     }
T 1003     else if (preg_match($EMAIL_ADDRESS_PATTERN, $part['mailto'])) {
1004       if ($linked) {
1005         $out .= html::a(array(
1006             'href' => 'mailto:'.$part['mailto'],
1007             'onclick' => sprintf("return %s.command('compose','%s',this)", JS_OBJECT_NAME, JQ($part['mailto'])),
1008             'title' => $part['mailto'],
1009             'class' => "rcmContactAddress",
1010           ),
1011         Q($part['name']));
4e17e6 1012       }
8e44f4 1013       else {
T 1014         $out .= html::span(array('title' => $part['mailto'], 'class' => "rcmContactAddress"), Q($part['name']));
1015       }
1016
1017       if ($addicon) {
1018         $out .= '&nbsp;' . html::a(array(
1019             'href' => "#add",
1020             'onclick' => sprintf("return %s.command('add-contact','%s',this)", JS_OBJECT_NAME, urlencode($part['string'])),
1021             'title' => rcube_label('addtoaddressbook'),
1022           ),
1023           html::img(array(
1024             'src' => $CONFIG['skin_path'] . $addicon,
1025             'alt' => "Add contact",
1026             'border' => 0,
1027           )));
1028       }
1029     }
1030     else {
4e17e6 1031       if ($part['name'])
2bca6e 1032         $out .= Q($part['name']);
4e17e6 1033       if ($part['mailto'])
28bfe4 1034         $out .= (strlen($out) ? ' ' : '') . sprintf('&lt;%s&gt;', Q($part['mailto']));
8e44f4 1035     }
4e17e6 1036       
T 1037     if ($c>$j)
1038       $out .= ','.($max ? '&nbsp;' : ' ');
1039         
8e44f4 1040     if ($max && $j==$max && $c>$j) {
4e17e6 1041       $out .= '...';
T 1042       break;
1043     }
8e44f4 1044   }
4e17e6 1045     
T 1046   return $out;
8e44f4 1047 }
4e17e6 1048
T 1049
ccd63c 1050 /**
T 1051  * Wrap text to a given number of characters per line
1052  * but respect the mail quotation of replies messages (>)
1053  *
1054  * @param string Text to wrap
1055  * @param int The line width
1056  * @return string The wrapped text
1057  */
1058 function rcmail_wrap_quoted($text, $max = 76)
1059 {
1060   // Rebuild the message body with a maximum of $max chars, while keeping quoted message.
1061   $lines = preg_split('/\r?\n/', trim($text));
1062   $out = '';
1063
1064   foreach ($lines as $line) {
1065     if (strlen($line) > $max) {
1066       if (preg_match('/^([>\s]+)/', $line, $regs)) {
1067         $length = strlen($regs[0]);
1068         $prefix = substr($line, 0, $length);
1069
1070         // Remove '> ' from the line, then wordwrap() the line
1071         $line = wordwrap(substr($line, $length), $max - $length);
1072
1073         // Rebuild the line with '> ' at the beginning of each 'subline'
1074         $newline = '';
1075         foreach (explode("\n", $line) as $l) {
1076           $newline .= $prefix . $l . "\n";
1077         }
1078
1079         // Remove the righest newline char
1080         $line = rtrim($newline);
1081       }
1082       else {
1083         $line = wordwrap($line, $max);
1084       }
1085     }
1086
1087     // Append the line
1088     $out .= $line . "\n";
1089   }
1090   
1091   return $out;
1092 }
1093
1094
4e17e6 1095 function rcmail_message_part_controls()
T 1096   {
8fa58e 1097   global $MESSAGE;
4e17e6 1098   
d5342a 1099   $part = asciiwords(get_input_value('_part', RCUBE_INPUT_GPC));
8fa58e 1100   if (!is_object($MESSAGE) || !is_array($MESSAGE->parts) || !($_GET['_uid'] && $_GET['_part']) || !$MESSAGE->mime_parts[$part])
4e17e6 1101     return '';
T 1102     
8fa58e 1103   $part = $MESSAGE->mime_parts[$part];
T 1104   $table = new html_table(array('cols' => 3));
4e17e6 1105   
8fa58e 1106   if (!empty($part->filename)) {
T 1107     $table->add('title', Q(rcube_label('filename')));
1108     $table->add(null, Q($part->filename));
8dc048 1109     $table->add(null, '[' . html::a('?'.str_replace('_frame=', '_download=', $_SERVER['QUERY_STRING']), Q(rcube_label('download'))) . ']');
8fa58e 1110   }
4e17e6 1111   
8fa58e 1112   if (!empty($part->size)) {
T 1113     $table->add('title', Q(rcube_label('filesize')));
1114     $table->add(null, Q(show_bytes($part->size)));
1115   }
4e17e6 1116   
8fa58e 1117   return $table->show($attrib);
4e17e6 1118   }
T 1119
1120
1121
1122 function rcmail_message_part_frame($attrib)
1123   {
1124   global $MESSAGE;
1125   
8fa58e 1126   $part = $MESSAGE->mime_parts[asciiwords(get_input_value('_part', RCUBE_INPUT_GPC))];
4e17e6 1127   $ctype_primary = strtolower($part->ctype_primary);
T 1128
95fcc3 1129   $attrib['src'] = './?' . str_replace('_frame=', ($ctype_primary=='text' ? '_show=' : '_preload='), $_SERVER['QUERY_STRING']);
4e17e6 1130
95fcc3 1131   return html::iframe($attrib);
4e17e6 1132   }
T 1133
1134
45f56c 1135 /**
T 1136  * clear message composing settings
1137  */
4e17e6 1138 function rcmail_compose_cleanup()
T 1139   {
1140   if (!isset($_SESSION['compose']))
1141     return;
70d4b9 1142
4e17e6 1143   // remove attachment files from temp dir
T 1144   if (is_array($_SESSION['compose']['attachments']))
1145     foreach ($_SESSION['compose']['attachments'] as $attachment)
15a9d1 1146       @unlink($attachment['path']);
4e17e6 1147   
T 1148   unset($_SESSION['compose']);
1149   }
fba1f5 1150   
T 1151
1152 /**
1153  * Send the given message compose object using the configured method
1154  */
1155 function rcmail_deliver_message(&$message, $from, $mailto)
1156 {
1157   global $CONFIG;
1158
1159   $msg_body = $message->get();
8fa58e 1160   $headers = $message->headers();
79aeb3 1161
fba1f5 1162   // send thru SMTP server using custom SMTP library
T 1163   if ($CONFIG['smtp_server'])
1164     {
1165     // generate list of recipients
1166     $a_recipients = array($mailto);
1167   
1168     if (strlen($headers['Cc']))
1169       $a_recipients[] = $headers['Cc'];
1170     if (strlen($headers['Bcc']))
1171       $a_recipients[] = $headers['Bcc'];
1172   
1173     // clean Bcc from header for recipients
1174     $send_headers = $headers;
1175     unset($send_headers['Bcc']);
7ec922 1176     // here too, it because txtHeaders() below use $message->_headers not only $send_headers
A 1177     unset($message->_headers['Bcc']);
fba1f5 1178
T 1179     // send message
1180     $smtp_response = array();
7ec922 1181     $sent = smtp_mail($from, $a_recipients, ($foo = $message->txtHeaders($send_headers, true)), $msg_body, $smtp_response);
fba1f5 1182
T 1183     // log error
1184     if (!$sent)
1185       raise_error(array('code' => 800, 'type' => 'smtp', 'line' => __LINE__, 'file' => __FILE__,
1186                         'message' => "SMTP error: ".join("\n", $smtp_response)), TRUE, FALSE);
1187     }
1188   
1189   // send mail using PHP's mail() function
1190   else
1191     {
1192     // unset some headers because they will be added by the mail() function
1193     $headers_enc = $message->headers($headers);
1194     $headers_php = $message->_headers;
1195     unset($headers_php['To'], $headers_php['Subject']);
1196     
1197     // reset stored headers and overwrite
1198     $message->_headers = array();
1199     $header_str = $message->txtHeaders($headers_php);
1200   
1201     if (ini_get('safe_mode'))
1202       $sent = mail($headers_enc['To'], $headers_enc['Subject'], $msg_body, $header_str);
1203     else
1204       $sent = mail($headers_enc['To'], $headers_enc['Subject'], $msg_body, $header_str, "-f$from");
1205     }
1206   
79aeb3 1207   if ($sent)
A 1208   {
1209     // remove MDN headers after sending
ae8f19 1210     unset($headers['Return-Receipt-To'], $headers['Disposition-Notification-To']);
79aeb3 1211     
A 1212     if ($CONFIG['smtp_log'])
1213       write_log('sendmail', sprintf("[%s] User: %d on %s; Message for %s; %s",
1214         date("d-M-Y H:i:s O", mktime()),
1215         $_SESSION['user_id'],
1216         $_SERVER['REMOTE_ADDR'],
1217         $mailto,
1218         !empty($smtp_response) ? join('; ', $smtp_response) : ''));
1219   }
fba1f5 1220   
T 1221   $message->_headers = array();
1222   $message->headers($headers);
1223   
1224   return $sent;
1225 }
f11541 1226
T 1227
0ea884 1228 function rcmail_send_mdn($uid)
T 1229 {
83a763 1230   global $RCMAIL, $IMAP;
8fa58e 1231
T 1232   $message = new rcube_message($uid);
0ea884 1233   
5b3dd4 1234   if ($message->headers->mdn_to && !$message->headers->mdn_sent && $IMAP->check_permflag('MDNSENT'))
0ea884 1235   {
83a763 1236     $identity = $RCMAIL->user->get_identity();
0ea884 1237     $sender = format_email_recipient($identity['email'], $identity['name']);
8fa58e 1238     $recipient = array_shift($IMAP->decode_address_list($message->headers->mdn_to));
0ea884 1239     $mailto = $recipient['mailto'];
T 1240
83a763 1241     $compose = new rcube_mail_mime($RCMAIL->config->header_delimiter());
0ea884 1242     $compose->setParam(array(
T 1243       'text_encoding' => 'quoted-printable',
1244       'html_encoding' => 'quoted-printable',
1245       'head_encoding' => 'quoted-printable',
1246       'head_charset'  => RCMAIL_CHARSET,
1247       'html_charset'  => RCMAIL_CHARSET,
1248       'text_charset'  => RCMAIL_CHARSET,
1249     ));
1250     
1251     // compose headers array
1252     $headers = array(
1253       'Date' => date('r'),
1254       'From' => $sender,
8fa58e 1255       'To'   => $message->headers->mdn_to,
T 1256       'Subject' => rcube_label('receiptread') . ': ' . $message->subject,
83a763 1257       'Message-ID' => sprintf('<%s@%s>', md5(uniqid('rcmail'.rand(),true)), $RCMAIL->config->mail_domain($_SESSION['imap_host'])),
0ea884 1258       'X-Sender' => $identity['email'],
T 1259       'Content-Type' => 'multipart/report; report-type=disposition-notification',
1260     );
1261     
83a763 1262     if ($agent = $RCMAIL->config->get('useragent'))
T 1263       $headers['User-Agent'] = $agent;
0ea884 1264
T 1265     $body = rcube_label("yourmessage") . "\r\n\r\n" .
8fa58e 1266       "\t" . rcube_label("to") . ': ' . rcube_imap::decode_mime_string($message->headers->to, $message->headers->charset) . "\r\n" .
T 1267       "\t" . rcube_label("subject") . ': ' . $message->subject . "\r\n" .
83a763 1268       "\t" . rcube_label("sent") . ': ' . format_date($message->headers->date, $RCMAIL->config->get('date_long')) . "\r\n" .
0ea884 1269       "\r\n" . rcube_label("receiptnote") . "\r\n";
T 1270     
83a763 1271     $ua = $RCMAIL->config->get('useragent', "RoundCube Webmail (Version ".RCMAIL_VERSION.")");
0ea884 1272     $report = "Reporting-UA: $ua\r\n";
T 1273     
8fa58e 1274     if ($message->headers->to)
T 1275         $report .= "Original-Recipient: {$message->headers->to}\r\n";
0ea884 1276     
T 1277     $report .= "Final-Recipient: rfc822; {$identity['email']}\r\n" .
8fa58e 1278                "Original-Message-ID: {$message->headers->messageID}\r\n" .
0ea884 1279                "Disposition: manual-action/MDN-sent-manually; displayed\r\n";
T 1280     
8fa58e 1281     $compose->headers($headers);
T 1282     $compose->setTXTBody(wordwrap($body, 75, "\r\n"));
0ea884 1283     $compose->addAttachment($report, 'message/disposition-notification', 'MDNPart2.txt', false, '7bit', 'inline');
T 1284
1285     $sent = rcmail_deliver_message($compose, $identity['email'], $mailto);
1286
1287     if ($sent)
1288     {
8fa58e 1289       $IMAP->set_flag($message->uid, 'MDNSENT');
0ea884 1290       return true;
T 1291     }
1292   }
1293   
1294   return false;
1295 }
1296
1297
f11541 1298 // register UI objects
T 1299 $OUTPUT->add_handlers(array(
1300   'mailboxlist' => 'rcmail_mailbox_list',
1301   'messages' => 'rcmail_message_list',
1302   'messagecountdisplay' => 'rcmail_messagecount_display',
1303   'quotadisplay' => 'rcmail_quota_display',
ac5d15 1304   'mailboxname' => 'rcmail_mailbox_name_display',
f11541 1305   'messageheaders' => 'rcmail_message_headers',
T 1306   'messagebody' => 'rcmail_message_body',
1307   'messagecontentframe' => 'rcmail_messagecontent_frame',
1308   'messagepartframe' => 'rcmail_message_part_frame',
1309   'messagepartcontrols' => 'rcmail_message_part_controls',
47124c 1310   'searchform' => array($OUTPUT, 'search_form'),
f11541 1311 ));
T 1312
93be5b 1313 ?>