From a04a74fec4b5e13e8464f1f3c9071fa0b56a13eb Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Wed, 12 Sep 2012 09:59:10 +0200 Subject: Improvements in building criteria string for IMAP SEARCH --- program/include/rcube_imap.php | 8 +++++++- program/include/rcube_shared.inc | 15 +++++++++++++++ program/steps/mail/search.inc | 2 +- tests/Framework/Shared.php | 28 ++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php index 66b5c4bd6..0b2f84d4f 100644 --- a/program/include/rcube_imap.php +++ b/program/include/rcube_imap.php @@ -1434,6 +1434,12 @@ class rcube_imap extends rcube_storage $criteria = 'UNDELETED '.$criteria; } + // unset CHARSET if criteria string is ASCII, this way + // SEARCH won't be re-sent after "unsupported charset" response + if ($charset && $charset != 'US-ASCII' && is_ascii($criteria)) { + $charset = 'US-ASCII'; + } + if ($this->threading) { $threads = $this->conn->thread($folder, $this->threading, $criteria, true, $charset); @@ -1465,7 +1471,7 @@ class rcube_imap extends rcube_storage } $messages = $this->conn->search($folder, - ($charset ? "CHARSET $charset " : '') . $criteria, true); + ($charset && $charset != 'US-ASCII' ? "CHARSET $charset " : '') . $criteria, true); // Error, try with US-ASCII (some servers may support only US-ASCII) if ($messages->is_error() && $charset && $charset != 'US-ASCII') { diff --git a/program/include/rcube_shared.inc b/program/include/rcube_shared.inc index c15305c08..4577c6df5 100644 --- a/program/include/rcube_shared.inc +++ b/program/include/rcube_shared.inc @@ -254,6 +254,21 @@ function asciiwords($str, $css_id = false, $replace_with = '') } +/** + * Check if a string contains only ascii characters + * + * @param string $str String to check + * @param bool $control_chars Includes control characters + * + * @return bool + */ +function is_ascii($str, $control_chars = true) +{ + $regexp = $control_chars ? '/[^\x00-\x7F]/' : '/[^\x20-\x7E]/'; + return preg_match($regexp, $str) ? false : true; +} + + /** * Remove single and double quotes from a given string * diff --git a/program/steps/mail/search.inc b/program/steps/mail/search.inc index 670680959..db5424b3b 100644 --- a/program/steps/mail/search.inc +++ b/program/steps/mail/search.inc @@ -100,7 +100,7 @@ $search = isset($srch) ? trim($srch) : trim($str); if (!empty($subject)) { $search_str .= str_repeat(' OR', count($subject)-1); foreach ($subject as $sub) - $search_str .= sprintf(" %s {%d}\r\n%s", $sub, strlen($search), $search); + $search_str .= ' ' . $sub . ' ' . rcube_imap_generic::escape($search); } $search_str = trim($search_str); diff --git a/tests/Framework/Shared.php b/tests/Framework/Shared.php index 99ef829da..0394cd025 100644 --- a/tests/Framework/Shared.php +++ b/tests/Framework/Shared.php @@ -201,4 +201,32 @@ class Framework_Shared extends PHPUnit_Framework_TestCase } + /** + * rcube_shared.inc: is_ascii() + */ + function test_is_ascii() + { + $result = is_ascii("0123456789"); + $this->assertTrue($result, "Valid ASCII (numbers)"); + + $result = is_ascii("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); + $this->assertTrue($result, "Valid ASCII (letters)"); + + $result = is_ascii(" !\"#\$%&'()*+,-./:;<=>?@[\\^_`{|}~"); + $this->assertTrue($result, "Valid ASCII (special characters)"); + + $result = is_ascii("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + ."\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"); + $this->assertTrue($result, "Valid ASCII (control characters)"); + + $result = is_ascii("\n", false); + $this->assertFalse($result, "Valid ASCII (control characters)"); + + $result = is_ascii("ż"); + $this->assertFalse($result, "Invalid ASCII (UTF-8 character)"); + + $result = is_ascii("ż", false); + $this->assertFalse($result, "Invalid ASCII (UTF-8 character [2])"); + } + } -- cgit v1.2.3