| | |
| | | if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL') { |
| | | $search_request = md5($mbox_name.$_SESSION['search_filter']); |
| | | |
| | | $IMAP->search($mbox_name, $_SESSION['search_filter'], RCMAIL_CHARSET, $_SESSION['sort_col']); |
| | | $IMAP->search($mbox_name, $_SESSION['search_filter'], RCMAIL_CHARSET, rcmail_sort_column()); |
| | | $_SESSION['search'] = $IMAP->get_search_set(); |
| | | $_SESSION['search_request'] = $search_request; |
| | | $OUTPUT->set_env('search_request', $search_request); |
| | |
| | | $OUTPUT->set_pagetitle(rcmail_localize_foldername($IMAP->mod_mailbox($mbox_name))); |
| | | } |
| | | |
| | | /** |
| | | * Returns 'to' if current folder is configured Sent or Drafts |
| | | * or their subfolders, otherwise returns 'from'. |
| | | * |
| | | * @return string Column name |
| | | */ |
| | | function rcmail_message_list_smart_column_name() |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | $delim = $RCMAIL->imap->get_hierarchy_delimiter(); |
| | | $mbox = $RCMAIL->imap->get_mailbox_name(); |
| | | $sent_mbox = $RCMAIL->config->get('sent_mbox'); |
| | | $drafts_mbox = $RCMAIL->config->get('drafts_mbox'); |
| | | |
| | | if (strpos($mbox.$delim, $sent_mbox.$delim) === 0 || strpos($mbox.$delim, $drafts_mbox.$delim) === 0) { |
| | | return 'to'; |
| | | } |
| | | |
| | | return 'from'; |
| | | } |
| | | |
| | | /** |
| | | * Returns configured messages list sorting column name |
| | | * The name is context-sensitive, which means if sorting is set to 'fromto' |
| | | * it will return 'from' or 'to' according to current folder type. |
| | | * |
| | | * @return string Column name |
| | | */ |
| | | function rcmail_sort_column() |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | if (isset($_SESSION['sort_col'])) { |
| | | $column = $_SESSION['sort_col']; |
| | | } |
| | | else { |
| | | $column = $RCMAIL->config->get('message_sort_col'); |
| | | } |
| | | |
| | | // get name of smart From/To column in folder context |
| | | if ($column == 'fromto') { |
| | | $column = rcmail_message_list_smart_column_name(); |
| | | } |
| | | |
| | | return $column; |
| | | } |
| | | |
| | | /** |
| | | * Returns configured message list sorting order |
| | | * |
| | | * @return string Sorting order (ASC|DESC) |
| | | */ |
| | | function rcmail_sort_order() |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | if (isset($_SESSION['sort_order'])) { |
| | | return $_SESSION['sort_order']; |
| | | } |
| | | |
| | | return $RCMAIL->config->get('message_sort_order'); |
| | | } |
| | | |
| | | /** |
| | | * return the message list as HTML table |
| | | */ |
| | | function rcmail_message_list($attrib) |
| | | { |
| | | global $IMAP, $CONFIG, $OUTPUT; |
| | | global $CONFIG, $OUTPUT; |
| | | |
| | | // add some labels to client |
| | | $OUTPUT->add_label('from', 'to'); |
| | |
| | | |
| | | // save some variables for use in ajax list |
| | | $_SESSION['list_attrib'] = $attrib; |
| | | |
| | | $mbox = $IMAP->get_mailbox_name(); |
| | | $delim = $IMAP->get_hierarchy_delimiter(); |
| | | |
| | | // show 'to' instead of 'from' in sent/draft messages |
| | | if ((strpos($mbox.$delim, $CONFIG['sent_mbox'].$delim)===0 || strpos($mbox.$delim, $CONFIG['drafts_mbox'].$delim)===0) |
| | | && (($f = array_search('from', $a_show_cols)) !== false) && array_search('to', $a_show_cols) === false) |
| | | $a_show_cols[$f] = 'to'; |
| | | |
| | | // make sure 'threads' and 'subject' columns are present |
| | | if (!in_array('subject', $a_show_cols)) |
| | |
| | | } |
| | | |
| | | $mbox = $IMAP->get_mailbox_name(); |
| | | $delim = $IMAP->get_hierarchy_delimiter(); |
| | | |
| | | // make sure 'threads' and 'subject' columns are present |
| | | if (!in_array('subject', $a_show_cols)) |
| | |
| | | array_unshift($a_show_cols, 'threads'); |
| | | |
| | | $_SESSION['list_attrib']['columns'] = $a_show_cols; |
| | | |
| | | // show 'to' instead of 'from' in sent/draft messages |
| | | if ((strpos($mbox.$delim, $CONFIG['sent_mbox'].$delim)===0 || strpos($mbox.$delim, $CONFIG['drafts_mbox'].$delim)===0) |
| | | && (($f = array_search('from', $a_show_cols)) !== false) && array_search('to', $a_show_cols) === false) |
| | | $a_show_cols[$f] = 'to'; |
| | | |
| | | // Make sure there are no duplicated columns (#1486999) |
| | | $a_show_cols = array_unique($a_show_cols); |
| | |
| | | |
| | | $thead = $head_replace ? rcmail_message_list_head($_SESSION['list_attrib'], $a_show_cols) : NULL; |
| | | |
| | | $OUTPUT->command('set_message_coltypes', $a_show_cols, $thead); |
| | | // get name of smart From/To column in folder context |
| | | if (($f = array_search('fromto', $a_show_cols)) !== false) { |
| | | $smart_col = rcmail_message_list_smart_column_name(); |
| | | } |
| | | |
| | | $OUTPUT->command('set_message_coltypes', $a_show_cols, $thead, $smart_col); |
| | | |
| | | if (empty($a_headers)) |
| | | return; |
| | | |
| | | // remove 'threads', 'attachment', 'flag', 'status' columns, we don't need them here |
| | | foreach (array('threads', 'attachment', 'flag', 'status') as $col) { |
| | | foreach (array('threads', 'attachment', 'flag', 'status', 'priority') as $col) { |
| | | if (($key = array_search($col, $a_show_cols)) !== FALSE) |
| | | unset($a_show_cols[$key]); |
| | | } |
| | |
| | | |
| | | // format each col; similar as in rcmail_message_list() |
| | | foreach ($a_show_cols as $col) { |
| | | if (in_array($col, array('from', 'to', 'cc', 'replyto'))) |
| | | $cont = Q(rcmail_address_string($header->$col, 3), 'show'); |
| | | $col_name = $col == 'fromto' ? $smart_col : $col; |
| | | |
| | | if (in_array($col_name, array('from', 'to', 'cc', 'replyto'))) |
| | | $cont = Q(rcmail_address_string($header->$col_name, 3), 'show'); |
| | | else if ($col=='subject') { |
| | | $cont = trim($IMAP->decode_header($header->$col)); |
| | | if (!$cont) $cont = rcube_label('nosubject'); |
| | | $cont = Q($cont); |
| | | } |
| | | else if ($col=='size') |
| | | else if ($col == 'size') |
| | | $cont = show_bytes($header->$col); |
| | | else if ($col=='date') |
| | | else if ($col == 'date') |
| | | $cont = format_date($header->date); |
| | | else |
| | | $cont = Q($header->$col); |
| | |
| | | $a_msg_cols[$col] = $cont; |
| | | } |
| | | |
| | | $a_msg_flags = array_change_key_case(array_map('intval', (array) $header->flags)); |
| | | if ($header->depth) |
| | | $a_msg_flags['depth'] = $header->depth; |
| | | else if ($header->has_children) |
| | |
| | | $a_msg_flags['has_children'] = $header->has_children; |
| | | if ($header->unread_children) |
| | | $a_msg_flags['unread_children'] = $header->unread_children; |
| | | if ($header->deleted) |
| | | $a_msg_flags['deleted'] = 1; |
| | | if (!$header->seen) |
| | | $a_msg_flags['unread'] = 1; |
| | | if ($header->answered) |
| | | $a_msg_flags['replied'] = 1; |
| | | if ($header->forwarded) |
| | | $a_msg_flags['forwarded'] = 1; |
| | | if ($header->flagged) |
| | | $a_msg_flags['flagged'] = 1; |
| | | if ($header->others['list-post']) |
| | | $a_msg_flags['ml'] = 1; |
| | | if ($header->priority) |
| | | $a_msg_flags['prio'] = (int) $header->priority; |
| | | |
| | | $a_msg_flags['ctype'] = Q($header->ctype); |
| | | $a_msg_flags['mbox'] = $mbox; |
| | | |
| | | // merge with plugin result |
| | | // merge with plugin result (Deprecated, use $header->flags) |
| | | if (!empty($header->list_flags) && is_array($header->list_flags)) |
| | | $a_msg_flags = array_merge($a_msg_flags, $header->list_flags); |
| | | if (!empty($header->list_cols) && is_array($header->list_cols)) |
| | |
| | | } |
| | | |
| | | if ($IMAP->threading) { |
| | | $OUTPUT->command('init_threads', (array) $roots); |
| | | $OUTPUT->command('init_threads', (array) $roots, $mbox); |
| | | } |
| | | } |
| | | |
| | |
| | | */ |
| | | function rcmail_message_list_head($attrib, $a_show_cols) |
| | | { |
| | | global $CONFIG; |
| | | |
| | | $skin_path = $_SESSION['skin_path']; |
| | | $image_tag = html::img(array('src' => "%s%s", 'alt' => "%s")); |
| | | |
| | |
| | | $sort_order = $_SESSION['sort_order']; |
| | | |
| | | // define sortable columns |
| | | $a_sort_cols = array('subject', 'date', 'from', 'to', 'size', 'cc'); |
| | | $a_sort_cols = array('subject', 'date', 'from', 'to', 'fromto', 'size', 'cc'); |
| | | |
| | | if (!empty($attrib['optionsmenuicon'])) { |
| | | $onclick = 'return ' . JS_OBJECT_NAME . ".command('menu-open', 'messagelistmenu')"; |
| | |
| | | |
| | | $cells = array(); |
| | | |
| | | // get name of smart From/To column in folder context |
| | | if (($f = array_search('fromto', $a_show_cols)) !== false) { |
| | | $smart_col = rcmail_message_list_smart_column_name(); |
| | | } |
| | | |
| | | foreach ($a_show_cols as $col) { |
| | | // get column name |
| | | switch ($col) { |
| | |
| | | $col_name = '<span class="flagged"> </span>'; |
| | | break; |
| | | case 'attachment': |
| | | case 'priority': |
| | | case 'status': |
| | | $col_name = '<span class="' . $col .'"> </span>'; |
| | | break; |
| | | case 'threads': |
| | | $col_name = $list_menu; |
| | | break; |
| | | case 'fromto': |
| | | $col_name = Q(rcube_label($smart_col)); |
| | | break; |
| | | default: |
| | | $col_name = Q(rcube_label($col)); |
| | |
| | | * @param array CID map replaces (inline images) |
| | | * @return string Clean HTML |
| | | */ |
| | | function rcmail_wash_html($html, $p = array(), $cid_replaces) |
| | | function rcmail_wash_html($html, $p, $cid_replaces) |
| | | { |
| | | global $REMOTE_OBJECTS; |
| | | |
| | |
| | | // special replacements (not properly handled by washtml class) |
| | | $html_search = array( |
| | | '/(<\/nobr>)(\s+)(<nobr>)/i', // space(s) between <NOBR> |
| | | '/<title[^>]*>.*<\/title>/i', // PHP bug #32547 workaround: remove title tag |
| | | '/<title[^>]*>[^<]*<\/title>/i', // PHP bug #32547 workaround: remove title tag |
| | | '/^(\0\0\xFE\xFF|\xFF\xFE\0\0|\xFE\xFF|\xFF\xFE|\xEF\xBB\xBF)/', // byte-order mark (only outlook?) |
| | | '/<html\s[^>]+>/i', // washtml/DOMDocument cannot handle xml namespaces |
| | | ); |
| | |
| | | $html = preg_replace_callback('/(<[\/]*)([^\s>]+)/', 'rcmail_html_tag_callback', $html); |
| | | |
| | | // charset was converted to UTF-8 in rcube_imap::get_message_part(), |
| | | // -> change charset specification in HTML accordingly |
| | | $charset_pattern = '(<meta\s+[^>]*content=)[\'"]?(\w+\/\w+;\s*charset=)([a-z0-9-_]+[\'"]?)'; |
| | | if (preg_match("/$charset_pattern/Ui", $html)) { |
| | | $html = preg_replace("/$charset_pattern/i", '\\1"\\2'.RCMAIL_CHARSET.'"', $html); |
| | | } |
| | | else { |
| | | // add meta content-type to malformed messages, washtml cannot work without that |
| | | if (!preg_match('/<head[^>]*>(.*)<\/head>/Uims', $html)) |
| | | $html = '<head></head>'. $html; |
| | | $html = substr_replace($html, '<meta http-equiv="Content-Type" content="text/html; charset='.RCMAIL_CHARSET.'" />', intval(stripos($html, '<head>')+6), 0); |
| | | // change/add charset specification in HTML accordingly, |
| | | // washtml cannot work without that |
| | | $meta = '<meta http-equiv="Content-Type" content="text/html; charset='.RCMAIL_CHARSET.'" />'; |
| | | |
| | | // remove old meta tag and add the new one, making sure |
| | | // that it is placed in the head (#1488093) |
| | | $html = preg_replace('/<meta[^>]+charset=[a-z0-9-_]+[^>]*>/Ui', '', $html); |
| | | $html = preg_replace('/(<head[^>]*>)/Ui', '\\1'.$meta, $html, -1, $rcount); |
| | | if (!$rcount) { |
| | | $html = '<head>' . $meta . '</head>' . $html; |
| | | } |
| | | |
| | | // turn relative into absolute urls |
| | |
| | | // allow CSS styles, will be sanitized by rcmail_washtml_callback() |
| | | if (!$p['skip_washer_style_callback']) |
| | | $washer->add_callback('style', 'rcmail_washtml_callback'); |
| | | |
| | | // Remove non-UTF8 characters (#1487813) |
| | | $html = rc_utf8_clean($html); |
| | | |
| | | $html = $washer->wash($html); |
| | | $REMOTE_OBJECTS = $washer->extlinks; |
| | |
| | | else if ($data['type'] == 'enriched') { |
| | | $part->ctype_secondary = 'html'; |
| | | require_once(INSTALL_PATH . 'program/lib/enriched.inc'); |
| | | $body = Q(enriched_to_html($data['body']), 'show'); |
| | | $body = enriched_to_html($data['body']); |
| | | $body = rcmail_wash_html($body, $data, $part->replaces); |
| | | $part->ctype_secondary = 'html'; |
| | | } |
| | | else { |
| | | // assert plaintext |
| | |
| | | |
| | | // previous line is flowed? |
| | | if (isset($body[$last]) && $body[$n] |
| | | && $last != $last_sig |
| | | && $last !== $last_sig |
| | | && $body[$last][strlen($body[$last])-1] == ' ' |
| | | ) { |
| | | $body[$last] .= $body[$n]; |
| | |
| | | /** |
| | | * Callback function for washtml cleaning class |
| | | */ |
| | | function rcmail_washtml_callback($tagname, $attrib, $content) |
| | | function rcmail_washtml_callback($tagname, $attrib, $content, $washtml) |
| | | { |
| | | switch ($tagname) { |
| | | case 'form': |
| | |
| | | $stripped = preg_replace('/[^a-zA-Z\(:;]/', '', rcmail_xss_entity_decode($content)); |
| | | |
| | | // now check for evil strings like expression, behavior or url() |
| | | if (!preg_match('/expression|behavior|url\(|import[^a]/', $stripped)) { |
| | | $out = html::tag('style', array('type' => 'text/css'), $content); |
| | | if (!preg_match('/expression|behavior|javascript:|import[^a]/i', $stripped)) { |
| | | if (!$washtml->get_config('allow_remote') && stripos($stripped, 'url(')) |
| | | $washtml->extlinks = true; |
| | | else |
| | | $out = html::tag('style', array('type' => 'text/css'), $content); |
| | | break; |
| | | } |
| | | |
| | |
| | | $body = rcmail_print_body($part, array('safe' => $safe_mode, 'plain' => !$CONFIG['prefer_html'])); |
| | | |
| | | if ($part->ctype_secondary == 'html') { |
| | | $body = rcmail_html4inline($body, $attrib['id'], 'rcmBody', $attrs); |
| | | $body = rcmail_html4inline($body, $attrib['id'], 'rcmBody', $attrs, $safe_mode); |
| | | $div_attr = array('class' => 'message-htmlpart'); |
| | | $style = array(); |
| | | |
| | |
| | | rcmail_plain_body(Q($MESSAGE->body, 'strict', false)))); |
| | | } |
| | | |
| | | $ctype_primary = strtolower($MESSAGE->structure->ctype_primary); |
| | | $ctype_secondary = strtolower($MESSAGE->structure->ctype_secondary); |
| | | |
| | | // list images after mail body |
| | | if ($CONFIG['inline_images'] |
| | | && $ctype_primary == 'multipart' |
| | | && !empty($MESSAGE->attachments)) |
| | | { |
| | | if ($CONFIG['inline_images'] && !empty($MESSAGE->attachments)) { |
| | | foreach ($MESSAGE->attachments as $attach_prop) { |
| | | // skip inline images |
| | | if ($attach_prop->content_id && $attach_prop->disposition == 'inline') { |
| | | continue; |
| | | } |
| | | |
| | | // Content-Type: image/*... |
| | | if (preg_match('/^image\//i', $attach_prop->mimetype) || |
| | | // ...or known file extension: many clients are using application/octet-stream |
| | |
| | | ) { |
| | | $out .= html::tag('hr') . html::p(array('align' => "center"), |
| | | html::img(array( |
| | | 'src' => $MESSAGE->get_part_url($attach_prop->mime_id), |
| | | 'src' => $MESSAGE->get_part_url($attach_prop->mime_id, true), |
| | | 'title' => $attach_prop->filename, |
| | | 'alt' => $attach_prop->filename, |
| | | ))); |
| | |
| | | // check for <base href=...> |
| | | if (preg_match('!(<base.*href=["\']?)([hftps]{3,5}://[a-z0-9/.%-]+)!i', $body, $regs)) { |
| | | $replacer = new rcube_base_replacer($regs[2]); |
| | | |
| | | // replace all relative paths |
| | | $body = preg_replace_callback('/(src|background|href)=(["\']?)([^"\'\s]+)(\2|\s|>)/Ui', array($replacer, 'callback'), $body); |
| | | $body = preg_replace_callback('/(url\s*\()(["\']?)([^"\'\)\s]+)(\2)\)/Ui', array($replacer, 'callback'), $body); |
| | | $body = $replacer->replace($body); |
| | | } |
| | | |
| | | return $body; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * modify a HTML message that it can be displayed inside a HTML page |
| | | */ |
| | | function rcmail_html4inline($body, $container_id, $body_id='', &$attributes=null) |
| | | function rcmail_html4inline($body, $container_id, $body_id='', &$attributes=null, $allow_remote=false) |
| | | { |
| | | $last_style_pos = 0; |
| | | $body_lc = strtolower($body); |
| | |
| | | |
| | | // replace all css definitions with #container [def] |
| | | $styles = rcmail_mod_css_styles( |
| | | substr($body, $pos, $pos2-$pos), $cont_id); |
| | | substr($body, $pos, $pos2-$pos), $cont_id, $allow_remote); |
| | | |
| | | $body = substr($body, 0, $pos) . $styles . substr($body, $pos2); |
| | | $body_lc = strtolower($body); |
| | |
| | | 'href' => "#add", |
| | | 'onclick' => sprintf("return %s.command('add-contact','%s',this)", JS_OBJECT_NAME, urlencode($string)), |
| | | 'title' => rcube_label('addtoaddressbook'), |
| | | 'class' => 'rcmaddcontact', |
| | | ), |
| | | html::img(array( |
| | | 'src' => $CONFIG['skin_path'] . $addicon, |
| | |
| | | */ |
| | | 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)); |
| | | unset($_SESSION['compose_data'][$id]); |
| | | $rcmail->session->remove('compose_data_'.$id); |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | global $RCMAIL, $IMAP; |
| | | |
| | | if (!is_a($message, rcube_message)) |
| | | if (!is_object($message) || !is_a($message, 'rcube_message')) |
| | | $message = new rcube_message($message); |
| | | |
| | | if ($message->headers->mdn_to && !$message->headers->mdn_sent && |
| | | if ($message->headers->mdn_to && empty($message->headers->flags['MDNSENT']) && |
| | | ($IMAP->check_permflag('MDNSENT') || $IMAP->check_permflag('*'))) |
| | | { |
| | | $identity = $RCMAIL->user->get_identity(); |
| | |
| | | $select_filter->add(rcube_label('unanswered'), 'UNANSWERED'); |
| | | if (!$CONFIG['skip_deleted']) |
| | | $select_filter->add(rcube_label('deleted'), 'DELETED'); |
| | | $select_filter->add(rcube_label('priority').': '.rcube_label('highest'), 'HEADER X-PRIORITY 1'); |
| | | $select_filter->add(rcube_label('priority').': '.rcube_label('high'), 'HEADER X-PRIORITY 2'); |
| | | $select_filter->add(rcube_label('priority').': '.rcube_label('normal'), 'NOT HEADER X-PRIORITY 1 NOT HEADER X-PRIORITY 2 NOT HEADER X-PRIORITY 4 NOT HEADER X-PRIORITY 5'); |
| | | $select_filter->add(rcube_label('priority').': '.rcube_label('low'), 'HEADER X-PRIORITY 4'); |
| | | $select_filter->add(rcube_label('priority').': '.rcube_label('lowest'), 'HEADER X-PRIORITY 5'); |
| | | |
| | | $out = $select_filter->show($_SESSION['search_filter']); |
| | | |