- Added message status filter + fixes for r2046 (searching with SORT)

release-0.6
alecpl 16 years ago
parent 6fa87f3fa5
commit e538b3dc7d

@ -4,6 +4,7 @@ CHANGELOG RoundCube Webmail
2008/11/12 (alec)
----------
- Use SORT for searching on servers with SORT capability
- Added message status filter
2008/11/06 (alec)
----------

@ -61,7 +61,6 @@ class rcube_imap
var $msg_headers = array();
var $skip_deleted = FALSE;
var $search_set = NULL;
var $search_subject = '';
var $search_string = '';
var $search_charset = '';
var $search_sort_field = '';
@ -282,18 +281,18 @@ class rcube_imap
/**
* Save a set of message ids for future message listing methods
*
* @param array List of IMAP fields to search in
* @param string Search string
* @param array List of message ids or NULL if empty
* @param string IMAP Search query
* @param array List of message ids or NULL if empty
* @param string Charset of search string
* @param string Sorting field
*/
function set_search_set($subject, $str=null, $msgs=null, $charset=null, $sort_field=null)
function set_search_set($str=null, $msgs=null, $charset=null, $sort_field=null)
{
if (is_array($subject) && $str == null && $msgs == null)
list($subject, $str, $msgs, $charset, $sort_field) = $subject;
if ($msgs == null)
list($str, $msgs, $charset, $sort_field) = $str;
if ($msgs != null && !is_array($msgs))
$msgs = split(',', $msgs);
$this->search_subject = $subject;
$this->search_string = $str;
$this->search_set = (array)$msgs;
$this->search_charset = $charset;
@ -307,7 +306,7 @@ class rcube_imap
*/
function get_search_set()
{
return array($this->search_subject, $this->search_string, $this->search_set, $this->search_charset, $this->search_sort_field);
return array($this->search_string, $this->search_set, $this->search_charset, $this->search_sort_field);
}
@ -654,9 +653,9 @@ class rcube_imap
if ($this->get_capability('sort')) // SORT searching result
{
// reset search set if sorting field has been changed
if ($sort_field && $this->search_sort_field != $sort_field)
if ($this->sort_field && $this->search_sort_field != $this->sort_field)
{
$msgs = $this->search('', $this->search_subject, $this->search_string, $this->search_charset, $sort_field);
$msgs = $this->search('', $this->search_string, $this->search_charset, $this->sort_field);
}
// return empty array if no messages found
@ -783,7 +782,7 @@ class rcube_imap
/**
* Return sorted array of message UIDs
* Return sorted array of message IDs (not UIDs)
*
* @param string Mailbox to get index from
* @param string Sort column
@ -801,10 +800,25 @@ class rcube_imap
if (!isset($this->cache[$key]) && $this->search_string && $mailbox == $this->mailbox)
{
$this->cache[$key] = $a_msg_headers = array();
$this->_fetch_headers($mailbox, join(',', $this->search_set), $a_msg_headers, NULL);
if ($this->get_capability('sort'))
{
if ($this->sort_field && $this->search_sort_field != $this->sort_field)
$this->search('', $this->search_string, $this->search_charset, $this->sort_field);
if ($this->sort_order == 'DESC')
$this->cache[$key] = array_reverse($this->search_set);
else
$this->cache[$key] = $this->search_set;
}
else
{
// TODO: see list_header_set (fetch only one header field needed for sorting)
$this->_fetch_headers($mailbox, join(',', $this->search_set), $a_msg_headers, NULL);
foreach (iil_SortHeaders($a_msg_headers, $this->sort_field, $this->sort_order) as $i => $msg)
$this->cache[$key][] = $msg->uid;
foreach (iil_SortHeaders($a_msg_headers, $this->sort_field, $this->sort_order) as $i => $msg)
$this->cache[$key][] = $msg->id;
}
}
// have stored it in RAM
@ -825,28 +839,23 @@ class rcube_imap
// fetch complete message index
$msg_count = $this->_messagecount($mailbox);
if ($this->get_capability('sort') && ($a_index = iil_C_Sort($this->conn, $mailbox, $this->sort_field, '', TRUE)))
if ($this->get_capability('sort') && ($a_index = iil_C_Sort($this->conn, $mailbox, $this->sort_field, '')))
{
if ($this->sort_order == 'DESC')
$a_index = array_reverse($a_index);
$this->cache[$key] = $a_index;
}
else
{
$a_index = iil_C_FetchHeaderIndex($this->conn, $mailbox, "1:$msg_count", $this->sort_field);
$a_uids = iil_C_FetchUIDs($this->conn, $mailbox);
if ($this->sort_order=="ASC")
asort($a_index);
else if ($this->sort_order=="DESC")
arsort($a_index);
$i = 0;
$this->cache[$key] = array();
foreach ($a_index as $index => $value)
$this->cache[$key][$i++] = $a_uids[$index];
$this->cache[$key] = $a_index;
}
return $this->cache[$key];
@ -906,39 +915,46 @@ class rcube_imap
* Invoke search request to IMAP server
*
* @param string mailbox name to search in
* @param string search criteria (ALL, TO, FROM, SUBJECT, etc)
* @param string search string
* @param string search string charset
* @param string header field to sort by
* @return array search results as list of message ids
* @access public
*/
function search($mbox_name='', $criteria='ALL', $str=NULL, $charset=NULL, $sort_field=NULL)
function search($mbox_name='', $str=NULL, $charset=NULL, $sort_field=NULL)
{
$mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $this->mailbox;
$search = '';
// have an array of criterias => create search string
if (is_array($criteria) && count($criteria) > 1)
$search .= 'OR';
$criteria = (array) $criteria;
foreach($criteria as $idx => $crit)
if ($str)
$search .= sprintf(" (%s {%d}\r\n%s)", $crit, strlen($str), $str);
else
$search .= '('. $crit .')';
$results = $this->_search_index($mailbox, $search, $charset, $sort_field);
$results = $this->_search_index($mailbox, $str, $charset, $sort_field);
// try search with ISO charset (should be supported by server)
if (empty($results) && !empty($charset) && $charset!='ISO-8859-1')
$results = $this->search($mbox_name, $criteria, rcube_charset_convert($str, $charset, 'ISO-8859-1'), 'ISO-8859-1', $sort_field);
{
// convert strings to ISO-8859-1
if(preg_match_all('/\{([0-9]+)\}\r\n/', $str, $matches, PREG_OFFSET_CAPTURE))
{
$last = 0; $res = '';
foreach($matches[1] as $m)
{
$string_offset = $m[1] + strlen($m[0]) + 4; // {}\r\n
$string = substr($str, $string_offset - 1, $m[0]);
$string = rcube_charset_convert($string, $charset, 'ISO-8859-1');
$res .= sprintf("%s{%d}\r\n%s", substr($str, $last, $m[1] - $last - 1), strlen($string), $string);
$last = $m[0] + $string_offset - 1;
}
if ($last < strlen($str))
$res .= substr($str, $last, strlen($str)-$last);
}
else // strings for conversion not found
$res = $str;
$results = $this->search($mbox_name, $res, 'ISO-8859-1', $sort_field);
}
$this->set_search_set($criteria, $str, $results, $charset, $sort_field);
$this->set_search_set($str, $results, $charset, $sort_field);
return $results;
}
}
/**
@ -974,8 +990,8 @@ class rcube_imap
*/
function refresh_search()
{
if (!empty($this->search_subject) && !empty($this->search_string))
$this->search_set = $this->search('', $this->search_subject, $this->search_string, $this->search_charset, $this->search_sort_field);
if (!empty($this->search_string))
$this->search_set = $this->search('', $this->search_string, $this->search_charset, $this->search_sort_field);
return $this->get_search_set();
}

@ -266,7 +266,7 @@ function rcube_webmail()
this.set_page_buttons();
if (this.env.address_sources && !this.env.address_sources[this.env.source].readonly)
if (this.env.address_sources && this.env.address_sources[this.env.source] && !this.env.address_sources[this.env.source].readonly)
this.enable_command('add', true);
if (this.env.cid)
@ -1414,6 +1414,24 @@ function rcube_webmail()
}
};
// list messages of a specific mailbox using filter
this.filter_mailbox = function(filter)
{
var search;
if (this.gui_objects.qsearchbox)
search = this.gui_objects.qsearchbox.value;
this.message_list.clear();
// reset vars
this.env.current_page = 1;
this.set_busy(true, 'searching');
this.http_request('search', '_filter='+filter
+ (search ? '&_q='+urlencode(search) : '')
+ (this.env.mailbox ? '&_mbox='+urlencode(this.env.mailbox) : ''), true);
}
// list messages of a specific mailbox
this.list_mailbox = function(mbox, page, sort)
{
@ -2283,7 +2301,7 @@ function rcube_webmail()
};
// send remote request to search mail or contacts
this.qsearch = function(value)
this.qsearch = function(value, addurl)
{
if (value != '')
{
@ -2292,12 +2310,18 @@ function rcube_webmail()
else if (this.contact_list) {
this.contact_list.clear(true);
this.show_contentframe(false);
}
}
if (this.gui_objects.search_filter)
addurl = '&_filter=' + this.gui_objects.search_filter.value;
// reset vars
this.env.current_page = 1;
this.set_busy(true, 'searching');
this.http_request('search', '_q='+urlencode(value)+(this.env.mailbox ? '&_mbox='+urlencode(this.env.mailbox) : '')+(this.env.source ? '&_source='+urlencode(this.env.source) : ''), true);
this.http_request('search', '_q='+urlencode(value)
+(this.env.mailbox ? '&_mbox='+urlencode(this.env.mailbox) : '')
+(this.env.source ? '&_source='+urlencode(this.env.source) : '')
+(addurl ? addurl : ''), true);
}
return true;
};

