Browse Source

Fix mail search error on invalid search_mods definition (#7789)

pull/7824/head
Aleksander Machniak 5 years ago
parent
commit
837078cd23
  1. 1
      CHANGELOG
  2. 3
      config/defaults.inc.php
  3. 47
      program/actions/mail/search.php
  4. 37
      tests/Actions/Mail/Search.php

1
CHANGELOG

@ -71,6 +71,7 @@ CHANGELOG Roundcube Webmail
- Password: Added 'pwned' password strength driver (#7274) - Password: Added 'pwned' password strength driver (#7274)
- Password: Removed old 'cpanel' driver, 'cpanel_webmail' driver renamed to 'cpanel' (#7780) - Password: Removed old 'cpanel' driver, 'cpanel_webmail' driver renamed to 'cpanel' (#7780)
- Fix bug where it wasn't possible to save Spanish (Latin America) locale preference (#7784) - Fix bug where it wasn't possible to save Spanish (Latin America) locale preference (#7784)
- Fix mail search error on invalid search_mods definition (#7789)
- Fix error when dealing with message/rfc822 attachments using Gmail IMAP (#6854) - Fix error when dealing with message/rfc822 attachments using Gmail IMAP (#6854)
- Fix ISO-2022-JP-MS encoding issues (#7091) - Fix ISO-2022-JP-MS encoding issues (#7091)
- Fix so messages in threads with no root aren't displayed separately (#4999) - Fix so messages in threads with no root aren't displayed separately (#4999)

3
config/defaults.inc.php

@ -1352,9 +1352,10 @@ $config['sig_separator'] = true;
// Use MIME encoding (quoted-printable) for 8bit characters in message body // Use MIME encoding (quoted-printable) for 8bit characters in message body
$config['force_7bit'] = false; $config['force_7bit'] = false;
// Defaults of the search field configuration.
// Default fields configuration for mail search.
// The array can contain a per-folder list of header fields which should be considered when searching // The array can contain a per-folder list of header fields which should be considered when searching
// The entry with key '*' stands for all folders which do not have a specific list set. // The entry with key '*' stands for all folders which do not have a specific list set.
// Supported fields: subject, from, to, cc, bcc, body, text.
// Please note that folder names should to be in sync with $config['*_mbox'] options // Please note that folder names should to be in sync with $config['*_mbox'] options
$config['search_mods'] = null; // Example: ['*' => ['subject'=>1, 'from'=>1], 'Sent' => ['subject'=>1, 'to'=>1]]; $config['search_mods'] = null; // Example: ['*' => ['subject'=>1, 'from'=>1], 'Sent' => ['subject'=>1, 'to'=>1]];

47
program/actions/mail/search.php

@ -51,9 +51,7 @@ class rcmail_action_mail_search extends rcmail_action_mail_index
$search_request = md5($mbox . $scope . $interval . $filter . $str); $search_request = md5($mbox . $scope . $interval . $filter . $str);
// Parse input // Parse input
list($subject, $srch) = self::search_input($str, $headers, $scope, $mbox);
$search = isset($srch) ? trim($srch) : trim($str);
list($subject, $search) = self::search_input($str, $headers, $scope, $mbox);
// add list filter string // add list filter string
$search_str = $filter && $filter != 'ALL' ? $filter : ''; $search_str = $filter && $filter != 'ALL' ? $filter : '';
@ -213,11 +211,22 @@ class rcmail_action_mail_search extends rcmail_action_mail_index
return $search . ' ' . $date->format('j-M-Y'); return $search . ' ' . $date->format('j-M-Y');
} }
/**
* Parse search input.
*
* @param string $str Search string
* @param string $headers Comma-separated list of headers/fields to search in
* @param string $scope Search scope (all | base | sub)
* @param string $mbox Folder name
*
* @return array Search criteria (1st element) and search value (2nd element)
*/
public static function search_input($str, $headers, $scope, $mbox) public static function search_input($str, $headers, $scope, $mbox)
{ {
$rcmail = rcmail::get_instance();
$subject = [];
$srch = null;
$rcmail = rcmail::get_instance();
$subject = [];
$srch = null;
$supported = ['subject', 'from', 'to', 'cc', 'bcc'];
// Check the search string for type of search // Check the search string for type of search
if (preg_match("/^from:.*/i", $str)) { if (preg_match("/^from:.*/i", $str)) {
@ -247,22 +256,30 @@ class rcmail_action_mail_search extends rcmail_action_mail_index
else if (strlen(trim($str))) { else if (strlen(trim($str))) {
if ($headers) { if ($headers) {
foreach (explode(',', $headers) as $header) { foreach (explode(',', $headers) as $header) {
if ($header == 'text') {
switch ($header) {
case 'text':
// #1488208: get rid of other headers when searching by "TEXT" // #1488208: get rid of other headers when searching by "TEXT"
$subject = ['text' => 'TEXT']; $subject = ['text' => 'TEXT'];
break 2;
case 'body':
$subject['body'] = 'BODY';
break; break;
}
else {
$subject[$header] = ($header != 'body' ? 'HEADER ' : '') . strtoupper($header);
default:
if (in_array_nocase($header, $supported)) {
$subject[$header] = 'HEADER ' . strtoupper($header);
}
} }
} }
// save search modifiers for the current folder to user prefs // save search modifiers for the current folder to user prefs
$mkey = $scope == 'all' ? '*' : $mbox;
$search_mods = self::search_mods();
$search_mods[$mkey] = array_fill_keys(array_keys($subject), 1);
$mkey = $scope == 'all' ? '*' : $mbox;
$search_mods = self::search_mods();
$search_mods_value = array_fill_keys(array_keys($subject), 1);
$rcmail->user->save_prefs(['search_mods' => $search_mods]);
if (!isset($search_mods[$mkey]) || $search_mods[$mkey] != $search_mods_value) {
$search_mods[$mkey] = $search_mods_value;
$rcmail->user->save_prefs(['search_mods' => $search_mods]);
}
} }
else { else {
// search in subject by default // search in subject by default
@ -270,6 +287,6 @@ class rcmail_action_mail_search extends rcmail_action_mail_index
} }
} }
return [$subject, $srch];
return [$subject, isset($srch) ? trim($srch) : trim($str)];
} }
} }

37
tests/Actions/Mail/Search.php

@ -7,16 +7,6 @@
*/ */
class Actions_Mail_Search extends ActionTestCase class Actions_Mail_Search extends ActionTestCase
{ {
/**
* Class constructor
*/
function test_class()
{
$object = new rcmail_action_mail_search;
$this->assertInstanceOf('rcmail_action', $object);
}
/** /**
* Test searching mail (empty result) * Test searching mail (empty result)
*/ */
@ -76,7 +66,32 @@ class Actions_Mail_Search extends ActionTestCase
*/ */
function test_search_input() function test_search_input()
{ {
$this->markTestIncomplete();
$output = $this->initOutput(rcmail_action::MODE_AJAX, 'mail', 'search');
$result = rcmail_action_mail_search::search_input('', 'subject,from', 'base', 'INBOX');
$this->assertSame([], $result[0]);
$this->assertSame('', $result[1]);
$result = rcmail_action_mail_search::search_input('test', 'subject,from', 'base', 'INBOX');
$this->assertSame(['subject' => 'HEADER SUBJECT', 'from' => 'HEADER FROM'], $result[0]);
$this->assertSame('test', $result[1]);
$result = rcmail_action_mail_search::search_input('test', null, 'base', 'INBOX');
$this->assertSame(['subject' => 'HEADER SUBJECT'], $result[0]);
$this->assertSame('test', $result[1]);
$result = rcmail_action_mail_search::search_input('body:test', 'subject,from', 'base', 'INBOX');
$this->assertSame(['body' => 'BODY'], $result[0]);
$this->assertSame('test', $result[1]);
$result = rcmail_action_mail_search::search_input('test', 'from,invalid entry', 'base', 'INBOX');
$this->assertSame(['from' => 'HEADER FROM'], $result[0]);
$this->assertSame('test', $result[1]);
} }
/** /**

Loading…
Cancel
Save