thomascube
2007-11-25 d5342aabcfeddb959cc286befe6de5bf35fe9d76
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                     |
f11541 8  | Copyright (C) 2005-2007, 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/html2text.inc');
23 require_once('lib/enriched.inc');
24
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']]))
T 50   $IMAP->set_search_set($_SESSION['search'][$_REQUEST['_search']]);
2bca6e 51
6a35c8 52
4e17e6 53 // define url for getting message parts
T 54 if (strlen($_GET['_uid']))
41bece 55   $GET_URL = rcmail_url('get', array('_mbox'=>$IMAP->get_mailbox_name(), '_uid'=>get_input_value('_uid', RCUBE_INPUT_GET)));
4e17e6 56
T 57
58 // set current mailbox in client environment
f11541 59 $OUTPUT->set_env('mailbox', $IMAP->get_mailbox_name());
719804 60 $OUTPUT->set_env('quota', $IMAP->get_capability('quota'));
4e17e6 61
T 62 if ($CONFIG['trash_mbox'])
f11541 63   $OUTPUT->set_env('trash_mailbox', $CONFIG['trash_mbox']);
1966c5 64 if ($CONFIG['drafts_mbox'])
f11541 65   $OUTPUT->set_env('drafts_mailbox', $CONFIG['drafts_mbox']);
b4b081 66 if ($CONFIG['junk_mbox'])
f11541 67   $OUTPUT->set_env('junk_mailbox', $CONFIG['junk_mbox']);
T 68
69 if (!$OUTPUT->ajax_call)
eb6842 70   rcube_add_label('checkingmail', 'deletemessage', 'movemessagetotrash');
f11541 71
5eee00 72 // set page title
T 73 if (empty($_action) || $_action == 'list')
74   $OUTPUT->set_pagetitle(rcube_charset_convert($IMAP->get_mailbox_name(), 'UTF-7'));
75
4e17e6 76
T 77
78 // return the message list as HTML table
79 function rcmail_message_list($attrib)
80   {
f11541 81   global $IMAP, $CONFIG, $COMM_PATH, $OUTPUT;
b076a4 82
4e17e6 83   $skin_path = $CONFIG['skin_path'];
T 84   $image_tag = '<img src="%s%s" alt="%s" border="0" />';
b076a4 85
f3b659 86   // check to see if we have some settings for sorting
6a35c8 87   $sort_col   = $_SESSION['sort_col'];
T 88   $sort_order = $_SESSION['sort_order'];
24053e 89   
T 90   // add some labels to client
91   rcube_add_label('from', 'to');
f3b659 92
4e17e6 93   // get message headers
f3b659 94   $a_headers = $IMAP->list_headers('', '', $sort_col, $sort_order);
4e17e6 95
T 96   // add id to message list table if not specified
97   if (!strlen($attrib['id']))
98     $attrib['id'] = 'rcubemessagelist';
99
100   // allow the following attributes to be added to the <table> tag
101   $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary'));
102
103   $out = '<table' . $attrib_str . ">\n";
e0ddd4 104
T 105
4e17e6 106   // define list of cols to be displayed
T 107   $a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject');
c8c1e0 108   $a_sort_cols = array('subject', 'date', 'from', 'to', 'size');
41bece 109
T 110   $mbox = $IMAP->get_mailbox_name();
4e17e6 111   
T 112   // show 'to' instead of from in sent messages
41bece 113   if (($mbox==$CONFIG['sent_mbox'] || $mbox==$CONFIG['drafts_mbox']) && ($f = array_search('from', $a_show_cols))
8c2e58 114       && !array_search('to', $a_show_cols))
4e17e6 115     $a_show_cols[$f] = 'to';
8c2e58 116   
e0ddd4 117   // add col definition
T 118   $out .= '<colgroup>';
01c86f 119   $out .= '<col class="icon" />';
e0ddd4 120
T 121   foreach ($a_show_cols as $col)
01c86f 122     $out .= sprintf('<col class="%s" />', $col);
e0ddd4 123
01c86f 124   $out .= '<col class="icon" />';
e0ddd4 125   $out .= "</colgroup>\n";
4e17e6 126
T 127   // add table title
128   $out .= "<thead><tr>\n<td class=\"icon\">&nbsp;</td>\n";
b076a4 129
f3b659 130   $javascript = '';
4e17e6 131   foreach ($a_show_cols as $col)
f3b659 132     {
T 133     // get column name
2bca6e 134     $col_name = Q(rcube_label($col));
f3b659 135
T 136     // make sort links
137     $sort = '';
1cded8 138     if ($IMAP->get_capability('sort') && in_array($col, $a_sort_cols))
f3b659 139       {
1cded8 140       // have buttons configured
T 141       if (!empty($attrib['sortdescbutton']) || !empty($attrib['sortascbutton']))
142         {
143         $sort = '&nbsp;&nbsp;';
b076a4 144
1cded8 145         // asc link
T 146         if (!empty($attrib['sortascbutton']))
147           {
f11541 148           $sort .= $OUTPUT->button(array(
T 149             'command' => 'sort',
150             'prop' => $col.'_ASC',
151             'image' => $attrib['sortascbutton'],
152             'align' => 'absmiddle',
153             'title' => 'sortasc'));
1cded8 154           }       
b076a4 155         
1cded8 156         // desc link
T 157         if (!empty($attrib['sortdescbutton']))
158           {
f11541 159           $sort .= $OUTPUT->button(array(
T 160             'command' => 'sort',
161             'prop' => $col.'_DESC',
162             'image' => $attrib['sortdescbutton'],
163             'align' => 'absmiddle',
164             'title' => 'sortdesc'));
1cded8 165           }
T 166         }
167       // just add a link tag to the header
168       else
b076a4 169         {
41bece 170         $col_name = sprintf(
T 171           '<a href="./#sort" onclick="return %s.command(\'sort\',\'%s\',this)" title="%s">%s</a>',
172           JS_OBJECT_NAME,
173           $col,
174           rcube_label('sortby'),
175           $col_name);
b076a4 176         }
f3b659 177       }
b076a4 178       
T 179     $sort_class = $col==$sort_col ? " sorted$sort_order" : '';
f3b659 180
T 181     // put it all together
b076a4 182     $out .= '<td class="'.$col.$sort_class.'" id="rcmHead'.$col.'">' . "$col_name$sort</td>\n";    
f3b659 183     }
4e17e6 184
T 185   $out .= '<td class="icon">'.($attrib['attachmenticon'] ? sprintf($image_tag, $skin_path, $attrib['attachmenticon'], '') : '')."</td>\n";
186   $out .= "</tr></thead>\n<tbody>\n";
187
188   // no messages in this mailbox
189   if (!sizeof($a_headers))
5eee00 190     $OUTPUT->show_message('nomessagesfound', 'notice');
4e17e6 191
T 192
193   $a_js_message_arr = array();
194
195   // create row for each message
196   foreach ($a_headers as $i => $header)  //while (list($i, $header) = each($a_headers))
197     {
198     $message_icon = $attach_icon = '';
199     $js_row_arr = array();
200     $zebra_class = $i%2 ? 'even' : 'odd';
201
202     // set messag attributes to javascript array
6ec0a8 203     if ($header->deleted)
S 204       $js_row_arr['deleted'] = true;
4e17e6 205     if (!$header->seen)
T 206       $js_row_arr['unread'] = true;
207     if ($header->answered)
208       $js_row_arr['replied'] = true;
6ec0a8 209     // set message icon  
S 210     if ($attrib['deletedicon'] && $header->deleted)
211       $message_icon = $attrib['deletedicon'];
212     else if ($attrib['unreadicon'] && !$header->seen)
4e17e6 213       $message_icon = $attrib['unreadicon'];
T 214     else if ($attrib['repliedicon'] && $header->answered)
215       $message_icon = $attrib['repliedicon'];
216     else if ($attrib['messageicon'])
217       $message_icon = $attrib['messageicon'];
218     
f11541 219     // set attachment icon
8d4bcd 220     if ($attrib['attachmenticon'] && preg_match("/multipart\/[mr]/i", $header->ctype))
4e17e6 221       $attach_icon = $attrib['attachmenticon'];
T 222         
15a9d1 223     $out .= sprintf('<tr id="rcmrow%d" class="message%s%s %s">'."\n",
T 224                     $header->uid,
225                     $header->seen ? '' : ' unread',
226                     $header->deleted ? ' deleted' : '',
227                     $zebra_class);    
228     
4e17e6 229     $out .= sprintf("<td class=\"icon\">%s</td>\n", $message_icon ? sprintf($image_tag, $skin_path, $message_icon, '') : '');
f11541 230     
4e17e6 231     // format each col
T 232     foreach ($a_show_cols as $col)
233       {
234       if ($col=='from' || $col=='to')
2bca6e 235         $cont = Q(rcmail_address_string($header->$col, 3, $attrib['addicon']), 'show');
4e17e6 236       else if ($col=='subject')
b4b081 237         {
41bece 238         $action = $mbox==$CONFIG['drafts_mbox'] ? 'compose' : 'show';
T 239         $uid_param = $mbox==$CONFIG['drafts_mbox'] ? '_draf_uid' : '_uid';
f11541 240         $cont = Q(rcube_imap::decode_mime_string($header->$col, $header->charset));
T 241         if (empty($cont)) $cont = Q(rcube_label('nosubject'));
b2fb95 242         $cont = sprintf('<a href="%s" onclick="return rcube_event.cancel(event)">%s</a>', Q(rcmail_url($action, array($uid_param=>$header->uid, '_mbox'=>$mbox))), $cont);
b4b081 243         }
4e17e6 244       else if ($col=='size')
T 245         $cont = show_bytes($header->$col);
246       else if ($col=='date')
f11541 247         $cont = format_date($header->date);
4e17e6 248       else
2bca6e 249         $cont = Q($header->$col);
4e17e6 250         
2bca6e 251       $out .= '<td class="'.$col.'">' . $cont . "</td>\n";
4e17e6 252       }
T 253
254     $out .= sprintf("<td class=\"icon\">%s</td>\n", $attach_icon ? sprintf($image_tag, $skin_path, $attach_icon, '') : '');
255     $out .= "</tr>\n";
256     
257     if (sizeof($js_row_arr))
258       $a_js_message_arr[$header->uid] = $js_row_arr;
259     }
260   
261   // complete message table
262   $out .= "</tbody></table>\n";
263   
264   
265   $message_count = $IMAP->messagecount();
266   
267   // set client env
f11541 268   $OUTPUT->add_gui_object('mailcontframe', 'mailcontframe');
T 269   $OUTPUT->add_gui_object('messagelist', $attrib['id']);
270   $OUTPUT->set_env('messagecount', $message_count);
271   $OUTPUT->set_env('current_page', $IMAP->list_page);
272   $OUTPUT->set_env('pagecount', ceil($message_count/$IMAP->page_size));
273   $OUTPUT->set_env('sort_col', $sort_col);
274   $OUTPUT->set_env('sort_order', $sort_order);
4e17e6 275   
T 276   if ($attrib['messageicon'])
f11541 277     $OUTPUT->set_env('messageicon', $skin_path . $attrib['messageicon']);
6ec0a8 278   if ($attrib['deletedicon'])
f11541 279     $OUTPUT->set_env('deletedicon', $skin_path . $attrib['deletedicon']);
4e17e6 280   if ($attrib['unreadicon'])
f11541 281     $OUTPUT->set_env('unreadicon', $skin_path . $attrib['unreadicon']);
4e17e6 282   if ($attrib['repliedicon'])
f11541 283     $OUTPUT->set_env('repliedicon', $skin_path . $attrib['repliedicon']);
4e17e6 284   if ($attrib['attachmenticon'])
f11541 285     $OUTPUT->set_env('attachmenticon', $skin_path . $attrib['attachmenticon']);
4e17e6 286   
ae895a 287   $OUTPUT->set_env('messages', $a_js_message_arr);
f11541 288   
6b47de 289   $OUTPUT->include_script('list.js');
4e17e6 290   
T 291   return $out;
292   }
293
294
295 // return javascript commands to add rows to the message list
296 function rcmail_js_message_list($a_headers, $insert_top=FALSE)
297   {
f11541 298   global $CONFIG, $IMAP, $OUTPUT;
4e17e6 299
T 300   $a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject');
41bece 301   $mbox = $IMAP->get_mailbox_name();
4e17e6 302
T 303   // show 'to' instead of from in sent messages
41bece 304   if (($mbox == $CONFIG['sent_mbox'] || $mbox == $CONFIG['drafts_mbox'])
f11541 305       && (($f = array_search('from', $a_show_cols)) !== false) && array_search('to', $a_show_cols) === false)
4e17e6 306     $a_show_cols[$f] = 'to';
T 307
f11541 308   $OUTPUT->command('set_message_coltypes', $a_show_cols);
25d8ba 309
4e17e6 310   // loop through message headers
ecd2e7 311   foreach ($a_headers as $n => $header)
4e17e6 312     {
T 313     $a_msg_cols = array();
314     $a_msg_flags = array();
ecd2e7 315     
T 316     if (empty($header))
317       continue;
f11541 318
4e17e6 319     // format each col; similar as in rcmail_message_list()
T 320     foreach ($a_show_cols as $col)
321       {
322       if ($col=='from' || $col=='to')
2bca6e 323         $cont = Q(rcmail_address_string($header->$col, 3), 'show');
4e17e6 324       else if ($col=='subject')
7bbd5f 325         {
41bece 326         $action = $mbox==$CONFIG['drafts_mbox'] ? 'compose' : 'show';
T 327         $uid_param = $mbox==$CONFIG['drafts_mbox'] ? '_draf_uid' : '_uid';
f11541 328         $cont = Q(rcube_imap::decode_mime_string($header->$col, $header->charset));
7bbd5f 329         if (!$cont) $cont = Q(rcube_label('nosubject'));
b2fb95 330         $cont = sprintf('<a href="%s" onclick="return rcube_event.cancel(event)">%s</a>', Q(rcmail_url($action, array($uid_param=>$header->uid, '_mbox'=>$mbox))), $cont);
7bbd5f 331         }
4e17e6 332       else if ($col=='size')
T 333         $cont = show_bytes($header->$col);
334       else if ($col=='date')
f11541 335         $cont = format_date($header->date);
4e17e6 336       else
2bca6e 337         $cont = Q($header->$col);
4e17e6 338           
T 339       $a_msg_cols[$col] = $cont;
340       }
341
6ec0a8 342     $a_msg_flags['deleted'] = $header->deleted ? 1 : 0;
4e17e6 343     $a_msg_flags['unread'] = $header->seen ? 0 : 1;
T 344     $a_msg_flags['replied'] = $header->answered ? 1 : 0;
f11541 345     $OUTPUT->command('add_message_row',
T 346       $header->uid,
347       $a_msg_cols,
348       $a_msg_flags,
349       preg_match("/multipart\/m/i", $header->ctype),
350       $insert_top);
4e17e6 351     }
T 352   }
353
354
b19097 355 // return an HTML iframe for loading mail content
T 356 function rcmail_messagecontent_frame($attrib)
357   {
f11541 358   global $OUTPUT;
b19097 359   
T 360   if (empty($attrib['id']))
361     $attrib['id'] = 'rcmailcontentwindow';
362
363   // allow the following attributes to be added to the <iframe> tag
364   $attrib_str = create_attrib_string($attrib, array('id', 'class', 'style', 'src', 'width', 'height', 'frameborder'));
365   $framename = $attrib['id'];
366
367   $out = sprintf('<iframe name="%s"%s></iframe>'."\n",
368          $framename,
369          $attrib_str);
370
f11541 371   $OUTPUT->set_env('contentframe', $framename);
T 372   $OUTPUT->set_env('blankpage', $attrib['src'] ? $OUTPUT->abs_url($attrib['src']) : 'program/blank.gif');
b19097 373
T 374   return $out;
375   }
376
4e17e6 377
T 378 function rcmail_messagecount_display($attrib)
379   {
f11541 380   global $IMAP, $OUTPUT;
4e17e6 381   
T 382   if (!$attrib['id'])
383     $attrib['id'] = 'rcmcountdisplay';
384
f11541 385   $OUTPUT->add_gui_object('countdisplay', $attrib['id']);
4e17e6 386
T 387   // allow the following attributes to be added to the <span> tag
388   $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id'));
389
390   
391   $out = '<span' . $attrib_str . '>';
392   $out .= rcmail_get_messagecount_text();
393   $out .= '</span>';
394   return $out;
395   }
396
397
58e360 398 function rcmail_quota_display($attrib)
T 399   {
f11541 400   global $OUTPUT, $COMM_PATH;
58e360 401
T 402   if (!$attrib['id'])
403     $attrib['id'] = 'rcmquotadisplay';
404
f11541 405   $OUTPUT->add_gui_object('quotadisplay', $attrib['id']);
58e360 406
T 407   // allow the following attributes to be added to the <span> tag
2bca6e 408   $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id'));
23796e 409
S 410   $out = '<span' . $attrib_str . '>';
411   $out .= rcmail_quota_content($attrib['display']);
412   $out .= '</span>';
413   return $out;
414   }
415
416
417 function rcmail_quota_content($display)
418   {
419   global $IMAP, $COMM_PATH;
3ea0e3 420
4647e1 421   if (!$IMAP->get_capability('QUOTA'))
T 422     $quota_text = rcube_label('unknown');
3ea0e3 423   else if ($quota = $IMAP->get_quota())
T 424     {
425     $quota_text = sprintf("%s / %s (%.0f%%)",
426                           show_bytes($quota["used"] * 1024),
427                           show_bytes($quota["total"] * 1024),
428                           $quota["percent"]);
429
430     // show quota as image (by Brett Patterson)
23796e 431     if ($display == 'image' && function_exists('imagegif'))
3ea0e3 432       {
23796e 433       $attrib = array('width' => 100, 'height' => 14);
f11541 434       $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 435                             $quota['used'], $quota['total'],
fda695 436                             $attrib['width'], $attrib['height'],
T 437                             $attrib['width'], $attrib['height'],
438                             $quota_text,
439                             show_bytes($quota["used"] * 1024),
440                             show_bytes($quota["total"] * 1024));
3ea0e3 441       }
T 442     }
443   else
4647e1 444     $quota_text = rcube_label('unlimited');
58e360 445
23796e 446   return $quota_text;
58e360 447   }
T 448
4e17e6 449
4647e1 450 function rcmail_get_messagecount_text($count=NULL, $page=NULL)
4e17e6 451   {
T 452   global $IMAP, $MESSAGE;
453   
454   if (isset($MESSAGE['index']))
455     {
456     return rcube_label(array('name' => 'messagenrof',
457                              'vars' => array('nr'  => $MESSAGE['index']+1,
4647e1 458                                              'count' => $count!==NULL ? $count : $IMAP->messagecount())));
4e17e6 459     }
31b2ce 460
4647e1 461   if ($page===NULL)
T 462     $page = $IMAP->list_page;
463     
464   $start_msg = ($page-1) * $IMAP->page_size + 1;
465   $max = $count!==NULL ? $count : $IMAP->messagecount();
4e17e6 466
T 467   if ($max==0)
468     $out = rcube_label('mailboxempty');
469   else
470     $out = rcube_label(array('name' => 'messagesfromto',
471                               'vars' => array('from'  => $start_msg,
472                                               'to'    => min($max, $start_msg + $IMAP->page_size - 1),
473                                               'count' => $max)));
474
2bca6e 475   return Q($out);
4e17e6 476   }
T 477
478
8d4bcd 479 function rcmail_print_body($part, $safe=FALSE, $plain=FALSE)
4e17e6 480   {
f11541 481   global $IMAP, $REMOTE_OBJECTS;
4e17e6 482   
8d4bcd 483   $body = is_array($part->replaces) ? strtr($part->body, $part->replaces) : $part->body;
a0109c 484
5cc4b1 485   // convert html to text/plain
T 486   if ($part->ctype_secondary=='html' && $plain)
487     {
488     $txt = new html2text($body, false, true);
489     $body = $txt->get_text();
490     $part->ctype_secondary = 'plain';
491     }
492     
4e17e6 493   // text/html
8d4bcd 494   if ($part->ctype_secondary=='html')
4e17e6 495     {
f7bfec 496     // remove charset specification in HTML message
T 497     $body = preg_replace('/charset=[a-z0-9\-]+/i', '', $body);
498
4e17e6 499     if (!$safe)  // remove remote images and scripts
T 500       {
ea206d 501       $remote_patterns = array('/<img\s+(.*)src=(["\']?)([hftps]{3,5}:\/{2}[^"\'\s]+)(\2|\s|>)/Ui',
T 502                                '/(src|background)=(["\']?)([hftps]{3,5}:\/{2}[^"\'\s]+)(\2|\s|>)/Ui',
4e17e6 503                                '/(<base.*href=["\']?)([hftps]{3,5}:\/{2}[^"\'\s]+)([^<]*>)/i',
T 504                                '/(<link.*href=["\']?)([hftps]{3,5}:\/{2}[^"\'\s]+)([^<]*>)/i',
505                                '/url\s*\(["\']?([hftps]{3,5}:\/{2}[^"\'\s]+)["\']?\)/i',
506                                '/url\s*\(["\']?([\.\/]+[^"\'\s]+)["\']?\)/i',
507                                '/<script.+<\/script>/Umis');
508
ee883a 509       $remote_replaces = array('<img \\1src=\\2./program/blocked.gif\\4',
4e17e6 510                                '',
ea206d 511                                '',
T 512                                '',
4e17e6 513                                'none',
T 514                                'none',
515                                '');
516       
517       // set flag if message containes remote obejcts that where blocked
518       foreach ($remote_patterns as $pattern)
519         {
520         if (preg_match($pattern, $body))
521           {
522           $REMOTE_OBJECTS = TRUE;
523           break;
524           }
525         }
526
527       $body = preg_replace($remote_patterns, $remote_replaces, $body);
528       }
529
2bca6e 530     return Q($body, 'show', FALSE);
4e17e6 531     }
T 532
533   // text/enriched
8d4bcd 534   if ($part->ctype_secondary=='enriched')
4e17e6 535     {
2bca6e 536     return Q(enriched_to_html($body), 'show');
4e17e6 537     }
T 538   else
539     {
540     // make links and email-addresses clickable
541     $convert_patterns = $convert_replaces = $replace_strings = array();
542     
949dea 543     $url_chars = 'a-z0-9_\-\+\*\$\/&%=@#:;';
4e17e6 544     $url_chars_within = '\?\.~,!';
T 545
546     $convert_patterns[] = "/([\w]+):\/\/([a-z0-9\-\.]+[a-z]{2,4}([$url_chars$url_chars_within]*[$url_chars])?)/ie";
20a1b3 547     $convert_replaces[] = "rcmail_str_replacement('<a href=\"\\1://\\2\" target=\"_blank\">\\1://\\2</a>', \$replace_strings)";
4e17e6 548
T 549     $convert_patterns[] = "/([^\/:]|\s)(www\.)([a-z0-9\-]{2,}[a-z]{2,4}([$url_chars$url_chars_within]*[$url_chars])?)/ie";
20a1b3 550     $convert_replaces[] = "rcmail_str_replacement('\\1<a href=\"http://\\2\\3\" target=\"_blank\">\\2\\3</a>', \$replace_strings)";
4e17e6 551     
T 552     $convert_patterns[] = '/([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9]\\.[a-z]{2,5})/ie';
f11541 553     $convert_replaces[] = "rcmail_str_replacement('<a href=\"mailto:\\1\" onclick=\"return ".JS_OBJECT_NAME.".command(\'compose\',\'\\1\',this)\">\\1</a>', \$replace_strings)";
10c92b 554     
T 555     if ($part->ctype_parameters['format'] != 'flowed')
556       $body = wordwrap(trim($body), 80);
4e17e6 557
T 558     $body = preg_replace($convert_patterns, $convert_replaces, $body);
559
560     // split body into single lines
561     $a_lines = preg_split('/\r?\n/', $body);
10c92b 562     $quote_level = 0;
4e17e6 563
T 564     // colorize quoted parts
565     for($n=0; $n<sizeof($a_lines); $n++)
566       {
567       $line = $a_lines[$n];
10c92b 568       $quotation = '';
T 569       $q = 0;
570       
571       if (preg_match('/^(>+\s*)/', $line, $regs))
572         {
573         $q = strlen(preg_replace('/\s/', '', $regs[1]));
574         $line = substr($line, strlen($regs[1]));
4e17e6 575
10c92b 576         if ($q > $quote_level)
T 577           $quotation = str_repeat('<blockquote>', $q - $quote_level);
578         else if ($q < $quote_level)
579           $quotation = str_repeat("</blockquote>", $quote_level - $q);
580         }
581       else if ($quote_level > 0)
582         $quotation = str_repeat("</blockquote>", $quote_level);
4e17e6 583
10c92b 584       $quote_level = $q;
2bca6e 585       $a_lines[$n] = $quotation . Q($line, 'replace', FALSE);
4e17e6 586       }
T 587
588     // insert the links for urls and mailtos
589     $body = preg_replace("/##string_replacement\{([0-9]+)\}##/e", "\$replace_strings[\\1]", join("\n", $a_lines));
590     
ea206d 591     return "<div class=\"pre\">".$body."\n</div>";
4e17e6 592     }
T 593   }
594
595
596
597 // add a string to the replacement array and return a replacement string
598 function rcmail_str_replacement($str, &$rep)
599   {
600   static $count = 0;
601   $rep[$count] = stripslashes($str);
602   return "##string_replacement{".($count++)."}##";
603   }
604
605
8d4bcd 606 function rcmail_parse_message(&$structure, $arg=array(), $recursive=FALSE)
4e17e6 607   {
T 608   global $IMAP;
609   static $sa_inline_objects = array();
610
611   // arguments are: (bool)$prefer_html, (string)$get_url
612   extract($arg);
613
614   $a_attachments = array();
615   $a_return_parts = array();
616   $out = '';
617
618   $message_ctype_primary = strtolower($structure->ctype_primary);
619   $message_ctype_secondary = strtolower($structure->ctype_secondary);
620
621   // show message headers
622   if ($recursive && is_array($structure->headers) && isset($structure->headers['subject']))
8d4bcd 623     {
T 624     $c = new stdClass;
625     $c->type = 'headers';
626     $c->headers = &$structure->headers;
627     $a_return_parts[] = $c;
628     }
4e17e6 629
T 630   // print body if message doesn't have multiple parts
631   if ($message_ctype_primary=='text')
632     {
8d4bcd 633     $structure->type = 'content';
T 634     $a_return_parts[] = &$structure;
4e17e6 635     }
T 636
637   // message contains alternative parts
638   else if ($message_ctype_primary=='multipart' && $message_ctype_secondary=='alternative' && is_array($structure->parts))
639     {
640     // get html/plaintext parts
641     $plain_part = $html_part = $print_part = $related_part = NULL;
642     
643     foreach ($structure->parts as $p => $sub_part)
644       {
719a25 645       $rel_parts = $attachmnts = null;
4e17e6 646       $sub_ctype_primary = strtolower($sub_part->ctype_primary);
T 647       $sub_ctype_secondary = strtolower($sub_part->ctype_secondary);
648
649       // check if sub part is 
650       if ($sub_ctype_primary=='text' && $sub_ctype_secondary=='plain')
651         $plain_part = $p;
652       else if ($sub_ctype_primary=='text' && $sub_ctype_secondary=='html')
653         $html_part = $p;
654       else if ($sub_ctype_primary=='text' && $sub_ctype_secondary=='enriched')
655         $enriched_part = $p;
719a25 656       else if ($sub_ctype_primary=='multipart' && ($sub_ctype_secondary=='related' || $sub_ctype_secondary=='mixed'))
4e17e6 657         $related_part = $p;
T 658       }
719a25 659       
4e17e6 660     // parse related part (alternative part could be in here)
719a25 661     if ($related_part!==NULL)
T 662     {
663       list($rel_parts, $attachmnts) = rcmail_parse_message($structure->parts[$related_part], $arg, TRUE);
4e17e6 664       $a_attachments = array_merge($a_attachments, $attachmnts);
719a25 665     }
T 666     
667     // merge related parts if any
668     if ($rel_parts && $prefer_html && !$html_part)
669       $a_return_parts = array_merge($a_return_parts, $rel_parts);
4e17e6 670
719a25 671     // choose html/plain part to print
4e17e6 672     else if ($html_part!==NULL && $prefer_html)
8d4bcd 673       $print_part = &$structure->parts[$html_part];
4e17e6 674     else if ($enriched_part!==NULL)
8d4bcd 675       $print_part = &$structure->parts[$enriched_part];
4e17e6 676     else if ($plain_part!==NULL)
8d4bcd 677       $print_part = &$structure->parts[$plain_part];
4e17e6 678
T 679     // show message body
680     if (is_object($print_part))
8d4bcd 681       {
T 682       $print_part->type = 'content';
683       $a_return_parts[] = $print_part;
684       }
4e17e6 685     // show plaintext warning
719a25 686     else if ($html_part!==NULL && empty($a_return_parts))
8d4bcd 687       {
T 688       $c = new stdClass;
689       $c->type = 'content';
690       $c->body = rcube_label('htmlmessage');
691       $c->ctype_primary = 'text';
692       $c->ctype_secondary = 'plain';
693       
694       $a_return_parts[] = $c;
695       }
4e17e6 696                                 
T 697     // add html part as attachment
698     if ($html_part!==NULL && $structure->parts[$html_part]!==$print_part)
699       {
8d4bcd 700       $html_part = &$structure->parts[$html_part];
T 701       $html_part->filename = rcube_label('htmlmessage');
702       $html_part->mimetype = 'text/html';
703       
704       $a_attachments[] = $html_part;
4e17e6 705       }
T 706     }
707
708   // message contains multiple parts
8d4bcd 709   else if (is_array($structure->parts) && !empty($structure->parts))
4e17e6 710     {
8d4bcd 711     for ($i=0; $i<count($structure->parts); $i++)
4e17e6 712       {
8d4bcd 713       $mail_part = &$structure->parts[$i];
4e17e6 714       $primary_type = strtolower($mail_part->ctype_primary);
T 715       $secondary_type = strtolower($mail_part->ctype_secondary);
716
717       // multipart/alternative
8d4bcd 718       if ($primary_type=='multipart')
4e17e6 719         {
T 720         list($parts, $attachmnts) = rcmail_parse_message($mail_part, $arg, TRUE);
721
722         $a_return_parts = array_merge($a_return_parts, $parts);
723         $a_attachments = array_merge($a_attachments, $attachmnts);
724         }
725
726       // part text/[plain|html] OR message/delivery-status
58e360 727       else if (($primary_type=='text' && ($secondary_type=='plain' || $secondary_type=='html') && $mail_part->disposition!='attachment') ||
4e17e6 728                ($primary_type=='message' && $secondary_type=='delivery-status'))
T 729         {
8d4bcd 730         $mail_part->type = 'content';
T 731         $a_return_parts[] = $mail_part;
4e17e6 732         }
T 733
734       // part message/*
735       else if ($primary_type=='message')
736         {
8d4bcd 737         list($parts, $attachmnts) = rcmail_parse_message($mail_part, $arg, TRUE);
T 738           
4e17e6 739         $a_return_parts = array_merge($a_return_parts, $parts);
T 740         $a_attachments = array_merge($a_attachments, $attachmnts);
741         }
742
743       // part is file/attachment
b595c9 744       else if ($mail_part->disposition=='attachment' || $mail_part->disposition=='inline' || $mail_part->headers['content-id'] ||
5cc4b1 745                (empty($mail_part->disposition) && $mail_part->filename))
4e17e6 746         {
bb8562 747         // skip apple resource forks
8d4bcd 748         if ($message_ctype_secondary=='appledouble' && $secondary_type=='applefile')
T 749           continue;
4e17e6 750
8d4bcd 751         // part belongs to a related message
T 752         if ($message_ctype_secondary=='related' && $mail_part->headers['content-id'])
753           {
754           $mail_part->content_id = preg_replace(array('/^</', '/>$/'), '', $mail_part->headers['content-id']);
755           $sa_inline_objects[] = $mail_part;
756           }
757         // is regular attachment
fd3934 758         else
T 759           {
760           if (!$mail_part->filename)
761             $mail_part->filename = 'file_'.$mail_part->mime_id;
8d4bcd 762           $a_attachments[] = $mail_part;
fd3934 763           }
4e17e6 764         }
T 765       }
766
767     // if this was a related part try to resolve references
768     if ($message_ctype_secondary=='related' && sizeof($sa_inline_objects))
769       {
8d4bcd 770       $a_replaces = array();
4e17e6 771         
T 772       foreach ($sa_inline_objects as $inline_object)
ea206d 773         $a_replaces['cid:'.$inline_object->content_id] = htmlspecialchars(sprintf($get_url, $inline_object->mime_id));
4e17e6 774       
8d4bcd 775       // add replace array to each content part
T 776       // (will be applied later when part body is available)
777       for ($i=0; $i<count($a_return_parts); $i++)
4e17e6 778         {
8d4bcd 779         if ($a_return_parts[$i]->type=='content')
T 780           $a_return_parts[$i]->replaces = $a_replaces;
4e17e6 781         }
T 782       }
783     }
784
04d630 785   // message is single part non-text
5cc4b1 786   else if ($structure->filename)
T 787     $a_attachments[] = $structure;
04d630 788
4e17e6 789   return array($a_return_parts, $a_attachments);
T 790   }
791
792
793
794
795 // return table with message headers
796 function rcmail_message_headers($attrib, $headers=NULL)
797   {
798   global $IMAP, $OUTPUT, $MESSAGE;
799   static $sa_attrib;
800   
801   // keep header table attrib
802   if (is_array($attrib) && !$sa_attrib)
803     $sa_attrib = $attrib;
804   else if (!is_array($attrib) && is_array($sa_attrib))
805     $attrib = $sa_attrib;
806   
807   
808   if (!isset($MESSAGE))
809     return FALSE;
810
811   // get associative array of headers object
812   if (!$headers)
813     $headers = is_object($MESSAGE['headers']) ? get_object_vars($MESSAGE['headers']) : $MESSAGE['headers'];
f11541 814   
4e17e6 815   $header_count = 0;
T 816   
817   // allow the following attributes to be added to the <table> tag
818   $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary'));
819   $out = '<table' . $attrib_str . ">\n";
820
821   // show these headers
bde645 822   $standard_headers = array('subject', 'from', 'organization', 'to', 'cc', 'bcc', 'reply-to', 'date');
4e17e6 823   
T 824   foreach ($standard_headers as $hkey)
825     {
826     if (!$headers[$hkey])
827       continue;
828
b076a4 829     if ($hkey=='date' && !empty($headers[$hkey]))
4e17e6 830       $header_value = format_date(strtotime($headers[$hkey]));
bde645 831     else if (in_array($hkey, array('from', 'to', 'cc', 'bcc', 'reply-to')))
2bca6e 832       $header_value = Q(rcmail_address_string($headers[$hkey], NULL, $attrib['addicon']), 'show');
4e17e6 833     else
f11541 834       $header_value = Q(rcube_imap::decode_mime_string($headers[$hkey], $headers['charset']));
4e17e6 835
T 836     $out .= "\n<tr>\n";
2bca6e 837     $out .= '<td class="header-title">'.Q(rcube_label($hkey)).":&nbsp;</td>\n";
4e17e6 838     $out .= '<td class="'.$hkey.'" width="90%">'.$header_value."</td>\n</tr>";
T 839     $header_count++;
840     }
841
842   $out .= "\n</table>\n\n";
843
844   return $header_count ? $out : '';  
845   }
846
847
848
849 function rcmail_message_body($attrib)
850   {
f11541 851   global $CONFIG, $OUTPUT, $MESSAGE, $IMAP, $GET_URL, $REMOTE_OBJECTS;
4e17e6 852   
T 853   if (!is_array($MESSAGE['parts']) && !$MESSAGE['body'])
854     return '';
855     
856   if (!$attrib['id'])
857     $attrib['id'] = 'rcmailMsgBody';
858
c57996 859   $safe_mode = intval($_GET['_safe']);
4e17e6 860   $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id'));
T 861   $out = '<div '. $attrib_str . ">\n";
862   
863   $header_attrib = array();
864   foreach ($attrib as $attr => $value)
865     if (preg_match('/^headertable([a-z]+)$/i', $attr, $regs))
866       $header_attrib[$regs[1]] = $value;
867
868
869   // this is an ecrypted message
870   // -> create a plaintext body with the according message
871   if (!sizeof($MESSAGE['parts']) && $MESSAGE['headers']->ctype=='multipart/encrypted')
872     {
8d4bcd 873     $p = new stdClass;
T 874     $p->type = 'content';
875     $p->ctype_primary = 'text';
876     $p->ctype_secondary = 'plain';
877     $p->body = rcube_label('encryptedmessage');
878     $MESSAGE['parts'][0] = $p;
4e17e6 879     }
T 880   
881   if ($MESSAGE['parts'])
882     {
883     foreach ($MESSAGE['parts'] as $i => $part)
884       {
8d4bcd 885       if ($part->type=='headers')
T 886         $out .= rcmail_message_headers(sizeof($header_attrib) ? $header_attrib : NULL, $part->headers);
887       else if ($part->type=='content')
4e17e6 888         {
8d4bcd 889         if (empty($part->ctype_parameters) || empty($part->ctype_parameters['charset']))
2c9298 890           $part->ctype_parameters['charset'] = $MESSAGE['headers']->charset;
a0109c 891
8d4bcd 892         // fetch part if not available
T 893         if (!isset($part->body))
894           $part->body = $IMAP->get_message_part($MESSAGE['UID'], $part->mime_id, $part);
a0109c 895
5cc4b1 896         $body = rcmail_print_body($part, $safe_mode, !$CONFIG['prefer_html']);
4e17e6 897         $out .= '<div class="message-part">';
a2f2c5 898         
8d4bcd 899         if ($part->ctype_secondary != 'plain')
5cc4b1 900           $out .= rcmail_sanitize_html($body, $attrib['id']);
a2f2c5 901         else
T 902           $out .= $body;
903
4e17e6 904         $out .= "</div>\n";
T 905         }
906       }
907     }
908   else
909     $out .= $MESSAGE['body'];
910
911
912   $ctype_primary = strtolower($MESSAGE['structure']->ctype_primary);
913   $ctype_secondary = strtolower($MESSAGE['structure']->ctype_secondary);
914   
915   // list images after mail body
719a25 916   if (get_boolean($attrib['showimages']) && $ctype_primary=='multipart' &&
T 917       !empty($MESSAGE['attachments']) && !strstr($message_body, '<html') && strlen($GET_URL))
4e17e6 918     {
T 919     foreach ($MESSAGE['attachments'] as $attach_prop)
920       {
8d4bcd 921       if (strpos($attach_prop->mimetype, 'image/')===0)
ea206d 922         $out .= sprintf("\n<hr />\n<p align=\"center\"><img src=\"%s&amp;_part=%s\" alt=\"%s\" title=\"%s\" /></p>\n",
T 923                         htmlspecialchars($GET_URL), $attach_prop->mime_id,
8d4bcd 924                         $attach_prop->filename,
T 925                         $attach_prop->filename);
4e17e6 926       }
T 927     }
928   
929   // tell client that there are blocked remote objects
930   if ($REMOTE_OBJECTS && !$safe_mode)
f11541 931     $OUTPUT->set_env('blockedobjects', true);
4e17e6 932
T 933   $out .= "\n</div>";
934   return $out;
935   }
936
937
938
939 // modify a HTML message that it can be displayed inside a HTML page
5cc4b1 940 function rcmail_sanitize_html($body, $container_id)
4e17e6 941   {
749b07 942   // remove any null-byte characters before parsing
T 943   $body = preg_replace('/\x00/', '', $body);
944   
97bd2c 945   $base_url = "";
4e17e6 946   $last_style_pos = 0;
T 947   $body_lc = strtolower($body);
97bd2c 948   
T 949   // check for <base href>
950   if (preg_match(($base_reg = '/(<base.*href=["\']?)([hftps]{3,5}:\/{2}[^"\'\s]+)([^<]*>)/i'), $body, $base_regs))
951     $base_url = $base_regs[2];
4e17e6 952   
T 953   // find STYLE tags
954   while (($pos = strpos($body_lc, '<style', $last_style_pos)) && ($pos2 = strpos($body_lc, '</style>', $pos)))
955     {
ea206d 956     $pos = strpos($body_lc, '>', $pos)+1;
T 957
4e17e6 958     // replace all css definitions with #container [def]
97bd2c 959     $styles = rcmail_mod_css_styles(substr($body, $pos, $pos2-$pos), $container_id, $base_url);
ea206d 960
3b12ae 961     $body = substr($body, 0, $pos) . $styles . substr($body, $pos2);
S 962     $body_lc = strtolower($body);
4e17e6 963     $last_style_pos = $pos2;
T 964     }
965
966
967   // remove SCRIPT tags
6a35c8 968   foreach (array('script', 'applet', 'object', 'embed', 'iframe') as $tag)
4e17e6 969     {
a08a60 970     while (($pos = strpos($body_lc, '<'.$tag)) && (($pos2 = strpos($body_lc, '</'.$tag.'>', $pos)) || ($pos3 = strpos($body_lc, '>', $pos))))
6a35c8 971       {
a08a60 972       $end = $pos2 ? $pos2 + strlen('</'.$tag.'>') : $pos3 + 1;
T 973       $body = substr($body, 0, $pos) . substr($body, $end, strlen($body)-$end);
6a35c8 974       $body_lc = strtolower($body);
T 975       }
4e17e6 976     }
6a35c8 977
T 978   // replace event handlers on any object
5e98e1 979   while ($body != $prev_body)
S 980     {
981     $prev_body = $body;
18e2a3 982     $body = preg_replace('/(<[^!][^>]*\s)(on[^=>]+)=([^>]+>)/im', '$1__removed=$3', $body);
T 983     $body = preg_replace('/(<[^!][^>]*\shref=["\']?)(javascript:)([^>]*?>)/im', '$1null:$3', $body);
5e98e1 984     }
4e17e6 985
T 986   // resolve <base href>
97bd2c 987   if ($base_url)
4e17e6 988     {
T 989     $body = preg_replace('/(src|background|href)=(["\']?)([\.\/]+[^"\'\s]+)(\2|\s|>)/Uie', "'\\1=\"'.make_absolute_url('\\3', '$base_url').'\"'", $body);
990     $body = preg_replace('/(url\s*\()(["\']?)([\.\/]+[^"\'\)\s]+)(\2)\)/Uie', "'\\1\''.make_absolute_url('\\3', '$base_url').'\')'", $body);
991     $body = preg_replace($base_reg, '', $body);
992     }
fe79b1 993     
T 994   // modify HTML links to open a new window if clicked
97bd2c 995   $body = preg_replace('/<(a|link)\s+([^>]+)>/Uie', "rcmail_alter_html_link('\\1','\\2', '$container_id');", $body);
4e17e6 996
T 997   // add comments arround html and other tags
06895c 998   $out = preg_replace(array(
T 999       '/(<!DOCTYPE.+)/i',
1000       '/(<\/?html[^>]*>)/i',
1001       '/(<\/?head[^>]*>)/i',
1002       '/(<title[^>]*>.*<\/title>)/Ui',
1003       '/(<\/?meta[^>]*>)/i'),
1004     '<!--\\1-->',
1005     $body);
a0109c 1006
97bd2c 1007   $out = preg_replace(
T 1008     array(
1009       '/<body([^>]*)>/i',
1010       '/<\/body>/i',
1011     ),
1012     array(
1013       '<div class="rcmBody"\\1>',
1014       '</div>',
1015     ),
1016     $out);
a0109c 1017
86958f 1018   // quote <? of php and xml files that are specified as text/html
T 1019   $out = preg_replace(array('/<\?/', '/\?>/'), array('&lt;?', '?&gt;'), $out);
1020
4e17e6 1021   return $out;
T 1022   }
1023
1024
fe79b1 1025 // parse link attributes and set correct target
97bd2c 1026 function rcmail_alter_html_link($tag, $attrs, $container_id)
fe79b1 1027   {
3cf664 1028   $in = preg_replace('/=([^("|\'|\s)]+)(\s|$)/', '="\1"', $in);
97bd2c 1029   $attrib = parse_attrib_string($attrs);
T 1030   
1031   if ($tag == 'link' && preg_match('/^https?:\/\//i', $attrib['href']))
1032     $attrib['href'] = "./bin/modcss.php?u=" . urlencode($attrib['href']) . "&amp;c=" . urlencode($container_id);
fe79b1 1033
97bd2c 1034   else if (stristr((string)$attrib['href'], 'mailto:'))
T 1035     $attrib['onclick'] = sprintf(
1036       "return %s.command('compose','%s',this)",
1037       JS_OBJECT_NAME,
1038       JQ(substr($attrib['href'], 7)));
1039   
fe79b1 1040   else if (!empty($attrib['href']) && $attrib['href']{0}!='#')
T 1041     $attrib['target'] = '_blank';
1042
97bd2c 1043   return "<$tag" . create_attrib_string($attrib, array('href','name','target','onclick','id','class','style','title','rel','type','media')) . ' />';
4e17e6 1044   }
T 1045
1046
a0109c 1047 function rcmail_has_html_part($message_parts)
S 1048 {
1049    if (!is_array($message_parts))
1050       return FALSE;
1051
1052    // check all message parts
1053    foreach ($message_parts as $pid => $part)
1054    {
1055       $mimetype = strtolower($part->ctype_primary.'/'.$part->ctype_secondary);
1056       if ($mimetype=='text/html')
1057       {
1058          return TRUE;
1059       }
1060    }
1061     
1062    return FALSE;
1063 }
1064
1065 // return first HTML part of a message
1066 function rcmail_first_html_part($message_struct)
1067   {
1068   global $IMAP;
1069
1070   if (!is_array($message_struct['parts']))
1071     return FALSE;
1072     
1073   $html_part = NULL;
1074
1075   // check all message parts
1076   foreach ($message_struct['parts'] as $pid => $part)
1077     {
1078     $mimetype = strtolower($part->ctype_primary.'/'.$part->ctype_secondary);
1079     if ($mimetype=='text/html')
1080       {
1081       $html_part = $IMAP->get_message_part($message_struct['UID'], $pid, $part);
1082       }
1083     }
1084
1085   if ($html_part)
1086     {
1087     // remove special chars encoding
1088     //$trans = array_flip(get_html_translation_table(HTML_ENTITIES));
1089     //$html_part = strtr($html_part, $trans);
1090
1091     return $html_part;
1092     }
1093
1094   return FALSE;
1095 }
1096
4e17e6 1097
T 1098 // return first text part of a message
8d4bcd 1099 function rcmail_first_text_part($message_struct)
4e17e6 1100   {
8d4bcd 1101   global $IMAP;
T 1102
e170b4 1103   if (empty($message_struct['parts']))
T 1104     return $message_struct['UID'] ? $IMAP->get_body($message_struct['UID']) : false;
1105
4e17e6 1106   // check all message parts
8d4bcd 1107   foreach ($message_struct['parts'] as $pid => $part)
4e17e6 1108     {
T 1109     $mimetype = strtolower($part->ctype_primary.'/'.$part->ctype_secondary);
8d4bcd 1110
4e17e6 1111     if ($mimetype=='text/plain')
8d4bcd 1112       return $IMAP->get_message_part($message_struct['UID'], $pid, $part);
T 1113
4e17e6 1114     else if ($mimetype=='text/html')
T 1115       {
8d4bcd 1116       $html_part = $IMAP->get_message_part($message_struct['UID'], $pid, $part);
T 1117       
1118       // remove special chars encoding
1119       $trans = array_flip(get_html_translation_table(HTML_ENTITIES));
1120       $html_part = strtr($html_part, $trans);
1121
1122       // create instance of html2text class
1123       $txt = new html2text($html_part);
1124       return $txt->get_text();
4e17e6 1125       }
T 1126     }
1127
1128   return FALSE;
1129   }
1130
1131
1132 // decode address string and re-format it as HTML links
1133 function rcmail_address_string($input, $max=NULL, $addicon=NULL)
1134   {
f11541 1135   global $IMAP, $PRINT_MODE, $CONFIG, $OUTPUT, $EMAIL_ADDRESS_PATTERN;
4e17e6 1136   
T 1137   $a_parts = $IMAP->decode_address_list($input);
1138
1139   if (!sizeof($a_parts))
1140     return $input;
1141
1142   $c = count($a_parts);
1143   $j = 0;
1144   $out = '';
1145
1146   foreach ($a_parts as $part)
1147     {
1148     $j++;
1149     if ($PRINT_MODE)
2bca6e 1150       $out .= sprintf('%s &lt;%s&gt;', Q($part['name']), $part['mailto']);
4e17e6 1151     else if (preg_match($EMAIL_ADDRESS_PATTERN, $part['mailto']))
T 1152       {
1153       $out .= sprintf('<a href="mailto:%s" onclick="return %s.command(\'compose\',\'%s\',this)" class="rcmContactAddress" title="%s">%s</a>',
28bfe4 1154                       Q($part['mailto']),
f11541 1155                       JS_OBJECT_NAME,
28bfe4 1156                       JQ($part['mailto']),
T 1157                       Q($part['mailto']),
2bca6e 1158                       Q($part['name']));
4e17e6 1159                       
T 1160       if ($addicon)
1161         $out .= sprintf('&nbsp;<a href="#add" onclick="return %s.command(\'add-contact\',\'%s\',this)" title="%s"><img src="%s%s" alt="add" border="0" /></a>',
f11541 1162                         JS_OBJECT_NAME,
4e17e6 1163                         urlencode($part['string']),
T 1164                         rcube_label('addtoaddressbook'),
1165                         $CONFIG['skin_path'],
1166                         $addicon);
1167       }
1168     else
1169       {
1170       if ($part['name'])
2bca6e 1171         $out .= Q($part['name']);
4e17e6 1172       if ($part['mailto'])
28bfe4 1173         $out .= (strlen($out) ? ' ' : '') . sprintf('&lt;%s&gt;', Q($part['mailto']));
4e17e6 1174       }
T 1175       
1176     if ($c>$j)
1177       $out .= ','.($max ? '&nbsp;' : ' ');
1178         
1179     if ($max && $j==$max && $c>$j)
1180       {
1181       $out .= '...';
1182       break;
1183       }        
1184     }
1185     
1186   return $out;
1187   }
1188
1189
1190 function rcmail_message_part_controls()
1191   {
1192   global $CONFIG, $IMAP, $MESSAGE;
1193   
d5342a 1194   $part = asciiwords(get_input_value('_part', RCUBE_INPUT_GPC));
c57996 1195   if (!is_array($MESSAGE) || !is_array($MESSAGE['parts']) || !($_GET['_uid'] && $_GET['_part']) || !$MESSAGE['parts'][$part])
4e17e6 1196     return '';
T 1197     
c57996 1198   $part = &$MESSAGE['parts'][$part];
4e17e6 1199   
T 1200   $attrib_str = create_attrib_string($attrib, array('id', 'class', 'style', 'cellspacing', 'cellpadding', 'border', 'summary'));
1201   $out = '<table '. $attrib_str . ">\n";
1202   
1203   if ($filename)
1204     {
1205     $out .= sprintf('<tr><td class="title">%s</td><td>%s</td><td>[<a href="./?%s">%s</a>]</tr>'."\n",
2bca6e 1206                     Q(rcube_label('filename')),
5cc4b1 1207                     Q($part->filename),
4e17e6 1208                     str_replace('_frame=', '_download=', $_SERVER['QUERY_STRING']),
2bca6e 1209                     Q(rcube_label('download')));
4e17e6 1210     }
T 1211     
5cc4b1 1212   if ($part->size)
4e17e6 1213     $out .= sprintf('<tr><td class="title">%s</td><td>%s</td></tr>'."\n",
2bca6e 1214                     Q(rcube_label('filesize')),
5cc4b1 1215                     show_bytes($part->size));
4e17e6 1216   
T 1217   $out .= "\n</table>";
1218   
1219   return $out;
1220   }
1221
1222
1223
1224 function rcmail_message_part_frame($attrib)
1225   {
1226   global $MESSAGE;
1227   
d5342a 1228   $part = $MESSAGE['parts'][asciiwords(get_input_value('_part', RCUBE_INPUT_GPC))];
4e17e6 1229   $ctype_primary = strtolower($part->ctype_primary);
T 1230
719a25 1231   $attrib['src'] = Q('./?'.str_replace('_frame=', ($ctype_primary=='text' ? '_show=' : '_preload='), $_SERVER['QUERY_STRING']));
4e17e6 1232
T 1233   $attrib_str = create_attrib_string($attrib, array('id', 'class', 'style', 'src', 'width', 'height'));
90022e 1234   $out = '<iframe '. $attrib_str . "></iframe>";
4e17e6 1235     
T 1236   return $out;
1237   }
1238
1239
1240 // clear message composing settings
1241 function rcmail_compose_cleanup()
1242   {
1243   if (!isset($_SESSION['compose']))
1244     return;
70d4b9 1245
4e17e6 1246   // remove attachment files from temp dir
T 1247   if (is_array($_SESSION['compose']['attachments']))
1248     foreach ($_SESSION['compose']['attachments'] as $attachment)
15a9d1 1249       @unlink($attachment['path']);
4e17e6 1250   
T 1251   unset($_SESSION['compose']);
1252   }
f11541 1253
T 1254
1255 // register UI objects
1256 $OUTPUT->add_handlers(array(
1257   'mailboxlist' => 'rcmail_mailbox_list',
1258   'messages' => 'rcmail_message_list',
1259   'messagecountdisplay' => 'rcmail_messagecount_display',
1260   'quotadisplay' => 'rcmail_quota_display',
1261   'messageheaders' => 'rcmail_message_headers',
1262   'messagebody' => 'rcmail_message_body',
1263   'messagecontentframe' => 'rcmail_messagecontent_frame',
1264   'messagepartframe' => 'rcmail_message_part_frame',
1265   'messagepartcontrols' => 'rcmail_message_part_controls',
1266   'searchform' => 'rcmail_search_form'
1267 ));
1268
93be5b 1269 ?>