@ -1292,6 +1292,36 @@ function rcmail_send_mdn($uid)
}
function rcmail_search_filter($attrib)
{
global $OUTPUT;
if (!strlen($attrib['id']))
$attrib['id'] = 'rcmlistfilter';
$attrib['onchange'] = JS_OBJECT_NAME.'.filter_mailbox(this.value)';
/*
RFC3501 (6.4.4): 'ALL', 'RECENT',
'ANSWERED', 'DELETED', 'FLAGGED', 'SEEN',
'UNANSWERED', 'UNDELETED', 'UNFLAGGED', 'UNSEEN',
'NEW', // = (RECENT UNSEEN)
'OLD' // = NOT RECENT
*/
$select_filter = new html_select($attrib);
$select_filter->add(rcube_label('all'), 'ALL');
$select_filter->add(rcube_label('unread'), 'UNSEEN');
$select_filter->add(rcube_label('flagged'), 'FLAGGED');
$select_filter->add(rcube_label('unanswered'), 'UNANSWERED');
$out = $select_filter->show($_SESSION['search_filter']);
$OUTPUT->add_gui_object('search_filter', $attrib['id']);
return $out;
}
// register UI objects
$OUTPUT->add_handlers(array(
'mailboxlist' => 'rcmail_mailbox_list',
@ -1304,6 +1334,7 @@ $OUTPUT->add_handlers(array(
'messagecontentframe' => 'rcmail_messagecontent_frame',
'messagepartframe' => 'rcmail_message_part_frame',
'messagepartcontrols' => 'rcmail_message_part_controls',
'searchfilter' => 'rcmail_search_filter',
'searchform' => array($OUTPUT, 'search_form'),
));

@ -41,6 +41,17 @@ else
$mbox_name = $IMAP->get_mailbox_name();
// initialize searching result if search_filter is used
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, $sort_col);
$_SESSION['search'][$search_request] = $IMAP->get_search_set();
$OUTPUT->set_env('search_request', $search_request);
}
// fetch message headers
if ($IMAP->messagecount($mbox_name, 'ALL', !empty($_REQUEST['_refresh'])))
$a_headers = $IMAP->list_headers($mbox_name, NULL, $sort_col, $sort_order);
@ -55,8 +66,6 @@ $OUTPUT->set_env('pagecount', $pages);
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count));
$OUTPUT->command('set_mailboxname', rcmail_get_mailbox_name_text());
// add message rows
if (isset($a_headers) && count($a_headers))
rcmail_js_message_list($a_headers);

