summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Machniak <alec@alec.pl>2012-09-19 08:02:25 (GMT)
committerAleksander Machniak <alec@alec.pl>2012-09-19 08:02:25 (GMT)
commit91bea80c1841479b9d492fa94017a1d76e8ddb5d (patch)
tree6124880dbe6fbe09aecd23b4f13318b219a345ba
parent540de2286720de3e30e48dad45884eb88eee2e23 (diff)
downloadkolab-syncroton-91bea80c1841479b9d492fa94017a1d76e8ddb5d.tar.gz
Update Roundcube Framework
-rw-r--r--lib/ext/Roundcube/rcube_addressbook.php2
-rw-r--r--lib/ext/Roundcube/rcube_charset.php31
-rw-r--r--lib/ext/Roundcube/rcube_config.php1
-rw-r--r--lib/ext/Roundcube/rcube_db.php18
-rw-r--r--lib/ext/Roundcube/rcube_imap.php19
-rw-r--r--lib/ext/Roundcube/rcube_imap_cache.php52
-rw-r--r--lib/ext/Roundcube/rcube_imap_generic.php22
-rw-r--r--lib/ext/Roundcube/rcube_message.php33
-rw-r--r--lib/ext/Roundcube/rcube_mime.php4
-rw-r--r--lib/ext/Roundcube/rcube_output_html.php31
-rw-r--r--lib/ext/Roundcube/rcube_result_index.php4
-rw-r--r--lib/ext/Roundcube/rcube_result_thread.php2
-rw-r--r--lib/ext/Roundcube/rcube_shared.inc25
-rw-r--r--lib/ext/Roundcube/rcube_storage.php2
-rw-r--r--lib/ext/Roundcube/rcube_utils.php60
-rw-r--r--lib/ext/Roundcube/rcube_vcard.php3
16 files changed, 241 insertions, 68 deletions
diff --git a/lib/ext/Roundcube/rcube_addressbook.php b/lib/ext/Roundcube/rcube_addressbook.php
index 069ea57..f4f2553 100644
--- a/lib/ext/Roundcube/rcube_addressbook.php
+++ b/lib/ext/Roundcube/rcube_addressbook.php
@@ -465,7 +465,7 @@ abstract class rcube_addressbook
$fn = $contact['name'];
if (!$fn) // default display name composition according to vcard standard
- $fn = join(' ', array_filter(array($contact['prefix'], $contact['firstname'], $contact['middlename'], $contact['surname'], $contact['suffix'])));
+ $fn = trim(join(' ', array_filter(array($contact['prefix'], $contact['firstname'], $contact['middlename'], $contact['surname'], $contact['suffix']))));
// use email address part for name
$email = is_array($contact['email']) ? $contact['email'][0] : $contact['email'];
diff --git a/lib/ext/Roundcube/rcube_charset.php b/lib/ext/Roundcube/rcube_charset.php
index 380d149..35c6972 100644
--- a/lib/ext/Roundcube/rcube_charset.php
+++ b/lib/ext/Roundcube/rcube_charset.php
@@ -86,7 +86,7 @@ class rcube_charset
* Sometimes charset string is malformed, there are also charset aliases
* but we need strict names for charset conversion (specially utf8 class)
*
- * @param string Input charset name
+ * @param string $input Input charset name
*
* @return string The validated charset name
*/
@@ -176,11 +176,18 @@ class rcube_charset
{
static $iconv_options = null;
static $mbstring_list = null;
+ static $mbstring_sch = null;
static $conv = null;
- $to = empty($to) ? strtoupper(RCMAIL_CHARSET) : self::parse_charset($to);
+ $to = empty($to) ? strtoupper(RCMAIL_CHARSET) : $to;
$from = self::parse_charset($from);
+ // It is a common case when UTF-16 charset is used with US-ASCII content (#1488654)
+ // In that case we can just skip the conversion (use UTF-8)
+ if ($from == 'UTF-16' && !preg_match('/[^\x00-\x7F]/', $str)) {
+ $from = 'UTF-8';
+ }
+
if ($from == $to || empty($str) || empty($from)) {
return $str;
}
@@ -215,6 +222,7 @@ class rcube_charset
if ($mbstring_list === null) {
if (extension_loaded('mbstring')) {
+ $mbstring_sch = mb_substitute_character();
$mbstring_list = mb_list_encodings();
$mbstring_list = array_map('strtoupper', $mbstring_list);
}
@@ -223,14 +231,25 @@ class rcube_charset
// convert charset using mbstring module
if ($mbstring_list !== null) {
$aliases['WINDOWS-1257'] = 'ISO-8859-13';
+ // it happens that mbstring supports ASCII but not US-ASCII
+ if (($from == 'US-ASCII' || $to == 'US-ASCII') && !in_array('US-ASCII', $mbstring_list)) {
+ $aliases['US-ASCII'] = 'ASCII';
+ }
$mb_from = $aliases[$from] ? $aliases[$from] : $from;
$mb_to = $aliases[$to] ? $aliases[$to] : $to;
// return if encoding found, string matches encoding and convert succeeded
if (in_array($mb_from, $mbstring_list) && in_array($mb_to, $mbstring_list)) {
- if (mb_check_encoding($str, $mb_from) && ($out = mb_convert_encoding($str, $mb_to, $mb_from))) {
- return $out;
+ if (mb_check_encoding($str, $mb_from)) {
+ // Do the same as //IGNORE with iconv
+ mb_substitute_character('none');
+ $out = mb_convert_encoding($str, $mb_to, $mb_from);
+ mb_substitute_character($mbstring_sch);
+
+ if ($out !== false) {
+ return $out;
+ }
}
}
}
@@ -640,14 +659,14 @@ class rcube_charset
return $failover;
}
- // FIXME: the order is important, because sometimes
+ // FIXME: the order is important, because sometimes
// iso string is detected as euc-jp and etc.
$enc = array(
'UTF-8', 'SJIS', 'BIG5', 'GB2312',
'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4',
'ISO-8859-5', 'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8', 'ISO-8859-9',
'ISO-8859-10', 'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'ISO-8859-16',
- 'WINDOWS-1252', 'WINDOWS-1251', 'EUC-JP', 'EUC-TW', 'KOI8-R',
+ 'WINDOWS-1252', 'WINDOWS-1251', 'EUC-JP', 'EUC-TW', 'KOI8-R',
'ISO-2022-KR', 'ISO-2022-JP'
);
diff --git a/lib/ext/Roundcube/rcube_config.php b/lib/ext/Roundcube/rcube_config.php
index e299790..41acc80 100644
--- a/lib/ext/Roundcube/rcube_config.php
+++ b/lib/ext/Roundcube/rcube_config.php
@@ -42,6 +42,7 @@ class rcube_config
'default_folders' => 'default_imap_folders',
'mail_pagesize' => 'pagesize',
'addressbook_pagesize' => 'pagesize',
+ 'reply_mode' => 'top_posting',
);
diff --git a/lib/ext/Roundcube/rcube_db.php b/lib/ext/Roundcube/rcube_db.php
index f97d70a..eb1ad31 100644
--- a/lib/ext/Roundcube/rcube_db.php
+++ b/lib/ext/Roundcube/rcube_db.php
@@ -388,13 +388,19 @@ class rcube_db
$idx = 0;
while ($pos = strpos($query, '?', $pos)) {
- $val = $this->quote($params[$idx++]);
- unset($params[$idx-1]);
- $query = substr_replace($query, $val, $pos, 1);
- $pos += strlen($val);
+ if ($query[$pos+1] == '?') { // skip escaped ?
+ $pos += 2;
+ }
+ else {
+ $val = $this->quote($params[$idx++]);
+ unset($params[$idx-1]);
+ $query = substr_replace($query, $val, $pos, 1);
+ $pos += strlen($val);
+ }
}
- $query = rtrim($query, ';');
+ // replace escaped ? back to normal
+ $query = rtrim(strtr($query, array('??' => '?')), ';');
$this->debug($query);
@@ -591,7 +597,7 @@ class rcube_db
'integer' => PDO::PARAM_INT,
);
$type = isset($map[$type]) ? $map[$type] : PDO::PARAM_STR;
- return $this->dbh->quote($input, $type);
+ return strtr($this->dbh->quote($input, $type), array('?' => '??')); // escape ?
}
return 'NULL';
diff --git a/lib/ext/Roundcube/rcube_imap.php b/lib/ext/Roundcube/rcube_imap.php
index 5dd9c12..ebf31d5 100644
--- a/lib/ext/Roundcube/rcube_imap.php
+++ b/lib/ext/Roundcube/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') {
@@ -2222,6 +2228,10 @@ class rcube_imap extends rcube_storage
$folder = $this->folder;
}
+ if (!$this->check_connection()) {
+ return false;
+ }
+
// make sure folder exists
if ($this->folder_exists($folder)) {
if ($is_file) {
@@ -3287,11 +3297,8 @@ class rcube_imap extends rcube_storage
}
// Get folder rights (MYRIGHTS)
- if ($acl && !$options['noselect']) {
- // skip shared roots
- if (!$options['is_root'] || $options['namespace'] == 'personal') {
- $options['rights'] = (array)$this->my_rights($folder);
- }
+ if ($acl && ($rights = $this->my_rights($folder))) {
+ $options['rights'] = $rights;
}
// Set 'norename' flag
diff --git a/lib/ext/Roundcube/rcube_imap_cache.php b/lib/ext/Roundcube/rcube_imap_cache.php
index a061a1f..f36ace0 100644
--- a/lib/ext/Roundcube/rcube_imap_cache.php
+++ b/lib/ext/Roundcube/rcube_imap_cache.php
@@ -5,7 +5,7 @@
| program/include/rcube_imap_cache.php |
| |
| This file is part of the Roundcube Webmail client |
- | Copyright (C) 2005-2011, The Roundcube Dev Team |
+ | Copyright (C) 2005-2012, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
@@ -350,11 +350,11 @@ class rcube_imap_cache
function get_message($mailbox, $uid, $update = true, $cache = true)
{
// Check internal cache
- if ($this->icache['message']
- && $this->icache['message']['mailbox'] == $mailbox
- && $this->icache['message']['object']->uid == $uid
+ if ($this->icache['__message']
+ && $this->icache['__message']['mailbox'] == $mailbox
+ && $this->icache['__message']['object']->uid == $uid
) {
- return $this->icache['message']['object'];
+ return $this->icache['__message']['object'];
}
$sql_result = $this->db->query(
@@ -386,7 +386,7 @@ class rcube_imap_cache
// Save current message from internal cache
$this->save_icache();
- $this->icache['message'] = array(
+ $this->icache['__message'] = array(
'object' => $message,
'mailbox' => $mailbox,
'exists' => $found,
@@ -459,20 +459,28 @@ class rcube_imap_cache
*/
function change_flag($mailbox, $uids, $flag, $enabled = false)
{
+ if (empty($uids)) {
+ return;
+ }
+
$flag = strtoupper($flag);
$idx = (int) array_search($flag, $this->flags);
+ $uids = (array) $uids;
if (!$idx) {
return;
}
// Internal cache update
- if ($uids && count($uids) == 1 && ($uid = current($uids))
- && ($message = $this->icache['message'])
- && $message['mailbox'] == $mailbox && $message['object']->uid == $uid
+ if (($message = $this->icache['__message'])
+ && $message['mailbox'] === $mailbox
+ && in_array($message['object']->uid, $uids)
) {
$message['object']->flags[$flag] = $enabled;
- return;
+
+ if (count($uids) == 1) {
+ return;
+ }
}
$this->db->query(
@@ -481,7 +489,7 @@ class rcube_imap_cache
.", flags = flags ".($enabled ? "+ $idx" : "- $idx")
." WHERE user_id = ?"
." AND mailbox = ?"
- .($uids !== null ? " AND uid IN (".$this->db->array2list((array)$uids, 'integer').")" : "")
+ .($uids !== null ? " AND uid IN (".$this->db->array2list($uids, 'integer').")" : "")
." AND (flags & $idx) ".($enabled ? "= 0" : "= $idx"),
$this->userid, $mailbox);
}
@@ -503,10 +511,11 @@ class rcube_imap_cache
}
else {
// Remove the message from internal cache
- if (!empty($uids) && !is_array($uids) && ($message = $this->icache['message'])
- && $message['mailbox'] == $mailbox && $message['object']->uid == $uids
+ if (!empty($uids) && ($message = $this->icache['__message'])
+ && $message['mailbox'] === $mailbox
+ && in_array($message['object']->uid, (array)$uids)
) {
- $this->icache['message'] = null;
+ $this->icache['__message'] = null;
}
$this->db->query(
@@ -608,13 +617,13 @@ class rcube_imap_cache
// get expiration timestamp
$ts = get_offset_time($ttl, -1);
- $this->db->query("DELETE FROM ".get_table_name('cache_messages')
+ $this->db->query("DELETE FROM ".$this->db->table_name('cache_messages')
." WHERE changed < " . $this->db->fromunixtime($ts));
- $this->db->query("DELETE FROM ".get_table_name('cache_index')
+ $this->db->query("DELETE FROM ".$this->db->table_name('cache_index')
." WHERE changed < " . $this->db->fromunixtime($ts));
- $this->db->query("DELETE FROM ".get_table_name('cache_thread')
+ $this->db->query("DELETE FROM ".$this->db->table_name('cache_thread')
." WHERE changed < " . $this->db->fromunixtime($ts));
}
@@ -763,6 +772,11 @@ class rcube_imap_cache
$object = $index['object'];
$is_thread = is_a($object, 'rcube_result_thread');
+ // sanity check
+ if (empty($object)) {
+ return false;
+ }
+
// Get mailbox data (UIDVALIDITY, counters, etc.) for status check
$mbox_data = $this->imap->folder_data($mailbox);
@@ -1078,7 +1092,7 @@ class rcube_imap_cache
private function save_icache()
{
// Save current message from internal cache
- if ($message = $this->icache['message']) {
+ if ($message = $this->icache['__message']) {
// clean up some object's data
$object = $this->message_object_prepare($message['object']);
@@ -1089,7 +1103,7 @@ class rcube_imap_cache
$this->add_message($message['mailbox'], $object, !$message['exists']);
}
- $this->icache['message']['md5sum'] = $md5sum;
+ $this->icache['__message']['md5sum'] = $md5sum;
}
}
diff --git a/lib/ext/Roundcube/rcube_imap_generic.php b/lib/ext/Roundcube/rcube_imap_generic.php
index 915a11a..cce53ae 100644
--- a/lib/ext/Roundcube/rcube_imap_generic.php
+++ b/lib/ext/Roundcube/rcube_imap_generic.php
@@ -530,6 +530,7 @@ class rcube_imap_generic
}
else {
$authc = $user;
+ $user = '';
}
$auth_sasl = Auth_SASL::factory('digestmd5');
$reply = base64_encode($auth_sasl->getResponse($authc, $pass,
@@ -568,6 +569,7 @@ class rcube_imap_generic
}
else {
$authc = $user;
+ $user = '';
}
$reply = base64_encode($user . chr(0) . $authc . chr(0) . $pass);
@@ -2400,10 +2402,13 @@ class rcube_imap_generic
$mode = 0;
}
+ // Use BINARY extension when possible (and safe)
+ $binary = $mode && preg_match('/^[0-9.]+$/', $part) && $this->hasCapability('BINARY');
+ $fetch_mode = $binary ? 'BINARY' : 'BODY';
+
// format request
- $reply_key = '* ' . $id;
$key = $this->nextTag();
- $request = $key . ($is_uid ? ' UID' : '') . " FETCH $id (BODY.PEEK[$part])";
+ $request = $key . ($is_uid ? ' UID' : '') . " FETCH $id ($fetch_mode.PEEK[$part])";
// send request
if (!$this->putLine($request)) {
@@ -2411,6 +2416,10 @@ class rcube_imap_generic
return false;
}
+ if ($binary) {
+ $mode = -1;
+ }
+
// receive reply line
do {
$line = rtrim($this->readLine(1024));
@@ -2455,13 +2464,13 @@ class rcube_imap_generic
$prev = '';
while ($bytes > 0) {
- $line = $this->readLine(4096);
+ $line = $this->readLine(8192);
if ($line === NULL) {
break;
}
- $len = strlen($line);
+ $len = strlen($line);
if ($len > $bytes) {
$line = substr($line, 0, $bytes);
@@ -2538,7 +2547,7 @@ class rcube_imap_generic
{
unset($this->data['APPENDUID']);
- if (!$mailbox) {
+ if ($mailbox === null || $mailbox === '') {
return false;
}
@@ -2603,7 +2612,7 @@ class rcube_imap_generic
{
unset($this->data['APPENDUID']);
- if (!$mailbox) {
+ if ($mailbox === null || $mailbox === '') {
return false;
}
@@ -2612,6 +2621,7 @@ class rcube_imap_generic
if (file_exists(realpath($path))) {
$in_fp = fopen($path, 'r');
}
+
if (!$in_fp) {
$this->setError(self::ERROR_UNKNOWN, "Couldn't open $path for reading");
return false;
diff --git a/lib/ext/Roundcube/rcube_message.php b/lib/ext/Roundcube/rcube_message.php
index f550b57..fe2fcf3 100644
--- a/lib/ext/Roundcube/rcube_message.php
+++ b/lib/ext/Roundcube/rcube_message.php
@@ -52,7 +52,8 @@ class rcube_message
private $opt = array();
private $parse_alternative = false;
- public $uid = null;
+ public $uid;
+ public $folder;
public $headers;
public $parts = array();
public $mime_parts = array();
@@ -68,17 +69,22 @@ class rcube_message
*
* Provide a uid, and parse message structure.
*
- * @param string $uid The message UID.
+ * @param string $uid The message UID.
+ * @param string $folder Folder name
*
* @see self::$app, self::$storage, self::$opt, self::$parts
*/
- function __construct($uid)
+ function __construct($uid, $folder = null)
{
$this->uid = $uid;
$this->app = rcube::get_instance();
$this->storage = $this->app->get_storage();
+ $this->folder = strlen($folder) ? $folder : $this->storage->get_folder();
$this->storage->set_options(array('all_headers' => true));
+ // Set current folder
+ $this->storage->set_folder($this->folder);
+
$this->headers = $this->storage->get_message($uid);
if (!$this->headers)
@@ -179,10 +185,12 @@ class rcube_message
}
return $fp ? true : $part->body;
}
+
// get from IMAP
+ $this->storage->set_folder($this->folder);
+
return $this->storage->get_message_part($this->uid, $mime_id, $part, NULL, $fp, $skip_charset_conv);
- } else
- return null;
+ }
}
@@ -486,8 +494,13 @@ class rcube_message
}
// list as attachment as well
- if (!empty($mail_part->filename))
+ if (!empty($mail_part->filename)) {
$this->attachments[] = $mail_part;
+ }
+ // list html part as attachment (here the part is most likely inside a multipart/related part)
+ else if ($this->parse_alternative && ($secondary_type == 'html' && !$this->opt['prefer_html'])) {
+ $this->attachments[] = $mail_part;
+ }
}
// part message/*
else if ($primary_type == 'message') {
@@ -637,8 +650,10 @@ class rcube_message
function tnef_decode(&$part)
{
// @TODO: attachment may be huge, hadle it via file
- if (!isset($part->body))
+ if (!isset($part->body)) {
+ $this->storage->set_folder($this->folder);
$part->body = $this->storage->get_message_part($this->uid, $part->mime_id, $part);
+ }
$parts = array();
$tnef = new tnef_decoder;
@@ -673,8 +688,10 @@ class rcube_message
function uu_decode(&$part)
{
// @TODO: messages may be huge, hadle body via file
- if (!isset($part->body))
+ if (!isset($part->body)) {
+ $this->storage->set_folder($this->folder);
$part->body = $this->storage->get_message_part($this->uid, $part->mime_id, $part);
+ }
$parts = array();
// FIXME: line length is max.65?
diff --git a/lib/ext/Roundcube/rcube_mime.php b/lib/ext/Roundcube/rcube_mime.php
index e1f736a..d8e04a9 100644
--- a/lib/ext/Roundcube/rcube_mime.php
+++ b/lib/ext/Roundcube/rcube_mime.php
@@ -541,10 +541,10 @@ class rcube_mime
$prefix = $regs[0];
$level = strlen($prefix);
$line = rtrim(substr($line, $level));
- $line = $prefix . rc_wordwrap($line, $length - $level - 2, " \r\n$prefix ");
+ $line = $prefix . self::wordwrap($line, $length - $level - 2, " \r\n$prefix ");
}
else if ($line) {
- $line = rc_wordwrap(rtrim($line), $length - 2, " \r\n");
+ $line = self::wordwrap(rtrim($line), $length - 2, " \r\n");
// space-stuffing
$line = preg_replace('/(^|\r\n)(From| |>)/', '\\1 \\2', $line);
}
diff --git a/lib/ext/Roundcube/rcube_output_html.php b/lib/ext/Roundcube/rcube_output_html.php
index a071ee3..2743e77 100644
--- a/lib/ext/Roundcube/rcube_output_html.php
+++ b/lib/ext/Roundcube/rcube_output_html.php
@@ -400,7 +400,7 @@ class rcube_output_html extends rcube_output
'line' => __LINE__,
'file' => __FILE__,
'message' => 'Error loading template for '.$realname
- ), true, true);
+ ), true, $write);
return false;
}
@@ -698,6 +698,11 @@ class rcube_output_html extends rcube_output
}
break;
+ // frame
+ case 'frame':
+ return $this->frame($attrib);
+ break;
+
// show a label
case 'label':
if ($attrib['name'] || $attrib['command']) {
@@ -1275,6 +1280,30 @@ class rcube_output_html extends rcube_output
}
+ /**
+ * Returns iframe object, registers some related env variables
+ *
+ * @param array $attrib HTML attributes
+ *
+ * @return string IFRAME element
+ */
+ public function frame($attrib)
+ {
+ if (!$attrib['id']) {
+ $attrib['id'] = 'rcmframe';
+ }
+
+ if (!$attrib['name']) {
+ $attrib['name'] = $attrib['id'];
+ }
+
+ $this->set_env('contentframe', $attrib['id']);
+ $this->set_env('blankpage', $attrib['src'] ? $this->abs_url($attrib['src']) : 'program/resources/blank.gif');
+
+ return html::iframe($attrib);
+ }
+
+
/* ************* common functions delivering gui objects ************** */
diff --git a/lib/ext/Roundcube/rcube_result_index.php b/lib/ext/Roundcube/rcube_result_index.php
index cc1615d..334ec85 100644
--- a/lib/ext/Roundcube/rcube_result_index.php
+++ b/lib/ext/Roundcube/rcube_result_index.php
@@ -61,10 +61,14 @@ class rcube_result_index
for ($i=0, $len=count($data); $i<$len; $i++) {
$data_item = &$data[$i];
if (preg_match('/^ SORT/i', $data_item)) {
+ // valid response, initialize raw_data for is_error()
+ $this->raw_data = '';
$data_item = substr($data_item, 5);
break;
}
else if (preg_match('/^ (E?SEARCH)/i', $data_item, $m)) {
+ // valid response, initialize raw_data for is_error()
+ $this->raw_data = '';
$data_item = substr($data_item, strlen($m[0]));
if (strtoupper($m[1]) == 'ESEARCH') {
diff --git a/lib/ext/Roundcube/rcube_result_thread.php b/lib/ext/Roundcube/rcube_result_thread.php
index 214aec2..09fa465 100644
--- a/lib/ext/Roundcube/rcube_result_thread.php
+++ b/lib/ext/Roundcube/rcube_result_thread.php
@@ -61,6 +61,8 @@ class rcube_result_thread
// ...skip unilateral untagged server responses
for ($i=0, $len=count($data); $i<$len; $i++) {
if (preg_match('/^ THREAD/i', $data[$i])) {
+ // valid response, initialize raw_data for is_error()
+ $this->raw_data = '';
$data[$i] = substr($data[$i], 7);
break;
}
diff --git a/lib/ext/Roundcube/rcube_shared.inc b/lib/ext/Roundcube/rcube_shared.inc
index 5b839d8..4577c6d 100644
--- a/lib/ext/Roundcube/rcube_shared.inc
+++ b/lib/ext/Roundcube/rcube_shared.inc
@@ -108,11 +108,11 @@ function slashify($str)
/**
- * Remove slash at the end of the string
+ * Remove slashes at the end of the string
*/
function unslashify($str)
{
- return preg_replace('/\/$/', '', $str);
+ return preg_replace('/\/+$/', '', $str);
}
@@ -231,7 +231,7 @@ function array_keys_recursive($array)
{
$keys = array();
- if (!empty($array)) {
+ if (!empty($array) && is_array($array)) {
foreach ($array as $key => $child) {
$keys[] = $key;
foreach (array_keys_recursive($child) as $val) {
@@ -255,7 +255,22 @@ function asciiwords($str, $css_id = false, $replace_with = '')
/**
- * Remove single and double quotes from given string
+ * 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
*
* @param string Input value
*
@@ -422,7 +437,6 @@ function rcube_autoload($classname)
{
$filename = preg_replace(
array(
- '/MDB2_(.+)/',
'/Mail_(.+)/',
'/Net_(.+)/',
'/Auth_(.+)/',
@@ -431,7 +445,6 @@ function rcube_autoload($classname)
),
array(
'Mail/\\1',
- 'Mail/\\1',
'Net/\\1',
'Auth/\\1',
'html',
diff --git a/lib/ext/Roundcube/rcube_storage.php b/lib/ext/Roundcube/rcube_storage.php
index 768a26d..f83e240 100644
--- a/lib/ext/Roundcube/rcube_storage.php
+++ b/lib/ext/Roundcube/rcube_storage.php
@@ -195,7 +195,7 @@ abstract class rcube_storage
*/
public function set_folder($folder)
{
- if ($this->folder == $folder) {
+ if ($this->folder === $folder) {
return;
}
diff --git a/lib/ext/Roundcube/rcube_utils.php b/lib/ext/Roundcube/rcube_utils.php
index 9f18b79..b278431 100644
--- a/lib/ext/Roundcube/rcube_utils.php
+++ b/lib/ext/Roundcube/rcube_utils.php
@@ -92,9 +92,9 @@ class rcube_utils
return false;
}
- // Check domain part
- if (preg_match('/^\[*(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}\]*$/', $domain_part)) {
- return true; // IP address
+ // Validate domain part
+ if (preg_match('/^\[((IPv6:[0-9a-f:.]+)|([0-9.]+))\]$/i', $domain_part, $matches)) {
+ return self::check_ip(preg_replace('/^IPv6:/i', '', $matches[1])); // valid IPv4 or IPv6 address
}
else {
// If not an IP address
@@ -146,6 +146,52 @@ class rcube_utils
return false;
}
+
+ /**
+ * Validates IPv4 or IPv6 address
+ *
+ * @param string $ip IP address in v4 or v6 format
+ *
+ * @return bool True if the address is valid
+ */
+ public static function check_ip($ip)
+ {
+ // IPv6, but there's no build-in IPv6 support
+ if (strpos($ip, ':') !== false && !defined('AF_INET6')) {
+ $parts = explode(':', $domain_part);
+ $count = count($parts);
+
+ if ($count > 8 || $count < 2) {
+ return false;
+ }
+
+ foreach ($parts as $idx => $part) {
+ $length = strlen($part);
+ if (!$length) {
+ // there can be only one ::
+ if ($found_empty) {
+ return false;
+ }
+ $found_empty = true;
+ }
+ // last part can be an IPv4 address
+ else if ($idx == $count - 1) {
+ if (!preg_match('/^[0-9a-f]{1,4}$/i', $part)) {
+ return @inet_pton($part) !== false;
+ }
+ }
+ else if (!preg_match('/^[0-9a-f]{1,4}$/i', $part)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ return @inet_pton($ip) !== false;
+ }
+
+
/**
* Check whether the HTTP referer matches the current request
*
@@ -154,8 +200,8 @@ class rcube_utils
public static function check_referer()
{
$uri = parse_url($_SERVER['REQUEST_URI']);
- $referer = parse_url(rcube_request_header('Referer'));
- return $referer['host'] == rcube_request_header('Host') && $referer['path'] == $uri['path'];
+ $referer = parse_url(self::request_header('Referer'));
+ return $referer['host'] == self::request_header('Host') && $referer['path'] == $uri['path'];
}
@@ -175,6 +221,10 @@ class rcube_utils
static $js_rep_table = false;
static $xml_rep_table = false;
+ if (!is_string($str)) {
+ $str = strval($str);
+ }
+
// encode for HTML output
if ($enctype == 'html') {
if (!$html_encode_arr) {
diff --git a/lib/ext/Roundcube/rcube_vcard.php b/lib/ext/Roundcube/rcube_vcard.php
index 37cd3ab..49b312c 100644
--- a/lib/ext/Roundcube/rcube_vcard.php
+++ b/lib/ext/Roundcube/rcube_vcard.php
@@ -313,7 +313,7 @@ class rcube_vcard
case 'birthday':
case 'anniversary':
- if (($val = rcube_strtotime($value)) && ($fn = self::$fieldmap[$field]))
+ if (($val = rcube_utils::strtotime($value)) && ($fn = self::$fieldmap[$field]))
$this->raw[$fn][] = array(0 => date('Y-m-d', $val), 'value' => array('date'));
break;
@@ -555,6 +555,7 @@ class rcube_vcard
if ((list($key, $value) = explode('=', $attr)) && $value) {
$value = trim($value);
if ($key == 'ENCODING') {
+ $value = strtoupper($value);
// add next line(s) to value string if QP line end detected
if ($value == 'QUOTED-PRINTABLE') {
while (preg_match('/=$/', $lines[$i]))