summaryrefslogtreecommitdiff
path: root/program/steps
diff options
context:
space:
mode:
Diffstat (limited to 'program/steps')
-rw-r--r--program/steps/mail/check_recent.inc33
-rw-r--r--program/steps/mail/func.inc358
-rw-r--r--program/steps/mail/list.inc21
-rw-r--r--program/steps/mail/mark.inc9
-rw-r--r--program/steps/mail/move_del.inc10
-rw-r--r--program/steps/mail/search.inc4
-rw-r--r--program/steps/mail/show.inc4
-rw-r--r--program/steps/mail/viewsource.inc2
-rw-r--r--program/steps/settings/func.inc24
-rw-r--r--program/steps/settings/manage_folders.inc84
-rw-r--r--program/steps/settings/save_prefs.inc2
11 files changed, 281 insertions, 270 deletions
diff --git a/program/steps/mail/check_recent.inc b/program/steps/mail/check_recent.inc
index 9bc9e6f92..3c2827502 100644
--- a/program/steps/mail/check_recent.inc
+++ b/program/steps/mail/check_recent.inc
@@ -32,13 +32,12 @@ foreach ($a_mailboxes as $mbox_name) {
}
// get overall message count; allow caching because rcube_imap::recent_uids() did a refresh
- $all_count = $IMAP->messagecount();
+ $all_count = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL');
$unread_count = $IMAP->messagecount(NULL, 'UNSEEN', TRUE);
$_SESSION['unseen_count'][$mbox_name] = $unread_count;
$OUTPUT->set_env('messagecount', $all_count);
- $OUTPUT->set_env('pagesize', $IMAP->page_size);
$OUTPUT->set_env('pagecount', ceil($all_count/$IMAP->page_size));
$OUTPUT->command('set_unread_count', $mbox_name, $unread_count, ($mbox_name == 'INBOX'));
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($all_count));
@@ -56,17 +55,27 @@ foreach ($a_mailboxes as $mbox_name) {
if (empty($_GET['_list']))
continue;
- // use SEARCH/SORT to find recent messages
- $search_str = 'UID '.min($recents).':'.max($recents);
- if ($search_request)
- $search_str .= ' '.$IMAP->search_string;
+ if ($IMAP->threading) {
+ $OUTPUT->command('message_list.clear');
+ $sort_col = isset($_SESSION['sort_col']) ? $_SESSION['sort_col'] : $CONFIG['message_sort_col'];
+ $sort_order = isset($_SESSION['sort_order']) ? $_SESSION['sort_order'] : $CONFIG['message_sort_order'];
+ $result_h = $IMAP->list_headers($mbox_name, NULL, $sort_col, $sort_order);
+ // add to the list
+ rcmail_js_message_list($result_h);
+ }
+ else {
+ // use SEARCH/SORT to find recent messages
+ $search_str = 'UID '.min($recents).':'.max($recents);
+ if ($search_request)
+ $search_str .= ' '.$IMAP->search_string;
- if ($IMAP->search($mbox_name, $search_str, NULL, 'date')) {
- // revert sort order
- $order = $_SESSION['sort_col'] == 'date' && $_SESSION['sort_order'] == 'DESC' ? 'ASC' : 'DESC';
- // get the headers and add them to the list
- $result_h = $IMAP->list_headers($mbox_name, 1, 'date', $order);
- rcmail_js_message_list($result_h, true, false);
+ if ($IMAP->search($mbox_name, $search_str, NULL, 'date')) {
+ // revert sort order
+ $order = $_SESSION['sort_col'] == 'date' && $_SESSION['sort_order'] == 'DESC' ? 'ASC' : 'DESC';
+ // get the headers and add them to the list
+ $result_h = $IMAP->list_headers($mbox_name, 1, 'date', $order);
+ rcmail_js_message_list($result_h, true, false);
+ }
}
}
else {
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index 1968d20b2..5f52161c4 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -59,6 +59,17 @@ if (!isset($_SESSION['sort_col']))
if (!isset($_SESSION['sort_order']))
$_SESSION['sort_order'] = $CONFIG['message_sort_order'];
+// 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));
+}
+$IMAP->set_threading($a_threading[$_SESSION['mbox']]);
+
// set message set for search result
if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']]))
{
@@ -88,13 +99,20 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list')
$OUTPUT->set_env('search_mods', $search_mods);
// make sure the message count is refreshed (for default view)
- $IMAP->messagecount($mbox_name, 'ALL', true);
+ $IMAP->messagecount($mbox_name, $IMAP->threading ? 'THREADS' : 'ALL', true);
}
- // set current mailbox in client environment
+ // set current mailbox and some other vars in client environment
$OUTPUT->set_env('mailbox', $mbox_name);
+ $OUTPUT->set_env('pagesize', $IMAP->page_size);
$OUTPUT->set_env('quota', $IMAP->get_capability('quota'));
$OUTPUT->set_env('delimiter', $IMAP->get_hierarchy_delimiter());
+ $OUTPUT->set_env('threading', (bool) $IMAP->threading);
+ $OUTPUT->set_env('threads', $IMAP->threading
+ || $IMAP->get_capability('thread=references')
+ || $IMAP->get_capability('thread=orderedsubject')
+ || $IMAP->get_capability('thread=refs')
+ );
if ($CONFIG['flag_for_deletion'])
$OUTPUT->set_env('flag_for_deletion', true);
@@ -123,43 +141,26 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list')
* return the message list as HTML table
*/
function rcmail_message_list($attrib)
- {
- global $IMAP, $CONFIG, $COMM_PATH, $OUTPUT;
-
- $skin_path = $CONFIG['skin_path'];
- $image_tag = '<img src="%s%s" alt="%s" />';
+{
+ global $IMAP, $CONFIG, $OUTPUT;
- // check to see if we have some settings for sorting
- $sort_col = $_SESSION['sort_col'];
- $sort_order = $_SESSION['sort_order'];
-
// add some labels to client
$OUTPUT->add_label('from', 'to');
- // get message headers
- $a_headers = $IMAP->list_headers('', '', $sort_col, $sort_order);
-
// add id to message list table if not specified
if (!strlen($attrib['id']))
$attrib['id'] = 'rcubemessagelist';
- // allow the following attributes to be added to the <table> tag
- $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary'));
-
- $out = '<table' . $attrib_str . ">\n";
-
// 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');
else
$a_show_cols = preg_split('/[\s,;]+/', strip_quotes($attrib['columns']));
- // store column list in a session-variable
+ // save some variables for use in ajax list
$_SESSION['list_columns'] = $a_show_cols;
+ $_SESSION['list_attrib'] = $attrib;
- // define sortable columns
- $a_sort_cols = array('subject', 'date', 'from', 'to', 'size');
-
$mbox = $IMAP->get_mailbox_name();
$delim = $IMAP->get_hierarchy_delimiter();
@@ -167,198 +168,19 @@ function rcmail_message_list($attrib)
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';
-
- // add col definition
- $out .= '<colgroup>';
- $out .= '<col class="icon" />';
-
- foreach ($a_show_cols as $col)
- $out .= ($col!='attachment') ? sprintf('<col class="%s" />', $col) : '<col class="icon" />';
- $out .= "</colgroup>\n";
-
- // add table title
- $out .= "<thead><tr>\n<td class=\"icon\">&nbsp;</td>\n";
-
- $javascript = '';
- foreach ($a_show_cols as $col)
- {
- // get column name
- switch ($col)
- {
- case 'flag':
- $col_name = sprintf($image_tag, $skin_path, $attrib['unflaggedicon'], '');
- break;
- case 'attachment':
- $col_name = sprintf($image_tag, $skin_path, $attrib['attachmenticon'], '');
- break;
- default:
- $col_name = Q(rcube_label($col));
- }
-
- // make sort links
- $sort = '';
- if (in_array($col, $a_sort_cols))
- {
- // have buttons configured
- if (!empty($attrib['sortdescbutton']) || !empty($attrib['sortascbutton']))
- {
- $sort = '&nbsp;&nbsp;';
-
- // asc link
- if (!empty($attrib['sortascbutton']))
- {
- $sort .= $OUTPUT->button(array(
- 'command' => 'sort',
- 'prop' => $col.'_ASC',
- 'image' => $attrib['sortascbutton'],
- 'align' => 'absmiddle',
- 'title' => 'sortasc'));
- }
-
- // desc link
- if (!empty($attrib['sortdescbutton']))
- {
- $sort .= $OUTPUT->button(array(
- 'command' => 'sort',
- 'prop' => $col.'_DESC',
- 'image' => $attrib['sortdescbutton'],
- 'align' => 'absmiddle',
- 'title' => 'sortdesc'));
- }
- }
- // just add a link tag to the header
- else
- {
- $col_name = sprintf(
- '<a href="./#sort" onclick="return %s.command(\'sort\',\'%s\',this)" title="%s">%s</a>',
- JS_OBJECT_NAME,
- $col,
- rcube_label('sortby'),
- $col_name);
- }
- }
-
- $sort_class = $col==$sort_col ? " sorted$sort_order" : '';
-
- // put it all together
- if ($col!='attachment')
- $out .= '<td class="'.$col.$sort_class.'" id="rcm'.$col.'">' . "$col_name$sort</td>\n";
- else
- $out .= '<td class="icon" id="rcm'.$col.'">' . "$col_name$sort</td>\n";
- }
-
- $out .= "</tr></thead>\n<tbody>\n";
-
- // no messages in this mailbox
- if (!sizeof($a_headers))
- $OUTPUT->show_message('nomessagesfound', 'notice');
-
- $a_js_message_arr = array();
-
- // create row for each message
- foreach ($a_headers as $i => $header) //while (list($i, $header) = each($a_headers))
- {
- $message_icon = $attach_icon = $flagged_icon = '';
- $js_row_arr = array();
- $zebra_class = $i%2 ? ' even' : ' odd';
-
- // set messag attributes to javascript array
- if ($header->deleted)
- $js_row_arr['deleted'] = true;
- if (!$header->seen)
- $js_row_arr['unread'] = true;
- if ($header->answered)
- $js_row_arr['replied'] = true;
- if ($header->forwarded)
- $js_row_arr['forwarded'] = true;
- if ($header->flagged)
- $js_row_arr['flagged'] = true;
-
- // set message icon
- if ($attrib['deletedicon'] && $header->deleted)
- $message_icon = $attrib['deletedicon'];
- else if ($attrib['repliedicon'] && $header->answered)
- {
- if ($attrib['forwardedrepliedicon'] && $header->forwarded)
- $message_icon = $attrib['forwardedrepliedicon'];
- else
- $message_icon = $attrib['repliedicon'];
- }
- else if ($attrib['forwardedicon'] && $header->forwarded)
- $message_icon = $attrib['forwardedicon'];
- else if ($attrib['unreadicon'] && !$header->seen)
- $message_icon = $attrib['unreadicon'];
- else if ($attrib['messageicon'])
- $message_icon = $attrib['messageicon'];
-
- if ($attrib['flaggedicon'] && $header->flagged)
- $flagged_icon = $attrib['flaggedicon'];
- else if ($attrib['unflaggedicon'] && !$header->flagged)
- $flagged_icon = $attrib['unflaggedicon'];
-
- // set attachment icon
- if ($attrib['attachmenticon'] && preg_match("/multipart\/m/i", $header->ctype))
- $attach_icon = $attrib['attachmenticon'];
-
- $out .= sprintf('<tr id="rcmrow%d" class="message%s%s%s%s">'."\n",
- $header->uid,
- $header->seen ? '' : ' unread',
- $header->deleted ? ' deleted' : '',
- $header->flagged ? ' flagged' : '',
- $zebra_class);
-
- $out .= sprintf("<td class=\"icon\">%s</td>\n", $message_icon ? sprintf($image_tag, $skin_path, $message_icon, '') : '');
-
- $IMAP->set_charset(!empty($header->charset) ? $header->charset : $CONFIG['default_charset']);
-
- // format each col
- foreach ($a_show_cols as $col)
- {
- if (in_array($col, array('from', 'to', 'cc', 'replyto')))
- $cont = Q(rcmail_address_string($header->$col, 3, false, $attrib['addicon']), 'show');
- else if ($col=='subject')
- {
- $action = $mbox==$CONFIG['drafts_mbox'] ? 'compose' : 'show';
- $uid_param = $mbox==$CONFIG['drafts_mbox'] ? '_draft_uid' : '_uid';
- $cont = abbreviate_string(trim($IMAP->decode_header($header->$col)), 160);
- if (empty($cont)) $cont = rcube_label('nosubject');
- $cont = $OUTPUT->browser->ie ? Q($cont) : sprintf('<a href="%s" onclick="return rcube_event.cancel(event)">%s</a>', Q(rcmail_url($action, array($uid_param=>$header->uid, '_mbox'=>$mbox))), Q($cont));
- }
- else if ($col=='flag')
- $cont = $flagged_icon ? sprintf($image_tag, $skin_path, $flagged_icon, '') : '';
- else if ($col=='size')
- $cont = show_bytes($header->$col);
- else if ($col=='date')
- $cont = format_date($header->date);
- else
- $cont = Q($header->$col);
-
- if ($col!='attachment')
- $out .= '<td class="'.$col.'">' . $cont . "</td>\n";
- else
- $out .= sprintf("<td class=\"icon\">%s</td>\n", $attach_icon ? sprintf($image_tag, $skin_path, $attach_icon, '') : '&nbsp;');
- }
-
- $out .= "</tr>\n";
-
- if (sizeof($js_row_arr))
- $a_js_message_arr[$header->uid] = $js_row_arr;
- }
-
- // complete message table
- $out .= "</tbody></table>\n";
-
- $message_count = $IMAP->messagecount();
+ $skin_path = $_SESSION['skin_path'] = $CONFIG['skin_path'];
+ $message_count = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL');
// set client env
$OUTPUT->add_gui_object('mailcontframe', 'mailcontframe');
$OUTPUT->add_gui_object('messagelist', $attrib['id']);
+ $OUTPUT->set_env('autoexpand_threads', intval($CONFIG['autoexpand_threads']));
$OUTPUT->set_env('messagecount', $message_count);
$OUTPUT->set_env('current_page', $IMAP->list_page);
$OUTPUT->set_env('pagecount', ceil($message_count/$IMAP->page_size));
- $OUTPUT->set_env('sort_col', $sort_col);
- $OUTPUT->set_env('sort_order', $sort_order);
+ $OUTPUT->set_env('sort_col', $_SESSION['sort_col']);
+ $OUTPUT->set_env('sort_order', $_SESSION['sort_order']);
if ($attrib['messageicon'])
$OUTPUT->set_env('messageicon', $skin_path . $attrib['messageicon']);
@@ -378,22 +200,35 @@ function rcmail_message_list($attrib)
$OUTPUT->set_env('flaggedicon', $skin_path . $attrib['flaggedicon']);
if ($attrib['unflaggedicon'])
$OUTPUT->set_env('unflaggedicon', $skin_path . $attrib['unflaggedicon']);
+ if ($attrib['unreadchildrenicon'])
+ $OUTPUT->set_env('unreadchildrenicon', $skin_path . $attrib['unreadchildrenicon']);
- $OUTPUT->set_env('messages', $a_js_message_arr);
+ $OUTPUT->set_env('messages', array());
$OUTPUT->set_env('coltypes', $a_show_cols);
+ if (!$message_count)
+ $OUTPUT->show_message('nomessagesfound', 'notice');
+
$OUTPUT->include_script('list.js');
- return $out;
- }
+ $thead = '';
+ foreach (rcmail_message_list_head($attrib, $a_show_cols) as $cell)
+ $thead .= html::tag('td', array('class' => $cell['className'], 'id' => $cell['id']), $cell['html']);
+
+ return html::tag('table',
+ $attrib,
+ html::tag('thead', null, html::tag('tr', null, $thead)) .
+ html::tag('tbody', null, ''),
+ array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary'));
+}
/**
* return javascript commands to add rows to the message list
* or to replace the whole list (IE only)
*/
-function rcmail_js_message_list($a_headers, $insert_top=FALSE, $replace=TRUE)
- {
+function rcmail_js_message_list($a_headers, $insert_top=FALSE, $replace=TRUE, $head_replace=FALSE)
+{
global $CONFIG, $IMAP, $OUTPUT;
if (empty($_SESSION['list_columns']))
@@ -409,9 +244,12 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $replace=TRUE)
&& (($f = array_search('from', $a_show_cols)) !== false) && array_search('to', $a_show_cols) === false)
$a_show_cols[$f] = 'to';
- $browser = new rcube_browser;
+ $thead = $head_replace ? rcmail_message_list_head($_SESSION['list_attrib'], $a_show_cols) : NULL;
+
+ $OUTPUT->command('set_message_coltypes', $a_show_cols, $thead);
- $OUTPUT->command('set_message_coltypes', $a_show_cols);
+ if (empty($a_headers))
+ return;
// remove 'attachment' and 'flag' columns, we don't need them here
if(($key = array_search('attachment', $a_show_cols)) !== FALSE)
@@ -419,7 +257,7 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $replace=TRUE)
if(($key = array_search('flag', $a_show_cols)) !== FALSE)
unset($a_show_cols[$key]);
- if ($browser->ie && $replace)
+ if ($OUTPUT->browser->ie && $replace)
$OUTPUT->command('offline_message_list', true);
// loop through message headers
@@ -440,10 +278,9 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $replace=TRUE)
$cont = Q(rcmail_address_string($header->$col, 3), 'show');
else if ($col=='subject')
{
- $cont = abbreviate_string(trim($IMAP->decode_header($header->$col)), 160);
+ $cont = abbreviate_string(trim($IMAP->decode_header($header->$col)), 160);
if (!$cont) $cont = rcube_label('nosubject');
- $cont = Q($cont);
- $a_msg_cols['mbox'] = $mbox;
+ $cont = Q($cont);
}
else if ($col=='size')
$cont = show_bytes($header->$col);
@@ -455,6 +292,14 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $replace=TRUE)
$a_msg_cols[$col] = $cont;
}
+ if ($header->depth)
+ $a_msg_flags['depth'] = $header->depth;
+ if ($header->parent_uid)
+ $a_msg_flags['parent_uid'] = $header->parent_uid;
+ 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)
@@ -465,12 +310,14 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $replace=TRUE)
$a_msg_flags['forwarded'] = 1;
if ($header->flagged)
$a_msg_flags['flagged'] = 1;
-
+ if(preg_match("/multipart\/m/i", $header->ctype))
+ $a_msg_flags['attachment'] = 1;
+ $a_msg_flags['mbox'] = $mbox;
+
$OUTPUT->command('add_message_row',
$header->uid,
$a_msg_cols,
$a_msg_flags,
- preg_match("/multipart\/m/i", $header->ctype),
$insert_top);
}
@@ -479,6 +326,61 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $replace=TRUE)
}
+/*
+ * Creates <THEAD> for message list table
+ */
+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"));
+
+ // check to see if we have some settings for sorting
+ $sort_col = $_SESSION['sort_col'];
+ $sort_order = $_SESSION['sort_order'];
+
+ // define sortable columns
+ $a_sort_cols = array('subject', 'date', 'from', 'to', 'size', 'cc');
+
+ if (!empty($attrib['optionsmenuicon']))
+ $list_menu = html::a(
+ array('href' => '#', 'onclick' => 'return '.JS_OBJECT_NAME.".command('menu-open', 'messagelistmenu')"),
+ html::img(array('src' => $skin_path . $attrib['optionsmenuicon'], 'id' => 'listmenulink', 'title' => rcube_label('listoptions')))
+ );
+ else
+ $list_menu = '';
+
+ $cells = array(array('className' => 'threads', 'html' => $list_menu));
+
+ foreach ($a_show_cols as $col) {
+ // get column name
+ switch ($col) {
+ case 'flag':
+ $col_name = sprintf($image_tag, $skin_path, $attrib['unflaggedicon'], '');
+ break;
+ case 'attachment':
+ $col_name = sprintf($image_tag, $skin_path, $attrib['attachmenticon'], '');
+ break;
+ default:
+ $col_name = Q(rcube_label($col));
+ }
+
+ // make sort links
+ if (in_array($col, $a_sort_cols))
+ $col_name = html::a(array('href'=>"./#sort", 'onclick' => 'return '.JS_OBJECT_NAME.".command('sort','".$col."',this)", 'title' => rcube_label('sortby')), $col_name);
+
+ $sort_class = $col == $sort_col ? " sorted$sort_order" : '';
+ $class_name = $col == 'attachment' ? 'icon' : $col.$sort_class;
+
+ // put it all together
+ $cells[] = array('className' => $class_name, 'id' => "rcm$col", 'html' => $col_name);
+ }
+
+ return $cells;
+}
+
+
/**
* return an HTML iframe for loading mail content
*/
@@ -513,7 +415,7 @@ function rcmail_messagecount_display($attrib)
function rcmail_quota_display($attrib)
{
- global $OUTPUT, $COMM_PATH;
+ global $OUTPUT;
if (!$attrib['id'])
$attrib['id'] = 'rcmquotadisplay';
@@ -582,23 +484,23 @@ function rcmail_get_messagecount_text($count=NULL, $page=NULL)
if (isset($MESSAGE->index))
{
return rcube_label(array('name' => 'messagenrof',
- 'vars' => array('nr' => $MESSAGE->index+1,
- 'count' => $count!==NULL ? $count : $IMAP->messagecount())));
+ 'vars' => array('nr' => $MESSAGE->index+1,
+ 'count' => $count!==NULL ? $count : $IMAP->messagecount(NULL, 'ALL')))); // Only messages, no threads here
}
if ($page===NULL)
$page = $IMAP->list_page;
$start_msg = ($page-1) * $IMAP->page_size + 1;
- $max = $count!==NULL ? $count : $IMAP->messagecount();
+ $max = $count!==NULL ? $count : $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL');
if ($max==0)
$out = rcube_label('mailboxempty');
else
- $out = rcube_label(array('name' => 'messagesfromto',
- 'vars' => array('from' => $start_msg,
- 'to' => min($max, $start_msg + $IMAP->page_size - 1),
- 'count' => $max)));
+ $out = rcube_label(array('name' => $IMAP->threading ? 'threadsfromto' : 'messagesfromto',
+ 'vars' => array('from' => $start_msg,
+ 'to' => min($max, $start_msg + $IMAP->page_size - 1),
+ 'count' => $max)));
return Q($out);
}
diff --git a/program/steps/mail/list.inc b/program/steps/mail/list.inc
index cd1a3142d..89d127cdc 100644
--- a/program/steps/mail/list.inc
+++ b/program/steps/mail/list.inc
@@ -33,8 +33,6 @@ if ($sort = get_input_value('_sort', RCUBE_INPUT_GET))
$save_arr = array();
$_SESSION['sort_col'] = $save_arr['message_sort_col'] = $sort_col;
$_SESSION['sort_order'] = $save_arr['message_sort_order'] = $sort_order;
-
- $RCMAIL->user->save_prefs($save_arr);
}
else
{
@@ -43,6 +41,16 @@ else
$sort_order = isset($_SESSION['sort_order']) ? $_SESSION['sort_order'] : $CONFIG['message_sort_order'];
}
+// is there a set of columns for this request?
+if ($cols = get_input_value('_cols', RCUBE_INPUT_GET))
+{
+ $save_arr = array();
+ $_SESSION['list_columns'] = $save_arr['list_cols'] = explode(',', $cols);
+}
+
+if ($save_arr)
+ $RCMAIL->user->save_prefs($save_arr);
+
$mbox_name = $IMAP->get_mailbox_name();
// initialize searching result if search_filter is used
@@ -55,9 +63,13 @@ if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL')
}
// fetch message headers
-if ($count = $IMAP->messagecount($mbox_name, 'ALL', !empty($_REQUEST['_refresh'])))
+if ($count = $IMAP->messagecount($mbox_name, $IMAP->threading ? 'THREADS' : 'ALL', !empty($_REQUEST['_refresh'])))
$a_headers = $IMAP->list_headers($mbox_name, NULL, $sort_col, $sort_order);
+// update search set (possible change of threading mode)
+if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']]))
+ $_SESSION['search'][$_REQUEST['_search']] = $IMAP->get_search_set();
+
// update mailboxlist
rcmail_send_unread_count($mbox_name, !empty($_REQUEST['_refresh']));
@@ -65,13 +77,14 @@ rcmail_send_unread_count($mbox_name, !empty($_REQUEST['_refresh']));
$pages = ceil($count/$IMAP->page_size);
$OUTPUT->set_env('messagecount', $count);
$OUTPUT->set_env('pagecount', $pages);
+$OUTPUT->set_env('threading', (bool) $IMAP->threading);
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count));
$OUTPUT->command('set_mailboxname', rcmail_get_mailbox_name_text());
// add message rows
+rcmail_js_message_list($a_headers, FALSE, TRUE, (bool) $cols);
if (isset($a_headers) && count($a_headers))
{
- rcmail_js_message_list($a_headers);
if ($search_request)
$OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $count));
}
diff --git a/program/steps/mail/mark.inc b/program/steps/mail/mark.inc
index 3e0ee9ecb..c37a6e47c 100644
--- a/program/steps/mail/mark.inc
+++ b/program/steps/mail/mark.inc
@@ -36,7 +36,7 @@ if (($uids = get_input_value('_uid', RCUBE_INPUT_POST)) && ($flag = get_input_va
if ($flag == 'DELETED' && $CONFIG['skip_deleted'] && $_POST['_from'] != 'show') {
// count messages before changing anything
- $old_count = $IMAP->messagecount();
+ $old_count = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL');
$old_pages = ceil($old_count / $IMAP->page_size);
$count = sizeof(explode(',', $uids));
}
@@ -75,7 +75,7 @@ if (($uids = get_input_value('_uid', RCUBE_INPUT_POST)) && ($flag = get_input_va
$_SESSION['search'][$search_request] = $IMAP->refresh_search();
}
- $msg_count = $IMAP->messagecount();
+ $msg_count = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL');
$pages = ceil($msg_count / $IMAP->page_size);
$nextpage_count = $old_count - $IMAP->page_size * $IMAP->list_page;
$remaining = $msg_count - $IMAP->page_size * ($IMAP->list_page - 1);
@@ -103,8 +103,11 @@ if (($uids = get_input_value('_uid', RCUBE_INPUT_POST)) && ($flag = get_input_va
}
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count));
+ if ($IMAP->threading)
+ $count = get_input_value('_count', RCUBE_INPUT_POST);
+
// add new rows from next page (if any)
- if (($jump_back || $nextpage_count > 0)) {
+ if ($count && ($jump_back || $nextpage_count > 0)) {
$sort_col = isset($_SESSION['sort_col']) ? $_SESSION['sort_col'] : $CONFIG['message_sort_col'];
$sort_order = isset($_SESSION['sort_order']) ? $_SESSION['sort_order'] : $CONFIG['message_sort_order'];
diff --git a/program/steps/mail/move_del.inc b/program/steps/mail/move_del.inc
index b8bd16557..f884a781e 100644
--- a/program/steps/mail/move_del.inc
+++ b/program/steps/mail/move_del.inc
@@ -24,7 +24,7 @@ if (!$OUTPUT->ajax_call)
return;
// count messages before changing anything
-$old_count = $IMAP->messagecount();
+$old_count = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL');
$old_pages = ceil($old_count / $IMAP->page_size);
// move messages
@@ -50,6 +50,7 @@ if ($RCMAIL->action=='moveto' && !empty($_POST['_uid']) && !empty($_POST['_targe
else if ($RCMAIL->action=='delete' && !empty($_POST['_uid'])) {
$count = sizeof(explode(',', ($uids = get_input_value('_uid', RCUBE_INPUT_POST))));
$mbox = get_input_value('_mbox', RCUBE_INPUT_POST);
+
$del = $IMAP->delete_message($uids, $mbox);
if (!$del) {
@@ -82,7 +83,7 @@ if ($_POST['_from'] == 'show')
}
else
{
- $msg_count = $IMAP->messagecount();
+ $msg_count = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL');
$pages = ceil($msg_count / $IMAP->page_size);
$nextpage_count = $old_count - $IMAP->page_size * $IMAP->list_page;
$remaining = $msg_count - $IMAP->page_size * ($IMAP->list_page - 1);
@@ -116,8 +117,11 @@ else
$OUTPUT->command('set_quota', rcmail_quota_content());
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count));
+ if ($IMAP->threading)
+ $count = get_input_value('_count', RCUBE_INPUT_POST);
+
// add new rows from next page (if any)
- if ($addrows && ($jump_back || $nextpage_count > 0)) {
+ if ($addrows && $count && ($jump_back || $nextpage_count > 0)) {
$sort_col = isset($_SESSION['sort_col']) ? $_SESSION['sort_col'] : $CONFIG['message_sort_col'];
$sort_order = isset($_SESSION['sort_order']) ? $_SESSION['sort_order'] : $CONFIG['message_sort_order'];
diff --git a/program/steps/mail/search.inc b/program/steps/mail/search.inc
index 54c765047..52469952a 100644
--- a/program/steps/mail/search.inc
+++ b/program/steps/mail/search.inc
@@ -104,7 +104,7 @@ if ($search_str)
// Get the headers
$result_h = $IMAP->list_headers($mbox, 1, $_SESSION['sort_col'], $_SESSION['sort_order']);
-$count = $IMAP->messagecount();
+$count = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL');
// save search results in session
if (!is_array($_SESSION['search']))
@@ -120,7 +120,7 @@ if (!empty($result_h))
{
rcmail_js_message_list($result_h);
if ($search_str)
- $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $count));
+ $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $IMAP->messagecount(NULL, 'ALL')));
}
else
{
diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc
index 33e87d5bc..02e1f4824 100644
--- a/program/steps/mail/show.inc
+++ b/program/steps/mail/show.inc
@@ -104,7 +104,7 @@ if ($_GET['_uid']) {
$next = $prev = $first = $last = -1;
if ($_SESSION['sort_col'] == 'date' && $_SESSION['sort_order'] != 'DESC'
- && empty($_REQUEST['_search']) && !$IMAP->skip_deleted)
+ && empty($_REQUEST['_search']) && !$CONFIG['skip_deleted'] && !$IMAP->threading)
{
// this assumes that we are sorted by date_DESC
$cnt = $IMAP->messagecount();
@@ -142,7 +142,7 @@ if ($_GET['_uid']) {
if (!$MESSAGE->headers->seen)
$RCMAIL->plugins->exec_hook('message_read', array('uid' => $MESSAGE->uid,
- 'mailbox' => $IMAP->mailbox, 'message' => $MESSAGE));
+ 'mailbox' => $mbox_name, 'message' => $MESSAGE));
}
diff --git a/program/steps/mail/viewsource.inc b/program/steps/mail/viewsource.inc
index 17e382456..2e2228ab6 100644
--- a/program/steps/mail/viewsource.inc
+++ b/program/steps/mail/viewsource.inc
@@ -25,7 +25,7 @@ ob_end_clean();
if ($uid = get_input_value('_uid', RCUBE_INPUT_GET))
{
$headers = $IMAP->get_headers($uid);
- $charset = $headers->charset ? $headers->charset : $IMAP->default_charset;
+ $charset = $headers->charset ? $headers->charset : $CONFIG['default_charset'];
header("Content-Type: text/plain; charset={$charset}");
if (!empty($_GET['_save'])) {
diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc
index 44225c715..421fb37bf 100644
--- a/program/steps/settings/func.inc
+++ b/program/steps/settings/func.inc
@@ -248,17 +248,6 @@ function rcmail_user_prefs($current=null)
);
}
- // Show checkbox for toggling 'index_sort'
- if (!isset($no_override['index_sort'])) {
- $field_id = 'rcmfd_indexsort';
- $input_indexsort = new html_checkbox(array('name' => '_index_sort', 'id' => $field_id, 'value' => 1));
-
- $blocks['list']['options']['index_sort'] = array(
- 'title' => html::label($field_id, Q(rcube_label('indexsort'))),
- 'content' => $input_indexsort->show($config['index_sort']?1:0),
- );
- }
-
// show drop-down for available skins
if (!isset($no_override['skin'])) {
$skins = rcmail_get_skins();
@@ -311,6 +300,19 @@ function rcmail_user_prefs($current=null)
);
}
+ if (!isset($no_override['autoexpand_threads'])) {
+ $field_id = 'rcmfd_autoexpand_threads';
+ $select_autoexpand_threads = new html_select(array('name' => '_autoexpand_threads', 'id' => $field_id));
+ $select_autoexpand_threads->add(rcube_label('never'), 0);
+ $select_autoexpand_threads->add(rcube_label('do_expand'), 1);
+ $select_autoexpand_threads->add(rcube_label('expand_only_unread'), 2);
+
+ $blocks['main']['options']['autoexpand_threads'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('autoexpand_threads'))),
+ 'content' => $select_autoexpand_threads->show($config['autoexpand_threads']),
+ );
+ }
+
if (!isset($no_override['focus_on_new_message'])) {
$field_id = 'rcmfd_focus_on_new_message';
$input_focus_on_new_message = new html_checkbox(array('name' => '_focus_on_new_message', 'id' => $field_id, 'value' => 1));
diff --git a/program/steps/settings/manage_folders.inc b/program/steps/settings/manage_folders.inc
index 06fee7a87..fa5a4db70 100644
--- a/program/steps/settings/manage_folders.inc
+++ b/program/steps/settings/manage_folders.inc
@@ -38,6 +38,20 @@ else if ($RCMAIL->action=='unsubscribe')
$IMAP->unsubscribe(array($mbox));
}
+// enable threading for one or more mailboxes
+else if ($RCMAIL->action=='enable-threading')
+ {
+ if ($mbox = get_input_value('_mbox', RCUBE_INPUT_POST, false, 'UTF7-IMAP'))
+ rcube_set_threading($mbox, true);
+ }
+
+// enable threading for one or more mailboxes
+else if ($RCMAIL->action=='disable-threading')
+ {
+ if ($mbox = get_input_value('_mbox', RCUBE_INPUT_POST, false, 'UTF7-IMAP'))
+ rcube_set_threading($mbox, false);
+ }
+
// create a new mailbox
else if ($RCMAIL->action=='create-folder')
{
@@ -79,6 +93,24 @@ else if ($RCMAIL->action=='rename-folder')
$rename = $IMAP->rename_mailbox($oldname, $name);
}
+ // update per-folder options for modified folder and its subfolders
+ if ($rename) {
+ $a_threaded = $RCMAIL->config->get('message_threading', array());
+ $delimiter = $IMAP->get_hierarchy_delimiter();
+ $oldprefix = '/^' . preg_quote($oldname . $delimiter, '/') . '/';
+ foreach ($a_threaded as $key => $val)
+ if ($key == $oldname) {
+ unset($a_threaded[$key]);
+ $a_threaded[$name] = true;
+ }
+ else if (preg_match($oldprefix, $key)) {
+ unset($a_threaded[$key]);
+ $a_threaded[preg_replace($oldprefix, $name.$delimiter, $key)] = true;
+ }
+
+ $RCMAIL->user->save_prefs(array('message_threading' => $a_threaded));
+ }
+
if ($rename && $OUTPUT->ajax_call)
{
$folderlist = $IMAP->list_unsubscribed();
@@ -159,7 +191,11 @@ if ($OUTPUT->ajax_call)
// build table with all folders listed by server
function rcube_subscription_form($attrib)
{
- global $IMAP, $CONFIG, $OUTPUT;
+ global $RCMAIL, $IMAP, $CONFIG, $OUTPUT;
+
+ $threading_supported = $IMAP->get_capability('thread=references')
+ || $IMAP->get_capability('thread=orderedsubject')
+ || $IMAP->get_capability('thread=refs');
list($form_start, $form_end) = get_form_tags($attrib, 'folders');
unset($attrib['form']);
@@ -173,15 +209,17 @@ function rcube_subscription_form($attrib)
$table->add_header('name', rcube_label('foldername'));
$table->add_header('msgcount', rcube_label('messagecount'));
$table->add_header('subscribed', rcube_label('subscribed'));
+ if ($threading_supported)
+ $table->add_header('threaded', rcube_label('threaded'));
$table->add_header('rename', '&nbsp;');
$table->add_header('delete', '&nbsp;');
-
// get folders from server
$IMAP->clear_cache('mailboxes');
$a_unsubscribed = $IMAP->list_unsubscribed();
$a_subscribed = $IMAP->list_mailboxes();
+ $a_threaded = $a_threaded_copy = $RCMAIL->config->get('message_threading', array());
$delimiter = $IMAP->get_hierarchy_delimiter();
$a_js_folders = $seen_folders = $list_folders = array();
@@ -203,14 +241,28 @@ function rcube_subscription_form($attrib)
}
}
+ unset($a_threaded_copy[$folder]);
+
$list_folders[] = array('id' => $folder, 'name' => $name, 'level' => $level);
$seen[$folder]++;
}
+ // remove 'message_threading' option for not existing folders
+ if ($a_threaded_copy) {
+ foreach ($a_threaded_copy as $key => $val)
+ unset($a_threaded[$key]);
+ unset($a_threaded_copy);
+ $RCMAIL->user->save_prefs(array('message_threading' => $a_threaded));
+ }
+
$checkbox_subscribe = new html_checkbox(array(
'name' => '_subscribed[]',
'onclick' => JS_OBJECT_NAME.".command(this.checked?'subscribe':'unsubscribe',this.value)",
));
+ $checkbox_threaded = new html_checkbox(array(
+ 'name' => '_threaded[]',
+ 'onclick' => JS_OBJECT_NAME.".command(this.checked?'enable-threading':'disable-threading',this.value)",
+ ));
if (!empty($attrib['deleteicon']))
$del_button = html::img(array('src' => $CONFIG['skin_path'] . $attrib['deleteicon'], 'alt' => rcube_label('delete')));
@@ -226,6 +278,7 @@ function rcube_subscription_form($attrib)
foreach ($list_folders as $i => $folder) {
$idx = $i + 1;
$subscribed = in_array($folder['id'], $a_subscribed);
+ $threaded = $a_threaded[$folder['id']];
$protected = ($CONFIG['protect_default_folders'] == true && in_array($folder['id'], $CONFIG['default_imap_folders']));
$classes = array($i%2 ? 'even' : 'odd');
$folder_js = JQ($folder['id']);
@@ -238,9 +291,13 @@ function rcube_subscription_form($attrib)
$table->add_row(array('id' => 'rcmrow'.$idx, 'class' => join(' ', $classes)));
$table->add('name', Q($display_folder));
- $table->add('msgcount', ($folder['virtual'] ? '' : $IMAP->messagecount($folder['id'])));
+ $table->add('msgcount', ($folder['virtual'] ? '' : $IMAP->messagecount($folder['id']))); // XXX: Use THREADS or ALL?
$table->add('subscribed', ($protected || $folder['virtual']) ? ($subscribed ? '&nbsp;&#x2022;' : '&nbsp;') :
$checkbox_subscribe->show(($subscribed ? $folder_utf8 : ''), array('value' => $folder_utf8)));
+ if ($IMAP->get_capability('thread=references')) {
+ $table->add('threaded',
+ $checkbox_threaded->show(($threaded ? $folder_utf8 : ''), array('value' => $folder_utf8)));
+ }
// add rename and delete buttons
if (!$protected && !$folder['virtual']) {
@@ -335,6 +392,27 @@ function rcube_rename_folder_form($attrib)
return $out;
}
+
+// (un)set 'threading' for selected folder
+function rcube_set_threading($mbox, $state=true)
+ {
+ global $RCMAIL;
+ $mbox = (array)$mbox;
+ $a_prefs = (array)$RCMAIL->config->get('message_threading');
+
+ if ($state) {
+ foreach ($mbox as $box)
+ $a_prefs[$box] = true;
+ }
+ else {
+ foreach ($mbox as $box)
+ unset($a_prefs[$box]);
+ }
+
+ $RCMAIL->user->save_prefs(array('message_threading' => $a_prefs));
+ }
+
+
$OUTPUT->set_pagetitle(rcube_label('folders'));
$OUTPUT->include_script('list.js');
diff --git a/program/steps/settings/save_prefs.inc b/program/steps/settings/save_prefs.inc
index eeb64034c..4eebef291 100644
--- a/program/steps/settings/save_prefs.inc
+++ b/program/steps/settings/save_prefs.inc
@@ -32,7 +32,6 @@ switch ($CURR_SECTION)
'timezone' => isset($_POST['_timezone']) ? (is_numeric($_POST['_timezone']) ? floatval($_POST['_timezone']) : get_input_value('_timezone', RCUBE_INPUT_POST)) : $CONFIG['timezone'],
'dst_active' => isset($_POST['_dst_active']) ? TRUE : FALSE,
'pagesize' => is_numeric($_POST['_pagesize']) ? max(2, intval($_POST['_pagesize'])) : $CONFIG['pagesize'],
- 'index_sort' => isset($_POST['_index_sort']) ? TRUE : FALSE,
'prettydate' => isset($_POST['_pretty_date']) ? TRUE : FALSE,
'skin' => isset($_POST['_skin']) ? get_input_value('_skin', RCUBE_INPUT_POST) : $CONFIG['skin'],
);
@@ -42,6 +41,7 @@ switch ($CURR_SECTION)
$a_user_prefs = array(
'focus_on_new_message' => isset($_POST['_focus_on_new_message']) ? TRUE : FALSE,
'preview_pane' => isset($_POST['_preview_pane']) ? TRUE : FALSE,
+ 'autoexpand_threads' => isset($_POST['_autoexpand_threads']) ? intval($_POST['_autoexpand_threads']) : 0,
'mdn_requests' => isset($_POST['_mdn_requests']) ? intval($_POST['_mdn_requests']) : 0,
'keep_alive' => isset($_POST['_keep_alive']) ? intval($_POST['_keep_alive'])*60 : $CONFIG['keep_alive'],
'check_all_folders' => isset($_POST['_check_all_folders']) ? TRUE : FALSE,