@ -26,51 +26,66 @@ $imap_charset = 'UTF-8';
// get search string
$str = get_input_value('_q', RCUBE_INPUT_GET);
$filter = get_input_value('_filter', RCUBE_INPUT_GET);
$mbox = get_input_value('_mbox', RCUBE_INPUT_GET);
$search_request = md5($mbox.$str);
$search_request = md5($mbox.$filter.$str);
// add list filter string
$search_str = $filter && $filter != 'ALL' ? $filter : '';
$_SESSION['search_filter'] = $filter;
// Check the search string for type of search
if (preg_match("/^from:/i", $str))
if (preg_match("/^from:.*/i", $str))
{
list(,$srch) = explode(":", $str);
$subject = "HEADER FROM";
$subject = "HEADER FROM";
$search = trim($srch);
}
else if (preg_match("/^to:/i", $str))
else if (preg_match("/^to.*:/i", $str))
{
list(,$srch) = explode(":", $str);
$subject = "HEADER TO";
$search = trim($srch);
}
else if (preg_match("/^cc:/i", $str))
else if (preg_match("/^cc:.*/i", $str))
{
list(,$srch) = explode(":", $str);
$subject = "HEADER CC";
$search = trim($srch);
}
else if (preg_match("/^subject:/i", $str))
else if (preg_match("/^subject:.*/i", $str))
{
list(,$srch) = explode(":", $str);
$subject = "HEADER SUBJECT";
$search = trim($srch);
}
else if (preg_match("/^body:/i", $str))
else if (preg_match("/^body:.*/i", $str))
{
list(,$srch) = explode(":", $str);
$subject = "TEXT";
$search = trim($srch);
}
// search in subject and sender by default
else
else if(trim($str))
{
$from = ($mbox == $CONFIG['sent_mbox'] || $mbox == $CONFIG['drafts_mbox']) ? "TO" : "FROM";
$subject = array("HEADER SUBJECT", "HEADER $from");
$search = trim($str);
}
if ($subject && !is_array($subject))
$search_str .= sprintf(" %s {%d}\r\n%s", $subject, strlen($search), $search);
else if ($subject) {
$search_str .= ' OR';
foreach($subject as $sub)
$search_str .= sprintf(" (%s {%d}\r\n%s)", $sub, strlen($search), $search);
}
$search_str = trim($search_str);
// execute IMAP search
$result = $IMAP->search($mbox, $subject, $search, $imap_charset, $_SESSION['sort_col']);
$result = $IMAP->search($mbox, $search_str, $imap_charset, $_SESSION['sort_col']);
$count = 0;
// Make sure our $result is legit..

