| | |
| | | | program/steps/mail/func.inc | |
| | | | | |
| | | | This file is part of the Roundcube Webmail client | |
| | | | Copyright (C) 2005-2012, The Roundcube Dev Team | |
| | | | Copyright (C) 2005-2013, The Roundcube Dev Team | |
| | | | | |
| | | | Licensed under the GNU General Public License version 3 or | |
| | | | any later version with exceptions for skins & plugins. | |
| | |
| | | | | |
| | | +-----------------------------------------------------------------------+ |
| | | | Author: Thomas Bruederli <roundcube@gmail.com> | |
| | | | Author: Aleksander Machniak <alec@alec.pl> | |
| | | +-----------------------------------------------------------------------+ |
| | | */ |
| | | |
| | | // setup some global vars used by mail steps |
| | | $SENT_MBOX = $RCMAIL->config->get('sent_mbox'); |
| | | $DRAFTS_MBOX = $RCMAIL->config->get('drafts_mbox'); |
| | | $SEARCH_MODS_DEFAULT = array( |
| | | '*' => array('subject'=>1, 'from'=>1), |
| | | $SENT_MBOX => array('subject'=>1, 'to'=>1), |
| | | $DRAFTS_MBOX => array('subject'=>1, 'to'=>1) |
| | | ); |
| | | |
| | | // always instantiate storage object (but not connect to server yet) |
| | | $RCMAIL->storage_init(); |
| | | |
| | | // set imap properties and session vars |
| | | if (strlen(trim($mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC, true)))) |
| | | if (strlen(trim($mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC, true)))) { |
| | | $RCMAIL->storage->set_folder(($_SESSION['mbox'] = $mbox)); |
| | | else if ($RCMAIL->storage) |
| | | } |
| | | else if ($RCMAIL->storage) { |
| | | $_SESSION['mbox'] = $RCMAIL->storage->get_folder(); |
| | | } |
| | | |
| | | if (!empty($_GET['_page'])) |
| | | if (!empty($_GET['_page'])) { |
| | | $RCMAIL->storage->set_page(($_SESSION['page'] = intval($_GET['_page']))); |
| | | } |
| | | |
| | | $a_threading = $RCMAIL->config->get('message_threading', array()); |
| | | $message_sort_col = $RCMAIL->config->get('message_sort_col'); |
| | | $message_sort_order = $RCMAIL->config->get('message_sort_col'); |
| | | |
| | | // set default sort col/order to session |
| | | if (!isset($_SESSION['sort_col'])) |
| | | $_SESSION['sort_col'] = !empty($CONFIG['message_sort_col']) ? $CONFIG['message_sort_col'] : ''; |
| | | if (!isset($_SESSION['sort_order'])) |
| | | $_SESSION['sort_order'] = strtoupper($CONFIG['message_sort_order']) == 'ASC' ? 'ASC' : 'DESC'; |
| | | if (!isset($_SESSION['sort_col'])) { |
| | | $_SESSION['sort_col'] = $message_sort_col ? $message_sort_col : ''; |
| | | } |
| | | if (!isset($_SESSION['sort_order'])) { |
| | | $_SESSION['sort_order'] = strtoupper($message_sort_order) == 'ASC' ? 'ASC' : 'DESC'; |
| | | } |
| | | |
| | | // set threads mode |
| | | $a_threading = $RCMAIL->config->get('message_threading', array()); |
| | | if (isset($_GET['_threads'])) { |
| | | if ($_GET['_threads']) |
| | | $a_threading[$_SESSION['mbox']] = true; |
| | | else |
| | | unset($a_threading[$_SESSION['mbox']]); |
| | | |
| | | $RCMAIL->user->save_prefs(array('message_threading' => $a_threading)); |
| | | } |
| | | $RCMAIL->storage->set_threading($a_threading[$_SESSION['mbox']]); |
| | |
| | | && $_SESSION['search_request'] == $_REQUEST['_search'] |
| | | ) { |
| | | $RCMAIL->storage->set_search_set($_SESSION['search']); |
| | | |
| | | $OUTPUT->set_env('search_request', $_REQUEST['_search']); |
| | | $OUTPUT->set_env('search_text', $_SESSION['last_text_search']); |
| | | } |
| | |
| | | if (empty($RCMAIL->action)) { |
| | | // initialize searching result if search_filter is used |
| | | if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL') { |
| | | $search_request = md5($mbox_name.$_SESSION['search_filter']); |
| | | |
| | | $RCMAIL->storage->search($mbox_name, $_SESSION['search_filter'], RCUBE_CHARSET, rcmail_sort_column()); |
| | | |
| | | $search_request = md5($mbox_name.$_SESSION['search_filter']); |
| | | $_SESSION['search'] = $RCMAIL->storage->get_search_set(); |
| | | $_SESSION['search_request'] = $search_request; |
| | | |
| | | $OUTPUT->set_env('search_request', $search_request); |
| | | } |
| | | |
| | | $search_mods = $RCMAIL->config->get('search_mods', $SEARCH_MODS_DEFAULT); |
| | | $OUTPUT->set_env('search_mods', $search_mods); |
| | | $OUTPUT->set_env('search_mods', rcmail_search_mods()); |
| | | } |
| | | |
| | | $threading = (bool) $RCMAIL->storage->get_threading(); |
| | |
| | | $OUTPUT->set_env('threads', $threading || $RCMAIL->storage->get_capability('THREAD')); |
| | | $OUTPUT->set_env('reply_all_mode', (int) $RCMAIL->config->get('reply_all_mode')); |
| | | $OUTPUT->set_env('preview_pane_mark_read', $RCMAIL->config->get('preview_pane_mark_read', 0)); |
| | | |
| | | if ($RCMAIL->storage->get_capability('QUOTA')) { |
| | | $OUTPUT->set_env('quota', true); |
| | | } |
| | | |
| | | foreach (array('delete_junk','flag_for_deletion','read_when_deleted','skip_deleted','display_next','message_extwin','compose_extwin','forward_attachment') as $prop) { |
| | | if ($CONFIG[$prop]) |
| | | $OUTPUT->set_env($prop, true); |
| | | // set special folders |
| | | foreach (array('drafts', 'trash', 'junk') as $mbox) { |
| | | if ($folder = $RCMAIL->config->get($mbox . '_mbox')) { |
| | | $OUTPUT->set_env($mbox . '_mailbox', $folder); |
| | | } |
| | | } |
| | | |
| | | if ($CONFIG['trash_mbox']) |
| | | $OUTPUT->set_env('trash_mailbox', $CONFIG['trash_mbox']); |
| | | if ($CONFIG['drafts_mbox']) |
| | | $OUTPUT->set_env('drafts_mailbox', $CONFIG['drafts_mbox']); |
| | | if ($CONFIG['junk_mbox']) |
| | | $OUTPUT->set_env('junk_mailbox', $CONFIG['junk_mbox']); |
| | | // set configuration |
| | | $RCMAIL->set_env_config(array('delete_junk', 'flag_for_deletion', 'read_when_deleted', |
| | | 'skip_deleted', 'display_next', 'message_extwin', 'compose_extwin', 'forward_attachment')); |
| | | |
| | | if (!empty($_SESSION['browser_caps'])) |
| | | if (!empty($_SESSION['browser_caps'])) { |
| | | $OUTPUT->set_env('browser_capabilities', $_SESSION['browser_caps']); |
| | | } |
| | | |
| | | if (!$OUTPUT->ajax_call) |
| | | if (!$OUTPUT->ajax_call) { |
| | | $OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash', |
| | | 'movingmessage', 'copyingmessage', 'deletingmessage', 'markingmessage', |
| | | 'copy', 'move', 'quota', 'replyall', 'replylist', 'importwait'); |
| | | } |
| | | |
| | | $pagetitle = $RCMAIL->localize_foldername($RCMAIL->storage->mod_folder($mbox_name), true); |
| | | $pagetitle = str_replace($delimiter, " \xC2\xBB ", $pagetitle); |
| | |
| | | // register UI objects |
| | | $OUTPUT->add_handlers(array( |
| | | 'mailboxlist' => array($RCMAIL, 'folder_list'), |
| | | 'quotadisplay' => array($RCMAIL, 'quota_display'), |
| | | 'messages' => 'rcmail_message_list', |
| | | 'messagecountdisplay' => 'rcmail_messagecount_display', |
| | | 'quotadisplay' => array($RCMAIL, 'quota_display'), |
| | | 'mailboxname' => 'rcmail_mailbox_name_display', |
| | | 'messageheaders' => 'rcmail_message_headers', |
| | | 'messagefullheaders' => 'rcmail_message_full_headers', |
| | |
| | | )); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns default search mods |
| | | */ |
| | | function rcmail_search_mods() |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | $mods = $RCMAIL->config->get('search_mods'); |
| | | |
| | | if (empty($mods)) { |
| | | $mods = array('*' => array('subject' => 1, 'from' => 1)); |
| | | |
| | | foreach (array('sent', 'drafts') as $mbox) { |
| | | if ($mbox = $RCMAIL->config->get($mbox . '_mbox')) { |
| | | $mods[$mbox] = array('subject' => 1, 'to' => 1); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return $mods; |
| | | } |
| | | |
| | | /** |
| | | * Returns 'to' if current folder is configured Sent or Drafts |
| | |
| | | */ |
| | | function rcmail_message_list($attrib) |
| | | { |
| | | global $CONFIG, $OUTPUT; |
| | | global $RCMAIL, $OUTPUT; |
| | | |
| | | // add some labels to client |
| | | $OUTPUT->add_label('from', 'to'); |
| | |
| | | |
| | | // define list of cols to be displayed based on parameter or config |
| | | if (empty($attrib['columns'])) { |
| | | $a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject'); |
| | | $OUTPUT->set_env('col_movable', !in_array('list_cols', (array)$CONFIG['dont_override'])); |
| | | $list_cols = $RCMAIL->config->get('list_cols'); |
| | | $a_show_cols = !empty($list_cols) && is_array($list_cols) ? $list_cols : array('subject'); |
| | | |
| | | $OUTPUT->set_env('col_movable', !in_array('list_cols', (array)$RCMAIL->config->get('dont_override'))); |
| | | } |
| | | else { |
| | | $a_show_cols = preg_split('/[\s,;]+/', str_replace(array("'", '"'), '', $attrib['columns'])); |
| | |
| | | |
| | | // save some variables for use in ajax list |
| | | $_SESSION['list_attrib'] = $attrib; |
| | | |
| | | // make sure 'threads' and 'subject' columns are present |
| | | if (!in_array('subject', $a_show_cols)) |
| | | array_unshift($a_show_cols, 'subject'); |
| | | if (!in_array('threads', $a_show_cols)) |
| | | array_unshift($a_show_cols, 'threads'); |
| | | |
| | | $_SESSION['skin_path'] = $CONFIG['skin_path']; |
| | | $_SESSION['skin_path'] = $RCMAIL->config->get('skin_path'); |
| | | |
| | | // set client env |
| | | $OUTPUT->add_gui_object('messagelist', $attrib['id']); |
| | | $OUTPUT->set_env('autoexpand_threads', intval($CONFIG['autoexpand_threads'])); |
| | | $OUTPUT->set_env('autoexpand_threads', intval($RCMAIL->config->get('autoexpand_threads'))); |
| | | $OUTPUT->set_env('sort_col', $_SESSION['sort_col']); |
| | | $OUTPUT->set_env('sort_order', $_SESSION['sort_order']); |
| | | $OUTPUT->set_env('messages', array()); |
| | |
| | | $OUTPUT->include_script('list.js'); |
| | | |
| | | $table = new html_table($attrib); |
| | | |
| | | if (!$attrib['noheader']) { |
| | | foreach (rcmail_message_list_head($attrib, $a_show_cols) as $cell) |
| | | $table->add_header(array('class' => $cell['className'], 'id' => $cell['id']), $cell['html']); |
| | |
| | | return $table->show(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * return javascript commands to add rows to the message list |
| | | */ |
| | | function rcmail_js_message_list($a_headers, $insert_top=FALSE, $a_show_cols=null) |
| | | { |
| | | global $CONFIG, $RCMAIL, $OUTPUT; |
| | | global $RCMAIL, $OUTPUT; |
| | | |
| | | if (empty($a_show_cols)) { |
| | | if (!empty($_SESSION['list_attrib']['columns'])) |
| | | $a_show_cols = $_SESSION['list_attrib']['columns']; |
| | | else |
| | | $a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject'); |
| | | else { |
| | | $list_cols = $RCMAIL->config->get('list_cols'); |
| | | $a_show_cols = !empty($list_cols) && is_array($list_cols) ? $list_cols : array('subject'); |
| | | } |
| | | } |
| | | else { |
| | | if (!is_array($a_show_cols)) |
| | | if (!is_array($a_show_cols)) { |
| | | $a_show_cols = preg_split('/[\s,;]+/', str_replace(array("'", '"'), '', $a_show_cols)); |
| | | } |
| | | $head_replace = true; |
| | | } |
| | | |
| | |
| | | |
| | | $OUTPUT->command('set_message_coltypes', $a_show_cols, $thead, $smart_col); |
| | | |
| | | if (empty($a_headers)) |
| | | if (empty($a_headers)) { |
| | | return; |
| | | } |
| | | |
| | | // remove 'threads', 'attachment', 'flag', 'status' columns, we don't need them here |
| | | foreach (array('threads', 'attachment', 'flag', 'status', 'priority') as $col) { |
| | | if (($key = array_search($col, $a_show_cols)) !== FALSE) |
| | | if (($key = array_search($col, $a_show_cols)) !== FALSE) { |
| | | unset($a_show_cols[$key]); |
| | | } |
| | | } |
| | | |
| | | // loop through message headers |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | /* |
| | | * Creates <THEAD> for message list table |
| | | */ |
| | |
| | | else |
| | | $list_menu = html::a(array('href' => '#', 'onclick' => $onclick), |
| | | html::img(array('src' => $skin_path . $attrib['optionsmenuicon'], |
| | | 'id' => 'listmenulink', 'title' => $RCMAIL->gettext('listoptions'))) |
| | | ); |
| | | 'id' => 'listmenulink', 'title' => $RCMAIL->gettext('listoptions')))); |
| | | } |
| | | else |
| | | else { |
| | | $list_menu = ''; |
| | | } |
| | | |
| | | $cells = array(); |
| | | |
| | |
| | | } |
| | | |
| | | // make sort links |
| | | if (in_array($col, $a_sort_cols)) |
| | | $col_name = html::a(array('href'=>"./#sort", 'onclick' => 'return '.rcmail_output::JS_OBJECT_NAME.".command('sort','".$col."',this)", 'title' => $RCMAIL->gettext('sortby')), $col_name); |
| | | else if ($col_name[0] != '<') |
| | | if (in_array($col, $a_sort_cols)) { |
| | | $col_name = html::a(array( |
| | | 'href' => "./#sort", |
| | | 'onclick' => 'return '.rcmail_output::JS_OBJECT_NAME.".command('sort','".$col."',this)", |
| | | 'title' => $RCMAIL->gettext('sortby') |
| | | ), $col_name); |
| | | } |
| | | else if ($col_name[0] != '<') { |
| | | $col_name = '<span class="' . $col .'">' . $col_name . '</span>'; |
| | | } |
| | | |
| | | $sort_class = $col == $sort_col && !$disabled_order ? " sorted$sort_order" : ''; |
| | | $class_name = $col.$sort_class; |
| | |
| | | |
| | | return $cells; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * return an HTML iframe for loading mail content |
| | |
| | | |
| | | $attrib['name'] = $attrib['id']; |
| | | |
| | | if ($RCMAIL->config->get('preview_pane')) |
| | | if ($RCMAIL->config->get('preview_pane')) { |
| | | $OUTPUT->set_env('contentframe', $attrib['id']); |
| | | } |
| | | |
| | | $OUTPUT->set_env('blankpage', $attrib['src'] ? $OUTPUT->abs_url($attrib['src']) : 'program/resources/blank.gif'); |
| | | |
| | | return $OUTPUT->frame($attrib, true); |
| | | } |
| | | |
| | | |
| | | function rcmail_messagecount_display($attrib) |
| | | { |
| | |
| | | return html::span($attrib, $content); |
| | | } |
| | | |
| | | |
| | | function rcmail_get_messagecount_text($count=NULL, $page=NULL) |
| | | function rcmail_get_messagecount_text($count = null, $page = null) |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | if ($page === NULL) { |
| | | if ($page === null) { |
| | | $page = $RCMAIL->storage->get_page(); |
| | | } |
| | | |
| | | $page_size = $RCMAIL->storage->get_pagesize(); |
| | | $start_msg = ($page-1) * $page_size + 1; |
| | | |
| | | if ($count!==NULL) |
| | | if ($count !== null) |
| | | $max = $count; |
| | | else if ($RCMAIL->action) |
| | | $max = $RCMAIL->storage->count(NULL, $RCMAIL->storage->get_threading() ? 'THREADS' : 'ALL'); |
| | |
| | | return rcube::Q($out); |
| | | } |
| | | |
| | | |
| | | function rcmail_mailbox_name_display($attrib) |
| | | { |
| | | global $RCMAIL; |
| | |
| | | return html::span($attrib, rcmail_get_mailbox_name_text()); |
| | | } |
| | | |
| | | |
| | | function rcmail_get_mailbox_name_text() |
| | | { |
| | | global $RCMAIL; |
| | | return $RCMAIL->localize_foldername($RCMAIL->storage->get_folder()); |
| | | } |
| | | |
| | | |
| | | function rcmail_send_unread_count($mbox_name, $force=false, $count=null, $mark='') |
| | | { |
| | |
| | | return $unseen; |
| | | } |
| | | |
| | | |
| | | function rcmail_set_unseen_count($mbox_name, $count) |
| | | { |
| | | // @TODO: this data is doubled (session and cache tables) if caching is enabled |
| | | |
| | | // Make sure we have an array here (#1487066) |
| | | if (!is_array($_SESSION['unseen_count'])) |
| | | if (!is_array($_SESSION['unseen_count'])) { |
| | | $_SESSION['unseen_count'] = array(); |
| | | } |
| | | |
| | | $_SESSION['unseen_count'][$mbox_name] = $count; |
| | | } |
| | | |
| | | |
| | | function rcmail_get_unseen_count($mbox_name) |
| | | { |
| | | if (is_array($_SESSION['unseen_count']) && array_key_exists($mbox_name, $_SESSION['unseen_count'])) |
| | | if (is_array($_SESSION['unseen_count']) && array_key_exists($mbox_name, $_SESSION['unseen_count'])) { |
| | | return $_SESSION['unseen_count'][$mbox_name]; |
| | | else |
| | | return null; |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * Sets message is_safe flag according to 'show_images' option value |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Cleans up the given message HTML Body (for displaying) |
| | |
| | | // initialize HTML washer |
| | | $washer = new rcube_washtml($wash_opts); |
| | | |
| | | if (!$p['skip_washer_form_callback']) |
| | | if (!$p['skip_washer_form_callback']) { |
| | | $washer->add_callback('form', 'rcmail_washtml_callback'); |
| | | } |
| | | |
| | | // allow CSS styles, will be sanitized by rcmail_washtml_callback() |
| | | if (!$p['skip_washer_style_callback']) |
| | | if (!$p['skip_washer_style_callback']) { |
| | | $washer->add_callback('style', 'rcmail_washtml_callback'); |
| | | } |
| | | |
| | | // Remove non-UTF8 characters (#1487813) |
| | | $html = rcube_charset::clean($html); |
| | |
| | | |
| | | return $html; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Convert the given message part to proper HTML |
| | |
| | | if ($data['type'] == 'enriched') { |
| | | $data['body'] = rcube_enriched::to_html($data['body']); |
| | | } |
| | | |
| | | $txt = new rcube_html2text($data['body'], false, true); |
| | | $body = $txt->get_text(); |
| | | $part->ctype_secondary = 'plain'; |
| | |
| | | |
| | | return $data['type'] == 'html' ? $data['body'] : html::tag('pre', array(), $data['body']); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Handle links and citation marks in plain text message |
| | |
| | | // colorize signature (up to <sig_max_lines> lines) |
| | | $len = strlen($body); |
| | | $sig_max_lines = $RCMAIL->config->get('sig_max_lines', 15); |
| | | |
| | | while (($sp = strrpos($body, "-- \n", $sp ? -$len+$sp-1 : 0)) !== false) { |
| | | if ($sp == 0 || $body[$sp-1] == "\n") { |
| | | // do not touch blocks with more that X lines |
| | | if (substr_count($body, "\n", $sp) < $sig_max_lines) |
| | | if (substr_count($body, "\n", $sp) < $sig_max_lines) { |
| | | $body = substr($body, 0, max(0, $sp)) |
| | | .'<span class="sig">'.substr($body, $sp).'</span>'; |
| | | } |
| | | |
| | | break; |
| | | } |
| | | } |
| | |
| | | |
| | | return $body; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Callback function for washtml cleaning class |
| | |
| | | return $out; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * return table with message headers |
| | | */ |
| | |
| | | else if (!is_array($attrib) && is_array($sa_attrib)) |
| | | $attrib = $sa_attrib; |
| | | |
| | | if (!isset($MESSAGE)) |
| | | return FALSE; |
| | | if (!isset($MESSAGE)) { |
| | | return false; |
| | | } |
| | | |
| | | // get associative array of headers object |
| | | if (!$headers) { |
| | |
| | | } |
| | | else if ($hkey == 'replyto') { |
| | | if ($headers['replyto'] != $headers['from']) { |
| | | $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title); |
| | | $header_value = rcmail_address_string($value, $attrib['max'], true, |
| | | $attrib['addicon'], $headers['charset'], $header_title); |
| | | $ishtml = true; |
| | | } |
| | | else |
| | |
| | | if ($headers['mail-replyto'] != $headers['reply-to'] |
| | | && $headers['reply-to'] != $headers['from'] |
| | | ) { |
| | | $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title); |
| | | $header_value = rcmail_address_string($value, $attrib['max'], true, |
| | | $attrib['addicon'], $headers['charset'], $header_title); |
| | | $ishtml = true; |
| | | } |
| | | else |
| | |
| | | } |
| | | else if ($hkey == 'sender') { |
| | | if ($headers['sender'] != $headers['from']) { |
| | | $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title); |
| | | $header_value = rcmail_address_string($value, $attrib['max'], true, |
| | | $attrib['addicon'], $headers['charset'], $header_title); |
| | | $ishtml = true; |
| | | } |
| | | else |
| | | continue; |
| | | } |
| | | else if ($hkey == 'mail-followup-to') { |
| | | $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title); |
| | | $header_value = rcmail_address_string($value, $attrib['max'], true, |
| | | $attrib['addicon'], $headers['charset'], $header_title); |
| | | $ishtml = true; |
| | | } |
| | | else if (in_array($hkey, array('from', 'to', 'cc', 'bcc'))) { |
| | | $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title); |
| | | $header_value = rcmail_address_string($value, $attrib['max'], true, |
| | | $attrib['addicon'], $headers['charset'], $header_title); |
| | | $ishtml = true; |
| | | } |
| | | else if ($hkey == 'subject' && empty($value)) |
| | |
| | | ); |
| | | } |
| | | |
| | | $plugin = $RCMAIL->plugins->exec_hook('message_headers_output', |
| | | array('output' => $output_headers, 'headers' => $headers_obj, 'exclude' => $exclude_headers)); |
| | | $plugin = $RCMAIL->plugins->exec_hook('message_headers_output', array( |
| | | 'output' => $output_headers, |
| | | 'headers' => $headers_obj, |
| | | 'exclude' => $exclude_headers |
| | | )); |
| | | |
| | | // single header value is requested |
| | | if (!empty($attrib['valueof'])) |
| | | if (!empty($attrib['valueof'])) { |
| | | return rcube::Q($plugin['output'][$attrib['valueof']]['value'], ($attrib['valueof'] == 'subject' ? 'strict' : 'show')); |
| | | } |
| | | |
| | | // compose html table |
| | | $table = new html_table(array('cols' => 2)); |
| | | |
| | | foreach ($plugin['output'] as $hkey => $row) { |
| | | $val = $row['html'] ? $row['value'] : rcube::Q($row['value'], ($hkey == 'subject' ? 'strict' : 'show')); |
| | | |
| | | $table->add(array('class' => 'header-title'), rcube::Q($row['title'])); |
| | | $table->add(array('class' => 'header '.$hkey), $row['html'] ? $row['value'] : rcube::Q($row['value'], ($hkey == 'subject' ? 'strict' : 'show'))); |
| | | $table->add(array('class' => 'header '.$hkey), $val); |
| | | } |
| | | |
| | | return $table->show($attrib); |
| | |
| | | '5' => 'lowest', |
| | | ); |
| | | |
| | | if ($value && $labels_map[$value]) |
| | | if ($value && $labels_map[$value]) { |
| | | return $RCMAIL->gettext($labels_map[$value]); |
| | | } |
| | | |
| | | return ''; |
| | | } |
| | |
| | | global $OUTPUT, $RCMAIL; |
| | | |
| | | $html = html::div(array('id' => "all-headers", 'class' => "all", 'style' => 'display:none'), html::div(array('id' => 'headers-source'), '')); |
| | | $html .= html::div(array('class' => "more-headers show-headers", 'onclick' => "return ".rcmail_output::JS_OBJECT_NAME.".command('show-headers','',this)", 'title' => $RCMAIL->gettext('togglefullheaders')), ''); |
| | | $html .= html::div(array( |
| | | 'class' => "more-headers show-headers", |
| | | 'onclick' => "return ".rcmail_output::JS_OBJECT_NAME.".command('show-headers','',this)", |
| | | 'title' => $RCMAIL->gettext('togglefullheaders') |
| | | ), ''); |
| | | |
| | | $OUTPUT->add_gui_object('all_headers_row', 'all-headers'); |
| | | $OUTPUT->add_gui_object('all_headers_box', 'headers-source'); |
| | | |
| | | return html::div($attrib, $html); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Handler for the 'messagebody' GUI object |
| | |
| | | */ |
| | | function rcmail_message_body($attrib) |
| | | { |
| | | global $CONFIG, $OUTPUT, $MESSAGE, $RCMAIL, $REMOTE_OBJECTS; |
| | | global $OUTPUT, $MESSAGE, $RCMAIL, $REMOTE_OBJECTS; |
| | | |
| | | if (!is_array($MESSAGE->parts) && empty($MESSAGE->body)) |
| | | if (!is_array($MESSAGE->parts) && empty($MESSAGE->body)) { |
| | | return ''; |
| | | } |
| | | |
| | | if (!$attrib['id']) |
| | | $attrib['id'] = 'rcmailMsgBody'; |
| | |
| | | $out = ''; |
| | | |
| | | $header_attrib = array(); |
| | | foreach ($attrib as $attr => $value) |
| | | if (preg_match('/^headertable([a-z]+)$/i', $attr, $regs)) |
| | | foreach ($attrib as $attr => $value) { |
| | | if (preg_match('/^headertable([a-z]+)$/i', $attr, $regs)) { |
| | | $header_attrib[$regs[1]] = $value; |
| | | } |
| | | } |
| | | |
| | | if (!empty($MESSAGE->parts)) { |
| | | foreach ($MESSAGE->parts as $part) { |
| | |
| | | else if (!$part->size) { |
| | | continue; |
| | | } |
| | | |
| | | // Check if we have enough memory to handle the message in it |
| | | // #1487424: we need up to 10x more memory than the body |
| | | else if (!rcube_utils::mem_check($part->size * 10)) { |
| | |
| | | continue; |
| | | } |
| | | |
| | | if (empty($part->ctype_parameters) || empty($part->ctype_parameters['charset'])) |
| | | if (empty($part->ctype_parameters) || empty($part->ctype_parameters['charset'])) { |
| | | $part->ctype_parameters['charset'] = $MESSAGE->headers->charset; |
| | | } |
| | | |
| | | // fetch part if not available |
| | | if (!isset($part->body)) |
| | | if (!isset($part->body)) { |
| | | $part->body = $MESSAGE->get_part_content($part->mime_id); |
| | | } |
| | | |
| | | // extract headers from message/rfc822 parts |
| | | if ($part->mimetype == 'message/rfc822') { |
| | |
| | | rcmail_message_error($MESSAGE->uid); |
| | | } |
| | | |
| | | $plugin = $RCMAIL->plugins->exec_hook('message_body_prefix', array( |
| | | 'part' => $part, 'prefix' => '')); |
| | | $plugin = $RCMAIL->plugins->exec_hook('message_body_prefix', |
| | | array('part' => $part, 'prefix' => '')); |
| | | |
| | | $body = rcmail_print_body($part, array('safe' => $safe_mode, 'plain' => !$CONFIG['prefer_html'])); |
| | | $body = rcmail_print_body($part, array('safe' => $safe_mode, 'plain' => !$RCMAIL->config->get('prefer_html'))); |
| | | |
| | | if ($part->ctype_secondary == 'html') { |
| | | $body = rcmail_html4inline($body, $attrib['id'], 'rcmBody', $attrs, $safe_mode); |
| | |
| | | .'&_mbox='. urlencode($RCMAIL->storage->get_folder()), $RCMAIL->gettext('download'))); |
| | | } |
| | | else { |
| | | $plugin = $RCMAIL->plugins->exec_hook('message_body_prefix', array( |
| | | 'part' => $MESSAGE, 'prefix' => '')); |
| | | $plugin = $RCMAIL->plugins->exec_hook('message_body_prefix', |
| | | array('part' => $MESSAGE, 'prefix' => '')); |
| | | |
| | | $out .= html::div('message-part', $plugin['prefix'] . html::tag('pre', array(), |
| | | rcmail_plain_body(rcube::Q($MESSAGE->body, 'strict', false)))); |
| | |
| | | else { |
| | | $out .= html::tag('fieldset', 'image-attachment', |
| | | html::tag('legend', 'image-filename', rcube::Q($attach_prop->filename)) . |
| | | html::p(array('align' => "center"), |
| | | html::p(array('align' => 'center'), |
| | | html::img(array( |
| | | 'src' => $MESSAGE->get_part_url($attach_prop->mime_id, 'image'), |
| | | 'title' => $attach_prop->filename, |
| | |
| | | } |
| | | |
| | | // tell client that there are blocked remote objects |
| | | if ($REMOTE_OBJECTS && !$safe_mode) |
| | | if ($REMOTE_OBJECTS && !$safe_mode) { |
| | | $OUTPUT->set_env('blockedobjects', true); |
| | | } |
| | | |
| | | return html::div($attrib, $out); |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * modify a HTML message that it can be displayed inside a HTML page |
| | | */ |
| | |
| | | $cont_id = $container_id.($body_id ? ' div.'.$body_id : ''); |
| | | |
| | | // find STYLE tags |
| | | while (($pos = stripos($body, '<style', $last_style_pos)) && ($pos2 = stripos($body, '</style>', $pos))) |
| | | { |
| | | while (($pos = stripos($body, '<style', $last_style_pos)) && ($pos2 = stripos($body, '</style>', $pos))) { |
| | | $pos = strpos($body, '>', $pos) + 1; |
| | | $len = $pos2 - $pos; |
| | | |
| | |
| | | $regexp = '/<div class="' . preg_quote($body_id, '/') . '"([^>]*)/'; |
| | | if (preg_match($regexp, $body, $m)) { |
| | | $attrs = $m[0]; |
| | | |
| | | // Get bgcolor, we'll set it as background-color of the message container |
| | | if ($m[1] && preg_match('/bgcolor=["\']*([a-z0-9#]+)["\']*/i', $attrs, $mb)) { |
| | | $attributes['background-color'] = $mb[1]; |
| | | $attrs = preg_replace('/bgcolor=["\']*[a-z0-9#]+["\']*/i', '', $attrs); |
| | | } |
| | | |
| | | // Get background, we'll set it as background-image of the message container |
| | | if ($m[1] && preg_match('/background=["\']*([^"\'>\s]+)["\']*/', $attrs, $mb)) { |
| | | $attributes['background-image'] = 'url('.$mb[1].')'; |
| | | $attrs = preg_replace('/background=["\']*([^"\'>\s]+)["\']*/', '', $attrs); |
| | | } |
| | | |
| | | if (!empty($attributes)) { |
| | | $body = preg_replace($regexp, rtrim($attrs), $body, 1); |
| | | } |
| | |
| | | // get body style |
| | | if (preg_match('/#'.preg_quote($cont_id, '/').'\s+\{([^}]+)}/i', $body, $m)) { |
| | | // get background related style |
| | | if (preg_match_all('/(background-position|background-repeat)\s*:\s*([^;]+);/i', $m[1], $ma, PREG_SET_ORDER)) { |
| | | foreach ($ma as $style) |
| | | $regexp = '/(background-position|background-repeat)\s*:\s*([^;]+);/i'; |
| | | if (preg_match_all($regexp, $m[1], $ma, PREG_SET_ORDER)) { |
| | | foreach ($ma as $style) { |
| | | $attributes[$style[1]] = $style[2]; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | return $body; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * parse link (a, link, area) attributes and set correct target |
| | |
| | | return "<$tag" . html::attrib_string($attrib, $allow) . $end; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * decode address string and re-format it as HTML links |
| | | */ |
| | | function rcmail_address_string($input, $max=null, $linked=false, $addicon=null, $default_charset=null, $title=null) |
| | | { |
| | | global $RCMAIL, $PRINT_MODE, $CONFIG; |
| | | global $RCMAIL, $PRINT_MODE; |
| | | |
| | | $a_parts = rcube_mime::decode_address_list($input, null, true, $default_charset); |
| | | |
| | | if (!sizeof($a_parts)) |
| | | if (!sizeof($a_parts)) { |
| | | return $input; |
| | | } |
| | | |
| | | $c = count($a_parts); |
| | | $j = 0; |
| | |
| | | |
| | | foreach ($a_parts as $part) { |
| | | $j++; |
| | | |
| | | $name = $part['name']; |
| | | $mailto = $part['mailto']; |
| | | $string = $part['string']; |
| | |
| | | if ($linked) { |
| | | $attrs = array( |
| | | 'href' => 'mailto:' . $mailto, |
| | | 'onclick' => sprintf("return %s.command('compose','%s',this)", rcmail_output::JS_OBJECT_NAME, rcube::JQ(format_email_recipient($mailto, $name))), |
| | | 'class' => "rcmContactAddress", |
| | | 'class' => 'rcmContactAddress', |
| | | 'onclick' => sprintf("return %s.command('compose','%s',this)", |
| | | rcmail_output::JS_OBJECT_NAME, rcube::JQ(format_email_recipient($mailto, $name))), |
| | | ); |
| | | |
| | | if ($show_email && $name && $mailto) { |
| | |
| | | if ($addicon && $_SESSION['writeable_abook']) { |
| | | $address .= html::a(array( |
| | | 'href' => "#add", |
| | | 'onclick' => sprintf("return %s.command('add-contact','%s',this)", rcmail_output::JS_OBJECT_NAME, rcube::JQ($string)), |
| | | 'title' => $RCMAIL->gettext('addtoaddressbook'), |
| | | 'class' => 'rcmaddcontact', |
| | | 'onclick' => sprintf("return %s.command('add-contact','%s',this)", |
| | | rcmail_output::JS_OBJECT_NAME, rcube::JQ($string)), |
| | | ), |
| | | html::img(array( |
| | | 'src' => $CONFIG['skin_path'] . $addicon, |
| | | 'src' => $RCMAIL->config->get('skin_path') . $addicon, |
| | | 'alt' => "Add contact", |
| | | ))); |
| | | } |
| | |
| | | 'href' => '#more', |
| | | 'class' => 'morelink', |
| | | 'onclick' => '$(this).hide().next().show()', |
| | | ), rcube::Q($RCMAIL->gettext(array('name' => 'andnmore', 'vars' => array('nr' => $moreadrs))))) . |
| | | html::span(array('style' => 'display:none'), join(', ', $allvalues)); |
| | | ), |
| | | rcube::Q($RCMAIL->gettext(array('name' => 'andnmore', 'vars' => array('nr' => $moreadrs))))) |
| | | . html::span(array('style' => 'display:none'), join(', ', $allvalues)); |
| | | } |
| | | else { |
| | | $out .= ' ' . html::a(array( |
| | |
| | | |
| | | return $out; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Wrap text to a given number of characters per line |
| | |
| | | |
| | | foreach ($lines as $line) { |
| | | // don't wrap already quoted lines |
| | | if ($line[0] == '>') |
| | | if ($line[0] == '>') { |
| | | $line = '>' . rtrim($line); |
| | | } |
| | | else if (mb_strlen($line) > $max) { |
| | | $newline = ''; |
| | | |
| | | foreach (explode("\n", rcube_mime::wordwrap($line, $length - 2)) as $l) { |
| | | if (strlen($l)) |
| | | $newline .= '> ' . $l . "\n"; |
| | | else |
| | | $newline .= ">\n"; |
| | | } |
| | | |
| | | $line = rtrim($newline); |
| | | } |
| | | else |
| | | else { |
| | | $line = '> ' . $line; |
| | | } |
| | | |
| | | // Append the line |
| | | $out .= $line . "\n"; |
| | |
| | | return rtrim($out, "\n"); |
| | | } |
| | | |
| | | |
| | | function rcmail_draftinfo_encode($p) |
| | | { |
| | | $parts = array(); |
| | | foreach ($p as $key => $val) |
| | | foreach ($p as $key => $val) { |
| | | $parts[] = $key . '=' . ($key == 'folder' ? base64_encode($val) : $val); |
| | | } |
| | | |
| | | return join('; ', $parts); |
| | | } |
| | | |
| | | |
| | | function rcmail_draftinfo_decode($str) |
| | | { |
| | | $info = array(); |
| | | |
| | | foreach (preg_split('/;\s+/', $str) as $part) { |
| | | list($key, $val) = explode('=', $part, 2); |
| | | if ($key == 'folder') |
| | | if ($key == 'folder') { |
| | | $val = base64_decode($val); |
| | | } |
| | | |
| | | $info[$key] = $val; |
| | | } |
| | | |
| | | return $info; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * clear message composing settings |
| | | */ |
| | | function rcmail_compose_cleanup($id) |
| | | { |
| | | if (!isset($_SESSION['compose_data_'.$id])) |
| | | if (!isset($_SESSION['compose_data_'.$id])) { |
| | | return; |
| | | } |
| | | |
| | | $rcmail = rcmail::get_instance(); |
| | | $rcmail->plugins->exec_hook('attachments_cleanup', array('group' => $id)); |
| | | $rcmail->session->remove('compose_data_'.$id); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Send the MDN response |
| | |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | if (!is_object($message) || !is_a($message, 'rcube_message')) |
| | | if (!is_object($message) || !is_a($message, 'rcube_message')) { |
| | | $message = new rcube_message($message); |
| | | } |
| | | |
| | | if ($message->headers->mdn_to && empty($message->headers->flags['MDNSENT']) && |
| | | ($RCMAIL->storage->check_permflag('MDNSENT') || $RCMAIL->storage->check_permflag('*'))) |
| | | { |
| | | ($RCMAIL->storage->check_permflag('MDNSENT') || $RCMAIL->storage->check_permflag('*')) |
| | | ) { |
| | | $identity = rcmail_identity_select($message); |
| | | $sender = format_email_recipient($identity['email'], $identity['name']); |
| | | $recipient = array_shift(rcube_mime::decode_address_list( |
| | |
| | | 'References' => trim($message->headers->references . ' ' . $message->headers->messageID), |
| | | ); |
| | | |
| | | $report = "Final-Recipient: rfc822; {$identity['email']}\r\n" . |
| | | "Original-Message-ID: {$message->headers->messageID}\r\n" . |
| | | "Disposition: manual-action/MDN-sent-manually; displayed\r\n"; |
| | | $report = "Final-Recipient: rfc822; {$identity['email']}\r\n" |
| | | . "Original-Message-ID: {$message->headers->messageID}\r\n" |
| | | . "Disposition: manual-action/MDN-sent-manually; displayed\r\n"; |
| | | |
| | | if ($message->headers->to) { |
| | | $report .= "Original-Recipient: {$message->headers->to}\r\n"; |
| | |
| | | $compose->setTXTBody(rcube_mime::wordwrap($body, 75, "\r\n")); |
| | | $compose->addAttachment($report, 'message/disposition-notification', 'MDNPart2.txt', false, '7bit', 'inline'); |
| | | |
| | | if ($RCMAIL->config->get('mdn_use_from')) |
| | | if ($RCMAIL->config->get('mdn_use_from')) { |
| | | $options['mdn_use_from'] = true; |
| | | } |
| | | |
| | | $sent = $RCMAIL->deliver_message($compose, $identity['email'], $mailto, $smtp_error, $body_file, $options); |
| | | |
| | |
| | | { |
| | | // Some versions of Outlook create garbage Content-Type: |
| | | // application/pdf.A520491B_3BF7_494D_8855_7FAC2C6C0608 |
| | | if (preg_match('/^application\/pdf.+/', $name)) |
| | | if (preg_match('/^application\/pdf.+/', $name)) { |
| | | $name = 'application/pdf'; |
| | | } |
| | | // treat image/pjpeg (image/pjpg, image/jpg) as image/jpeg (#1489097) |
| | | else if (preg_match('/^image\/p?jpe?g$/', $name)) |
| | | else if (preg_match('/^image\/p?jpe?g$/', $name)) { |
| | | $name = 'image/jpeg'; |
| | | } |
| | | |
| | | return $name; |
| | | } |
| | |
| | | |
| | | function rcmail_search_filter($attrib) |
| | | { |
| | | global $RCMAIL, $OUTPUT, $CONFIG; |
| | | global $RCMAIL; |
| | | |
| | | if (!strlen($attrib['id'])) |
| | | $attrib['id'] = 'rcmlistfilter'; |
| | |
| | | $select_filter->add($RCMAIL->gettext('unread'), 'UNSEEN'); |
| | | $select_filter->add($RCMAIL->gettext('flagged'), 'FLAGGED'); |
| | | $select_filter->add($RCMAIL->gettext('unanswered'), 'UNANSWERED'); |
| | | if (!$CONFIG['skip_deleted']) { |
| | | if (!$RCMAIL->config->get('skip_deleted')) { |
| | | $select_filter->add($RCMAIL->gettext('deleted'), 'DELETED'); |
| | | $select_filter->add($RCMAIL->gettext('undeleted'), 'UNDELETED'); |
| | | } |
| | |
| | | |
| | | $out = $select_filter->show($_SESSION['search_filter']); |
| | | |
| | | $OUTPUT->add_gui_object('search_filter', $attrib['id']); |
| | | $RCMAIL->output->add_gui_object('search_filter', $attrib['id']); |
| | | |
| | | return $out; |
| | | } |
| | |
| | | // Set env variables for messageerror.html template |
| | | if ($RCMAIL->action == 'show') { |
| | | $mbox_name = $RCMAIL->storage->get_folder(); |
| | | |
| | | $RCMAIL->output->set_env('mailbox', $mbox_name); |
| | | $RCMAIL->output->set_env('uid', null); |
| | | } |
| | | |
| | | // display error message |
| | | $RCMAIL->output->show_message('messageopenerror', 'error'); |
| | | // ... display message error page |
| | |
| | | |
| | | function rcmail_message_import_form($attrib = array()) |
| | | { |
| | | global $OUTPUT, $RCMAIL; |
| | | global $RCMAIL; |
| | | |
| | | // set defaults |
| | | $attrib += array('id' => 'rcmImportform', 'buttons' => 'yes'); |
| | |
| | | 'accept' => ".eml, .mbox, message/rfc822, text/*", |
| | | )); |
| | | |
| | | $out = html::div($attrib, |
| | | $OUTPUT->form_tag(array('id' => $attrib['id'].'Frm', 'method' => 'post', 'enctype' => 'multipart/form-data'), |
| | | html::tag('input', array('type' => 'hidden', 'name' => '_unlock', 'value' => '')) . |
| | | html::div(null, $fileinput->show()) . |
| | | html::div('hint', $RCMAIL->gettext(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize)))) . |
| | | (rcube_utils::get_boolean($attrib['buttons']) ? html::div('buttons', |
| | | $button->show($RCMAIL->gettext('close'), array('class' => 'button', 'onclick' => "$('#$attrib[id]').hide()")) . ' ' . |
| | | $button->show($RCMAIL->gettext('upload'), array('class' => 'button mainaction', 'onclick' => rcmail_output::JS_OBJECT_NAME . ".command('import-messages', this.form)")) |
| | | ) : '') |
| | | ) |
| | | ); |
| | | $content = html::tag('input', array('type' => 'hidden', 'name' => '_unlock', 'value' => '')) |
| | | . html::div(null, $fileinput->show()) |
| | | . html::div('hint', $RCMAIL->gettext(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize)))); |
| | | |
| | | $OUTPUT->add_gui_object('importform', $attrib['id'].'Frm'); |
| | | return $out; |
| | | if (rcube_utils::get_boolean($attrib['buttons'])) { |
| | | $content .= html::div('buttons', |
| | | $button->show($RCMAIL->gettext('close'), array('class' => 'button', 'onclick' => "$('#$attrib[id]').hide()")) |
| | | . ' ' . |
| | | $button->show($RCMAIL->gettext('upload'), array( |
| | | 'class' => 'button mainaction', |
| | | 'onclick' => rcmail_output::JS_OBJECT_NAME . ".command('import-messages', this.form)" |
| | | ))); |
| | | } |
| | | |
| | | $out = $RCMAIL->output->form_tag(array( |
| | | 'id' => $attrib['id'].'Frm', |
| | | 'method' => 'post', |
| | | 'enctype' => 'multipart/form-data' |
| | | ), |
| | | $content); |
| | | |
| | | $RCMAIL->output->add_gui_object('importform', $attrib['id'].'Frm'); |
| | | |
| | | return html::div($attrib, $out); |
| | | } |