4 commits - lib/ext lib/kolab_sync_backend_device.php lib/kolab_sync_backend.php

Aleksander Machniak machniak at kolabsys.com
Wed Sep 19 10:34:31 CEST 2012


 lib/ext/Roundcube/rcube_addressbook.php   |    2 -
 lib/ext/Roundcube/rcube_charset.php       |   31 ++++++++++++---
 lib/ext/Roundcube/rcube_config.php        |    1 
 lib/ext/Roundcube/rcube_db.php            |   18 ++++++---
 lib/ext/Roundcube/rcube_imap.php          |   19 ++++++---
 lib/ext/Roundcube/rcube_imap_cache.php    |   52 ++++++++++++++++----------
 lib/ext/Roundcube/rcube_imap_generic.php  |   22 ++++++++---
 lib/ext/Roundcube/rcube_message.php       |   33 ++++++++++++----
 lib/ext/Roundcube/rcube_mime.php          |    4 +-
 lib/ext/Roundcube/rcube_output_html.php   |   31 +++++++++++++++
 lib/ext/Roundcube/rcube_result_index.php  |    4 ++
 lib/ext/Roundcube/rcube_result_thread.php |    2 +
 lib/ext/Roundcube/rcube_shared.inc        |   25 +++++++++---
 lib/ext/Roundcube/rcube_storage.php       |    2 -
 lib/ext/Roundcube/rcube_utils.php         |   60 +++++++++++++++++++++++++++---
 lib/ext/Roundcube/rcube_vcard.php         |    3 +
 lib/kolab_sync_backend.php                |    7 ++-
 lib/kolab_sync_backend_device.php         |    2 -
 18 files changed, 246 insertions(+), 72 deletions(-)

New commits:
commit bc5a28d56e0beb0e98bcee9a6cfaae209e4ec572
Author: Aleksander Machniak <alec at alec.pl>
Date:   Wed Sep 19 10:04:07 2012 +0200

    Fix parse error from last commit

diff --git a/lib/kolab_sync_backend.php b/lib/kolab_sync_backend.php
index 5e33506..b8f5463 100644
--- a/lib/kolab_sync_backend.php
+++ b/lib/kolab_sync_backend.php
@@ -370,7 +370,7 @@ class kolab_sync_backend
         // ALIAS: user-friendly device name
 
         $metadata = $this->root_meta;
-        $metadata['DEVICE'][$id] = $device
+        $metadata['DEVICE'][$id] = $device;
         $metadata = array(self::ASYNC_KEY => $this->serialize_metadata($metadata));
 
         $result = $this->storage->set_metadata(self::ROOT_MAILBOX, $metadata);


commit 91bea80c1841479b9d492fa94017a1d76e8ddb5d
Author: Aleksander Machniak <alec at alec.pl>
Date:   Wed Sep 19 10:02:25 2012 +0200

    Update Roundcube Framework

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]))


commit 540de2286720de3e30e48dad45884eb88eee2e23
Author: Aleksander Machniak <alec at alec.pl>
Date:   Wed Sep 19 09:55:09 2012 +0200

    Small comment fix

diff --git a/lib/kolab_sync_backend.php b/lib/kolab_sync_backend.php
index 440f982..5e33506 100644
--- a/lib/kolab_sync_backend.php
+++ b/lib/kolab_sync_backend.php
@@ -360,16 +360,17 @@ class kolab_sync_backend
         $this->devices_list();
 
         // Old Kolab_ZPush device parameters
-        // MODE: -1 | 0 | 1  (not set | flatmode | foldermode)
+        // MODE:  -1 | 0 | 1  (not set | flatmode | foldermode)
         // TYPE:  device type string
         // ALIAS: user-friendly device name
 
         // Syncroton (kolab_sync_backend_device) uses
-        // ID: internal identifier in syncroton database
-        // TYPE: device type string
+        // ID:    internal identifier in syncroton database
+        // TYPE:  device type string
+        // ALIAS: user-friendly device name
 
         $metadata = $this->root_meta;
-        $metadata['DEVICE'][$id] = $device;
+        $metadata['DEVICE'][$id] = $device
         $metadata = array(self::ASYNC_KEY => $this->serialize_metadata($metadata));
 
         $result = $this->storage->set_metadata(self::ROOT_MAILBOX, $metadata);


commit 833af0f50639a60398f4a02df61b1e61e95fac5c
Author: Aleksander Machniak <alec at alec.pl>
Date:   Wed Sep 19 09:44:44 2012 +0200

    Fix typo

diff --git a/lib/kolab_sync_backend_device.php b/lib/kolab_sync_backend_device.php
index c8cc7be..9f0b909 100644
--- a/lib/kolab_sync_backend_device.php
+++ b/lib/kolab_sync_backend_device.php
@@ -62,7 +62,7 @@ class kolab_sync_backend_device extends kolab_sync_backend_common implements Syn
         // Create device entry in kolab backend
         $created = $this->backend->device_create(array(
             'ID'    => $device->id,
-            'TYPE'  => $device->devicedype,
+            'TYPE'  => $device->devicetype,
             'ALIAS' => $device->friendlyname,
         ), $device->deviceid);
 





More information about the commits mailing list