@ -110,12 +110,13 @@ if ($_GET['_uid']) {
{
// Only if we use custom sorting
$a_msg_index = $IMAP->message_index(NULL, $_SESSION['sort_col'], $_SESSION['sort_order']);
$MESSAGE->index = array_search((string)$MESSAGE->uid, $a_msg_index, TRUE);
$prev = isset($a_msg_index[$MESSAGE->index-1]) ? $a_msg_index[$MESSAGE->index-1] : -1 ;
$first = count($a_msg_index)>0 ? $a_msg_index[0] : -1;
$next = isset($a_msg_index[$MESSAGE->index+1]) ? $a_msg_index[$MESSAGE->index+1] : -1 ;
$last = count($a_msg_index)>0 ? $a_msg_index[count($a_msg_index)-1] : -1;
$MESSAGE->index = array_search($IMAP->get_id($MESSAGE->uid), $a_msg_index);
$prev = isset($a_msg_index[$MESSAGE->index-1]) ? $IMAP->get_uid($a_msg_index[$MESSAGE->index-1]) : -1 ;
$first = count($a_msg_index)>0 ? $IMAP->get_uid($a_msg_index[0]) : -1;
$next = isset($a_msg_index[$MESSAGE->index+1]) ? $IMAP->get_uid($a_msg_index[$MESSAGE->index+1]) : -1 ;
$last = count($a_msg_index)>0 ? $IMAP->get_uid($a_msg_index[count($a_msg_index)-1]) : -1;
}
else
{
@ -130,11 +131,11 @@ if ($_GET['_uid']) {
if ($prev > 0)
$OUTPUT->set_env('prev_uid', $prev);
if ($first >0)
if ($first > 0)
$OUTPUT->set_env('first_uid', $first);
if ($next > 0)
$OUTPUT->set_env('next_uid', $next);
if ($last >0)
if ($last > 0)
$OUTPUT->set_env('last_uid', $last);
// mark message as read

@ -328,7 +328,7 @@ table.records-table tr.unfocused td
#quicksearchbar
{
position: absolute;
top: 60px;
top: 55px;
right: 20px;
width: 182px;
height: 20px;

@ -4,7 +4,7 @@
#messagetoolbar
{
position: absolute;
top: 45px;
top: 47px;
left: 200px;
right: 200px;
height: 35px;
@ -24,11 +24,17 @@
color: #333333;
}
#messagetoolbar select.searchfilter
{
position: relative;
bottom: 10px;
}
#messagetoolbar select.mboxlist
{
position: absolute;
left: 375px;
top: 10px;
top: 8px;
}
#messagetoolbar select.mboxlist option

@ -118,6 +118,7 @@
<roundcube:button command="forward" imageSel="/images/buttons/forward_sel.png" imageAct="/images/buttons/forward_act.png" imagePas="/images/buttons/forward_pas.png" width="32" height="32" title="forwardmessage" />
<roundcube:button command="delete" imageSel="/images/buttons/delete_sel.png" imageAct="/images/buttons/delete_act.png" imagePas="/images/buttons/delete_pas.png" width="32" height="32" title="deletemessage" />
<roundcube:button command="print" imageSel="/images/buttons/print_sel.png" imageAct="/images/buttons/print_act.png" imagePas="/images/buttons/print_pas.png" width="32" height="32" title="printmessage" />
<roundcube:object name="searchfilter" id="searchfilter" class="searchfilter" />
<div id="markmessagemenu">
<ul class="toolbarmenu">

Loading…
Cancel
Save