2 commits - lib/ext lib/init.php lib/kolab_sync_backend.php lib/kolab_sync_data_email.php lib/kolab_sync.php

Aleksander Machniak machniak at kolabsys.com
Mon Nov 26 11:59:25 CET 2012


 lib/ext/Roundcube/bootstrap.php             |  493 ++++++++
 lib/ext/Roundcube/html.php                  |    9 
 lib/ext/Roundcube/rcube.php                 |   84 -
 lib/ext/Roundcube/rcube_addressbook.php     |    9 
 lib/ext/Roundcube/rcube_base_replacer.php   |    5 
 lib/ext/Roundcube/rcube_browser.php         |    3 
 lib/ext/Roundcube/rcube_cache.php           |    4 
 lib/ext/Roundcube/rcube_charset.php         |   66 -
 lib/ext/Roundcube/rcube_config.php          |   39 
 lib/ext/Roundcube/rcube_contacts.php        |    3 
 lib/ext/Roundcube/rcube_content_filter.php  |    3 
 lib/ext/Roundcube/rcube_csv2vcard.php       |  382 ++++++
 lib/ext/Roundcube/rcube_db.php              |    9 
 lib/ext/Roundcube/rcube_db_mssql.php        |    5 
 lib/ext/Roundcube/rcube_db_mysql.php        |    4 
 lib/ext/Roundcube/rcube_db_pgsql.php        |    5 
 lib/ext/Roundcube/rcube_db_sqlite.php       |    7 
 lib/ext/Roundcube/rcube_db_sqlsrv.php       |    5 
 lib/ext/Roundcube/rcube_image.php           |   29 
 lib/ext/Roundcube/rcube_imap.php            |   22 
 lib/ext/Roundcube/rcube_imap_cache.php      |    4 
 lib/ext/Roundcube/rcube_imap_generic.php    |   19 
 lib/ext/Roundcube/rcube_ldap.php            |   39 
 lib/ext/Roundcube/rcube_message.php         |   23 
 lib/ext/Roundcube/rcube_message_header.php  |    6 
 lib/ext/Roundcube/rcube_message_part.php    |    4 
 lib/ext/Roundcube/rcube_mime.php            |   35 
 lib/ext/Roundcube/rcube_output.php          |  283 ----
 lib/ext/Roundcube/rcube_output_html.php     | 1672 ----------------------------
 lib/ext/Roundcube/rcube_output_json.php     |  257 ----
 lib/ext/Roundcube/rcube_plugin.php          |    3 
 lib/ext/Roundcube/rcube_plugin_api.php      |   15 
 lib/ext/Roundcube/rcube_result_index.php    |    3 
 lib/ext/Roundcube/rcube_result_set.php      |    3 
 lib/ext/Roundcube/rcube_result_thread.php   |    3 
 lib/ext/Roundcube/rcube_session.php         |   23 
 lib/ext/Roundcube/rcube_smtp.php            |    7 
 lib/ext/Roundcube/rcube_spellchecker.php    |    3 
 lib/ext/Roundcube/rcube_storage.php         |    8 
 lib/ext/Roundcube/rcube_string_replacer.php |   33 
 lib/ext/Roundcube/rcube_user.php            |   54 
 lib/ext/Roundcube/rcube_utils.php           |  100 +
 lib/ext/Roundcube/rcube_vcard.php           |   70 -
 lib/init.php                                |   44 
 lib/kolab_sync.php                          |    7 
 lib/kolab_sync_backend.php                  |   10 
 lib/kolab_sync_data_email.php               |    7 
 47 files changed, 1393 insertions(+), 2528 deletions(-)

New commits:
commit 75ace1ac33498c7292cdc1eba0770833bb26b134
Author: Aleksander Machniak <alec at alec.pl>
Date:   Mon Nov 26 11:58:14 2012 +0100

    Update Roundcube Framework, fix SMTP auth (#1380)

diff --git a/lib/ext/Roundcube/bootstrap.php b/lib/ext/Roundcube/bootstrap.php
new file mode 100644
index 0000000..47020c1
--- /dev/null
+++ b/lib/ext/Roundcube/bootstrap.php
@@ -0,0 +1,493 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | program/include/bootstrap.php                                         |
+ |                                                                       |
+ | This file is part of the Roundcube PHP suite                          |
+ | 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.                |
+ | See the README file for a full license statement.                     |
+ |                                                                       |
+ | CONTENTS:                                                             |
+ |   Roundcube Framework Initialization                                  |
+ |                                                                       |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube at gmail.com>                        |
+ | Author: Aleksander Machniak <alec at alec.pl>                            |
+ +-----------------------------------------------------------------------+
+*/
+
+
+/**
+ * Roundcube Framework Initialization
+ *
+ * @package    Framework
+ * @subpackage Core
+ */
+
+$config = array(
+    'error_reporting'         => E_ALL &~ (E_NOTICE | E_STRICT),
+    // Some users are not using Installer, so we'll check some
+    // critical PHP settings here. Only these, which doesn't provide
+    // an error/warning in the logs later. See (#1486307).
+    'mbstring.func_overload'  => 0,
+    'suhosin.session.encrypt' => 0,
+    'session.auto_start'      => 0,
+    'file_uploads'            => 1,
+    'magic_quotes_runtime'    => 0,
+    'magic_quotes_sybase'     => 0, // #1488506
+);
+foreach ($config as $optname => $optval) {
+    if ($optval != ini_get($optname) && @ini_set($optname, $optval) === false) {
+        die("ERROR: Wrong '$optname' option value and it wasn't possible to set it to required value ($optval).\n"
+            ."Check your PHP configuration (including php_admin_flag).");
+    }
+}
+
+// framework constants
+define('RCUBE_VERSION', '0.9-git');
+define('RCMAIL_CHARSET', 'UTF-8');
+
+if (!defined('RCUBE_LIB_DIR')) {
+    define('RCUBE_LIB_DIR', dirname(__FILE__).'/');
+}
+
+if (!defined('RCUBE_INSTALL_PATH')) {
+    define('RCUBE_INSTALL_PATH', RCUBE_LIB_DIR);
+}
+
+if (!defined('RCUBE_CONFIG_DIR')) {
+    define('RCUBE_CONFIG_DIR', RCUBE_INSTALL_PATH . 'config/');
+}
+
+if (!defined('RCUBE_PLUGINS_DIR')) {
+    define('RCUBE_PLUGINS_DIR', RCUBE_INSTALL_PATH . 'plugins/');
+}
+
+if (!defined('RCUBE_LOCALIZATION_DIR')) {
+    define('RCUBE_LOCALIZATION_DIR', RCUBE_INSTALL_PATH . 'localization/');
+}
+
+// set internal encoding for mbstring extension
+if (extension_loaded('mbstring')) {
+    mb_internal_encoding(RCMAIL_CHARSET);
+    @mb_regex_encoding(RCMAIL_CHARSET);
+}
+
+// Register autoloader
+spl_autoload_register('rcube_autoload');
+
+// set PEAR error handling (will also load the PEAR main class)
+PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'rcube_pear_error');
+
+
+
+/**
+ * Similar function as in_array() but case-insensitive
+ *
+ * @param string $needle    Needle value
+ * @param array  $heystack  Array to search in
+ *
+ * @return boolean True if found, False if not
+ */
+function in_array_nocase($needle, $haystack)
+{
+    $needle = mb_strtolower($needle);
+    foreach ((array)$haystack as $value) {
+        if ($needle === mb_strtolower($value)) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+
+/**
+ * Parse a human readable string for a number of bytes.
+ *
+ * @param string $str  Input string
+ *
+ * @return float Number of bytes
+ */
+function parse_bytes($str)
+{
+    if (is_numeric($str)) {
+        return floatval($str);
+    }
+
+    if (preg_match('/([0-9\.]+)\s*([a-z]*)/i', $str, $regs)) {
+        $bytes = floatval($regs[1]);
+        switch (strtolower($regs[2])) {
+        case 'g':
+        case 'gb':
+            $bytes *= 1073741824;
+            break;
+        case 'm':
+        case 'mb':
+            $bytes *= 1048576;
+            break;
+        case 'k':
+        case 'kb':
+            $bytes *= 1024;
+            break;
+        }
+    }
+
+    return floatval($bytes);
+}
+
+
+/**
+ * Make sure the string ends with a slash
+ */
+function slashify($str)
+{
+  return unslashify($str).'/';
+}
+
+
+/**
+ * Remove slashes at the end of the string
+ */
+function unslashify($str)
+{
+  return preg_replace('/\/+$/', '', $str);
+}
+
+
+/**
+ * Returns number of seconds for a specified offset string.
+ *
+ * @param string $str  String representation of the offset (e.g. 20min, 5h, 2days, 1week)
+ *
+ * @return int Number of seconds
+ */
+function get_offset_sec($str)
+{
+    if (preg_match('/^([0-9]+)\s*([smhdw])/i', $str, $regs)) {
+        $amount = (int) $regs[1];
+        $unit   = strtolower($regs[2]);
+    }
+    else {
+        $amount = (int) $str;
+        $unit   = 's';
+    }
+
+    switch ($unit) {
+    case 'w':
+        $amount *= 7;
+    case 'd':
+        $amount *= 24;
+    case 'h':
+        $amount *= 60;
+    case 'm':
+        $amount *= 60;
+    }
+
+    return $amount;
+}
+
+
+/**
+ * Create a unix timestamp with a specified offset from now.
+ *
+ * @param string $offset_str  String representation of the offset (e.g. 20min, 5h, 2days)
+ * @param int    $factor      Factor to multiply with the offset
+ *
+ * @return int Unix timestamp
+ */
+function get_offset_time($offset_str, $factor=1)
+{
+    return time() + get_offset_sec($offset_str) * $factor;
+}
+
+
+/**
+ * Truncate string if it is longer than the allowed length.
+ * Replace the middle or the ending part of a string with a placeholder.
+ *
+ * @param string $str         Input string
+ * @param int    $maxlength   Max. length
+ * @param string $placeholder Replace removed chars with this
+ * @param bool   $ending      Set to True if string should be truncated from the end
+ *
+ * @return string Abbreviated string
+ */
+function abbreviate_string($str, $maxlength, $placeholder='...', $ending=false)
+{
+    $length = mb_strlen($str);
+
+    if ($length > $maxlength) {
+        if ($ending) {
+            return mb_substr($str, 0, $maxlength) . $placeholder;
+        }
+
+        $placeholder_length = mb_strlen($placeholder);
+        $first_part_length  = floor(($maxlength - $placeholder_length)/2);
+        $second_starting_location = $length - $maxlength + $first_part_length + $placeholder_length;
+
+        $str = mb_substr($str, 0, $first_part_length) . $placeholder . mb_substr($str, $second_starting_location);
+    }
+
+    return $str;
+}
+
+
+/**
+ * Get all keys from array (recursive).
+ *
+ * @param array $array  Input array
+ *
+ * @return array List of array keys
+ */
+function array_keys_recursive($array)
+{
+    $keys = array();
+
+    if (!empty($array) && is_array($array)) {
+        foreach ($array as $key => $child) {
+            $keys[] = $key;
+            foreach (array_keys_recursive($child) as $val) {
+                $keys[] = $val;
+            }
+        }
+    }
+
+    return $keys;
+}
+
+
+/**
+ * Remove all non-ascii and non-word chars except ., -, _
+ */
+function asciiwords($str, $css_id = false, $replace_with = '')
+{
+    $allowed = 'a-z0-9\_\-' . (!$css_id ? '\.' : '');
+    return preg_replace("/[^$allowed]/i", $replace_with, $str);
+}
+
+
+/**
+ * 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
+ *
+ * @return string Dequoted string
+ */
+function strip_quotes($str)
+{
+    return str_replace(array("'", '"'), '', $str);
+}
+
+
+/**
+ * Remove new lines characters from given string
+ *
+ * @param string $str  Input value
+ *
+ * @return string Stripped string
+ */
+function strip_newlines($str)
+{
+    return preg_replace('/[\r\n]/', '', $str);
+}
+
+
+/**
+ * Compose a valid representation of name and e-mail address
+ *
+ * @param string $email  E-mail address
+ * @param string $name   Person name
+ *
+ * @return string Formatted string
+ */
+function format_email_recipient($email, $name = '')
+{
+    $email = trim($email);
+
+    if ($name && $name != $email) {
+        // Special chars as defined by RFC 822 need to in quoted string (or escaped).
+        if (preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $name)) {
+            $name = '"'.addcslashes($name, '"').'"';
+        }
+
+        return "$name <$email>";
+    }
+
+    return $email;
+}
+
+
+/**
+ * Format e-mail address
+ *
+ * @param string $email E-mail address
+ *
+ * @return string Formatted e-mail address
+ */
+function format_email($email)
+{
+    $email = trim($email);
+    $parts = explode('@', $email);
+    $count = count($parts);
+
+    if ($count > 1) {
+        $parts[$count-1] = mb_strtolower($parts[$count-1]);
+
+        $email = implode('@', $parts);
+    }
+
+    return $email;
+}
+
+
+/**
+ * mbstring replacement functions
+ */
+if (!extension_loaded('mbstring'))
+{
+    function mb_strlen($str)
+    {
+        return strlen($str);
+    }
+
+    function mb_strtolower($str)
+    {
+        return strtolower($str);
+    }
+
+    function mb_strtoupper($str)
+    {
+        return strtoupper($str);
+    }
+
+    function mb_substr($str, $start, $len=null)
+    {
+        return substr($str, $start, $len);
+    }
+
+    function mb_strpos($haystack, $needle, $offset=0)
+    {
+        return strpos($haystack, $needle, $offset);
+    }
+
+    function mb_strrpos($haystack, $needle, $offset=0)
+    {
+        return strrpos($haystack, $needle, $offset);
+    }
+}
+
+/**
+ * intl replacement functions
+ */
+
+if (!function_exists('idn_to_utf8'))
+{
+    function idn_to_utf8($domain, $flags=null)
+    {
+        static $idn, $loaded;
+
+        if (!$loaded) {
+            $idn = new Net_IDNA2();
+            $loaded = true;
+        }
+
+        if ($idn && $domain && preg_match('/(^|\.)xn--/i', $domain)) {
+            try {
+                $domain = $idn->decode($domain);
+            }
+            catch (Exception $e) {
+            }
+        }
+        return $domain;
+    }
+}
+
+if (!function_exists('idn_to_ascii'))
+{
+    function idn_to_ascii($domain, $flags=null)
+    {
+        static $idn, $loaded;
+
+        if (!$loaded) {
+            $idn = new Net_IDNA2();
+            $loaded = true;
+        }
+
+        if ($idn && $domain && preg_match('/[^\x20-\x7E]/', $domain)) {
+            try {
+                $domain = $idn->encode($domain);
+            }
+            catch (Exception $e) {
+            }
+        }
+        return $domain;
+    }
+}
+
+/**
+ * Use PHP5 autoload for dynamic class loading
+ *
+ * @todo Make Zend, PEAR etc play with this
+ * @todo Make our classes conform to a more straight forward CS.
+ */
+function rcube_autoload($classname)
+{
+    $filename = preg_replace(
+        array(
+            '/Mail_(.+)/',
+            '/Net_(.+)/',
+            '/Auth_(.+)/',
+            '/^html_.+/',
+            '/^rcube(.*)/',
+            '/^utf8$/',
+        ),
+        array(
+            'Mail/\\1',
+            'Net/\\1',
+            'Auth/\\1',
+            'Roundcube/html',
+            'Roundcube/rcube\\1',
+            'utf8.class',
+        ),
+        $classname
+    );
+
+    if ($fp = @fopen("$filename.php", 'r', true)) {
+        fclose($fp);
+        include_once "$filename.php";
+        return true;
+    }
+
+    return false;
+}
+
+/**
+ * Local callback function for PEAR errors
+ */
+function rcube_pear_error($err)
+{
+    error_log(sprintf("%s (%s): %s",
+        $err->getMessage(),
+        $err->getCode(),
+        $err->getUserinfo()), 0);
+}
diff --git a/lib/ext/Roundcube/html.php b/lib/ext/Roundcube/html.php
index 2349852..8ff685a 100644
--- a/lib/ext/Roundcube/html.php
+++ b/lib/ext/Roundcube/html.php
@@ -23,7 +23,8 @@
 /**
  * Class for HTML code creation
  *
- * @package HTML
+ * @package    Framework
+ * @subpackage HTML
  */
 class html
 {
@@ -252,9 +253,9 @@ class html
      * @return string HTML code
      * @see html::tag()
      */
-    public static function br()
+    public static function br($attrib = array())
     {
-        return self::tag('br');
+        return self::tag('br', $attrib);
     }
 
     /**
@@ -334,7 +335,7 @@ class html
      */
     public static function quote($str)
     {
-        return htmlspecialchars($str, ENT_COMPAT, RCMAIL_CHARSET);
+        return @htmlspecialchars($str, ENT_COMPAT, RCMAIL_CHARSET);
     }
 }
 
diff --git a/lib/ext/Roundcube/rcube.php b/lib/ext/Roundcube/rcube.php
index 0e40b3c..c798465 100644
--- a/lib/ext/Roundcube/rcube.php
+++ b/lib/ext/Roundcube/rcube.php
@@ -434,6 +434,9 @@ class rcube
         $this->session->register_gc_handler(array($this, 'temp_gc'));
         $this->session->register_gc_handler(array($this, 'cache_gc'));
 
+        $this->session->set_secret($this->config->get('des_key') . dirname($_SERVER['SCRIPT_NAME']));
+        $this->session->set_ip_check($this->config->get('ip_check'));
+
         // start PHP session (if not in CLI mode)
         if ($_SERVER['REMOTE_ADDR']) {
             session_start();
@@ -442,33 +445,6 @@ class rcube
 
 
     /**
-     * Configure session object internals
-     */
-    public function session_configure()
-    {
-        if (!$this->session) {
-            return;
-        }
-
-        $lifetime   = $this->config->get('session_lifetime', 0) * 60;
-        $keep_alive = $this->config->get('keep_alive');
-
-        // set keep-alive/check-recent interval
-        if ($keep_alive) {
-            // be sure that it's less than session lifetime
-            if ($lifetime) {
-                $keep_alive = min($keep_alive, $lifetime - 30);
-            }
-            $keep_alive = max(60, $keep_alive);
-            $this->session->set_keep_alive($keep_alive);
-        }
-
-        $this->session->set_secret($this->config->get('des_key') . dirname($_SERVER['SCRIPT_NAME']));
-        $this->session->set_ip_check($this->config->get('ip_check'));
-    }
-
-
-    /**
      * Garbage collector function for temp files.
      * Remove temp files older than two days
      */
@@ -620,8 +596,8 @@ class rcube
             ob_start();
 
             // get english labels (these should be complete)
-            @include(INSTALL_PATH . 'program/localization/en_US/labels.inc');
-            @include(INSTALL_PATH . 'program/localization/en_US/messages.inc');
+            @include(RCUBE_LOCALIZATION_DIR . 'en_US/labels.inc');
+            @include(RCUBE_LOCALIZATION_DIR . 'en_US/messages.inc');
 
             if (is_array($labels))
                 $this->texts = $labels;
@@ -629,9 +605,9 @@ class rcube
                 $this->texts = array_merge($this->texts, $messages);
 
             // include user language files
-            if ($lang != 'en' && $lang != 'en_US' && is_dir(INSTALL_PATH . 'program/localization/' . $lang)) {
-                include_once(INSTALL_PATH . 'program/localization/' . $lang . '/labels.inc');
-                include_once(INSTALL_PATH . 'program/localization/' . $lang . '/messages.inc');
+            if ($lang != 'en' && $lang != 'en_US' && is_dir(RCUBE_LOCALIZATION_DIR . $lang)) {
+                include_once(RCUBE_LOCALIZATION_DIR . $lang . '/labels.inc');
+                include_once(RCUBE_LOCALIZATION_DIR . $lang . '/messages.inc');
 
                 if (is_array($labels))
                     $this->texts = array_merge($this->texts, $labels);
@@ -669,7 +645,7 @@ class rcube
         }
 
         if (empty($rcube_languages)) {
-            @include(INSTALL_PATH . 'program/localization/index.inc');
+            @include(RCUBE_LOCALIZATION_DIR . 'index.inc');
         }
 
         // check if we have an alias for that language
@@ -690,7 +666,7 @@ class rcube
             }
         }
 
-        if (!isset($rcube_languages[$lang]) || !is_dir(INSTALL_PATH . 'program/localization/' . $lang)) {
+        if (!isset($rcube_languages[$lang]) || !is_dir(RCUBE_LOCALIZATION_DIR . $lang)) {
             $lang = 'en_US';
         }
 
@@ -708,11 +684,11 @@ class rcube
         static $sa_languages = array();
 
         if (!sizeof($sa_languages)) {
-            @include(INSTALL_PATH . 'program/localization/index.inc');
+            @include(RCUBE_LOCALIZATION_DIR . 'index.inc');
 
-            if ($dh = @opendir(INSTALL_PATH . 'program/localization')) {
+            if ($dh = @opendir(RCUBE_LOCALIZATION_DIR)) {
                 while (($name = readdir($dh)) !== false) {
-                    if ($name[0] == '.' || !is_dir(INSTALL_PATH . 'program/localization/' . $name)) {
+                    if ($name[0] == '.' || !is_dir(RCUBE_LOCALIZATION_DIR . $name)) {
                         continue;
                     }
 
@@ -1041,7 +1017,7 @@ class rcube
         $log_dir  = self::$instance ? self::$instance->config->get('log_dir') : null;
 
         if (empty($log_dir)) {
-            $log_dir = INSTALL_PATH . 'logs';
+            $log_dir = RCUBE_INSTALL_PATH . 'logs';
         }
 
         // try to open specific log file for writing
@@ -1227,8 +1203,38 @@ class rcube
         if (is_object($this->user)) {
             return $this->user->get_username();
         }
+        else if (isset($_SESSION['username'])) {
+            return $_SESSION['username'];
+        }
+    }
 
-        return null;
+
+    /**
+     * Getter for logged user email (derived from user name not identity).
+     *
+     * @return string User email address
+     */
+    public function get_user_email()
+    {
+        if (is_object($this->user)) {
+            return $this->user->get_username('mail');
+        }
+    }
+
+
+    /**
+     * Getter for logged user password.
+     *
+     * @return string User password
+     */
+    public function get_user_password()
+    {
+        if ($this->password) {
+            return $this->password;
+        }
+        else if ($_SESSION['password']) {
+            return $this->decrypt($_SESSION['password']);
+        }
     }
 }
 
diff --git a/lib/ext/Roundcube/rcube_addressbook.php b/lib/ext/Roundcube/rcube_addressbook.php
index 892ae26..d14fc58 100644
--- a/lib/ext/Roundcube/rcube_addressbook.php
+++ b/lib/ext/Roundcube/rcube_addressbook.php
@@ -23,7 +23,8 @@
 /**
  * Abstract skeleton of an address book/repository
  *
- * @package Addressbook
+ * @package    Framework
+ * @subpackage Addressbook
  */
 abstract class rcube_addressbook
 {
@@ -208,7 +209,7 @@ abstract class rcube_addressbook
      */
     public function validate(&$save_data, $autofix = false)
     {
-        $rcmail = rcmail::get_instance();
+        $rcmail = rcube::get_instance();
 
         // check validity of email addresses
         foreach ($this->get_col_values('email', $save_data, true) as $email) {
@@ -466,7 +467,7 @@ abstract class rcube_addressbook
      */
     public static function compose_display_name($contact, $full_email = false)
     {
-        $contact = rcmail::get_instance()->plugins->exec_hook('contact_displayname', $contact);
+        $contact = rcube::get_instance()->plugins->exec_hook('contact_displayname', $contact);
         $fn = $contact['name'];
 
         if (!$fn)  // default display name composition according to vcard standard
@@ -503,7 +504,7 @@ abstract class rcube_addressbook
         static $compose_mode;
 
         if (!isset($compose_mode))  // cache this
-            $compose_mode = rcmail::get_instance()->config->get('addressbook_name_listing', 0);
+            $compose_mode = rcube::get_instance()->config->get('addressbook_name_listing', 0);
 
         if ($compose_mode == 3)
             $fn = join(' ', array($contact['surname'] . ',', $contact['firstname'], $contact['middlename']));
diff --git a/lib/ext/Roundcube/rcube_base_replacer.php b/lib/ext/Roundcube/rcube_base_replacer.php
index 4ec3675..b2a0fc1 100644
--- a/lib/ext/Roundcube/rcube_base_replacer.php
+++ b/lib/ext/Roundcube/rcube_base_replacer.php
@@ -23,8 +23,9 @@
  * Helper class to turn relative urls into absolute ones
  * using a predefined base
  *
- * @package Core
- * @author Thomas Bruederli <roundcube at gmail.com>
+ * @package    Framework
+ * @subpackage Core
+ * @author     Thomas Bruederli <roundcube at gmail.com>
  */
 class rcube_base_replacer
 {
diff --git a/lib/ext/Roundcube/rcube_browser.php b/lib/ext/Roundcube/rcube_browser.php
index 7cfae70..154e7ef 100644
--- a/lib/ext/Roundcube/rcube_browser.php
+++ b/lib/ext/Roundcube/rcube_browser.php
@@ -22,7 +22,8 @@
 /**
  * Provide details about the client's browser based on the User-Agent header
  *
- * @package Core
+ * @package    Framework
+ * @subpackage Core
  */
 class rcube_browser
 {
diff --git a/lib/ext/Roundcube/rcube_cache.php b/lib/ext/Roundcube/rcube_cache.php
index 4e60dea..3e1ce4f 100644
--- a/lib/ext/Roundcube/rcube_cache.php
+++ b/lib/ext/Roundcube/rcube_cache.php
@@ -25,10 +25,10 @@
 /**
  * Interface class for accessing Roundcube cache
  *
- * @package    Cache
+ * @package    Framework
+ * @subpackage Cache
  * @author     Thomas Bruederli <roundcube at gmail.com>
  * @author     Aleksander Machniak <alec at alec.pl>
- * @version    1.1
  */
 class rcube_cache
 {
diff --git a/lib/ext/Roundcube/rcube_charset.php b/lib/ext/Roundcube/rcube_charset.php
index ff4c2bb..e8cce00 100644
--- a/lib/ext/Roundcube/rcube_charset.php
+++ b/lib/ext/Roundcube/rcube_charset.php
@@ -25,10 +25,11 @@
 /**
  * Character sets conversion functionality
  *
- * @package Core
- * @author Thomas Bruederli <roundcube at gmail.com>
- * @author Aleksander Machniak <alec at alec.pl>
- * @author Edmund Grimley Evans <edmundo at rano.org>
+ * @package    Framework
+ * @subpackage Core
+ * @author     Thomas Bruederli <roundcube at gmail.com>
+ * @author     Aleksander Machniak <alec at alec.pl>
+ * @author     Edmund Grimley Evans <edmundo at rano.org>
  */
 class rcube_charset
 {
@@ -655,22 +656,49 @@ class rcube_charset
      */
     public static function detect($string, $failover='')
     {
-        if (!function_exists('mb_detect_encoding')) {
-            return $failover;
-        }
-
-        // 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',
-            'ISO-2022-KR', 'ISO-2022-JP'
-        );
+        if (substr($string, 0, 4) == "\0\0\xFE\xFF") return 'UTF-32BE';  // Big Endian
+        if (substr($string, 0, 4) == "\xFF\xFE\0\0") return 'UTF-32LE';  // Little Endian
+        if (substr($string, 0, 2) == "\xFE\xFF")     return 'UTF-16BE';  // Big Endian
+        if (substr($string, 0, 2) == "\xFF\xFE")     return 'UTF-16LE';  // Little Endian
+        if (substr($string, 0, 3) == "\xEF\xBB\xBF") return 'UTF-8';
+
+        // heuristics
+        if ($string[0] == "\0" && $string[1] == "\0" && $string[2] == "\0" && $string[3] != "\0") return 'UTF-32BE';
+        if ($string[0] != "\0" && $string[1] == "\0" && $string[2] == "\0" && $string[3] == "\0") return 'UTF-32LE';
+        if ($string[0] == "\0" && $string[1] != "\0" && $string[2] == "\0" && $string[3] != "\0") return 'UTF-16BE';
+        if ($string[0] != "\0" && $string[1] == "\0" && $string[2] != "\0" && $string[3] == "\0") return 'UTF-16LE';
+
+        if (function_exists('mb_detect_encoding')) {
+            // FIXME: the order is important, because sometimes
+            // iso string is detected as euc-jp and etc.
+            $enc = array(
+                'UTF-8', 'SJIS', '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', 'BIG5',
+                'ISO-2022-KR', 'ISO-2022-JP',
+            );
 
-        $result = mb_detect_encoding($string, join(',', $enc));
+            $result = mb_detect_encoding($string, join(',', $enc));
+        }
+        else {
+            // No match, check for UTF-8
+            // from http://w3.org/International/questions/qa-forms-utf-8.html
+            if (preg_match('/\A(
+                [\x09\x0A\x0D\x20-\x7E]
+                | [\xC2-\xDF][\x80-\xBF]
+                | \xE0[\xA0-\xBF][\x80-\xBF]
+                | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}
+                | \xED[\x80-\x9F][\x80-\xBF]
+                | \xF0[\x90-\xBF][\x80-\xBF]{2}
+                | [\xF1-\xF3][\x80-\xBF]{3}
+                | \xF4[\x80-\x8F][\x80-\xBF]{2}
+                )*\z/xs', substr($string, 0, 2048))
+            ) {
+            return 'UTF-8';
+            }
+        }
 
         return $result ? $result : $failover;
     }
diff --git a/lib/ext/Roundcube/rcube_config.php b/lib/ext/Roundcube/rcube_config.php
index b9fd955..8112d2e 100644
--- a/lib/ext/Roundcube/rcube_config.php
+++ b/lib/ext/Roundcube/rcube_config.php
@@ -22,7 +22,8 @@
 /**
  * Configuration class for Roundcube
  *
- * @package Core
+ * @package    Framework
+ * @subpackage Core
  */
 class rcube_config
 {
@@ -43,6 +44,8 @@ class rcube_config
         'mail_pagesize'        => 'pagesize',
         'addressbook_pagesize' => 'pagesize',
         'reply_mode'           => 'top_posting',
+        'refresh_interval'     => 'keep_alive',
+        'min_refresh_interval' => 'min_keep_alive',
     );
 
 
@@ -68,11 +71,11 @@ class rcube_config
     private function load()
     {
         // load main config file
-        if (!$this->load_from_file(RCMAIL_CONFIG_DIR . '/main.inc.php'))
+        if (!$this->load_from_file(RCUBE_CONFIG_DIR . 'main.inc.php'))
             $this->errors[] = 'main.inc.php was not found.';
 
         // load database config
-        if (!$this->load_from_file(RCMAIL_CONFIG_DIR . '/db.inc.php'))
+        if (!$this->load_from_file(RCUBE_CONFIG_DIR . 'db.inc.php'))
             $this->errors[] = 'db.inc.php was not found.';
 
         // load host-specific configuration
@@ -93,8 +96,8 @@ class rcube_config
             $this->prop['skin'] = self::DEFAULT_SKIN;
 
         // fix paths
-        $this->prop['log_dir'] = $this->prop['log_dir'] ? realpath(unslashify($this->prop['log_dir'])) : INSTALL_PATH . 'logs';
-        $this->prop['temp_dir'] = $this->prop['temp_dir'] ? realpath(unslashify($this->prop['temp_dir'])) : INSTALL_PATH . 'temp';
+        $this->prop['log_dir'] = $this->prop['log_dir'] ? realpath(unslashify($this->prop['log_dir'])) : RCUBE_INSTALL_PATH . 'logs';
+        $this->prop['temp_dir'] = $this->prop['temp_dir'] ? realpath(unslashify($this->prop['temp_dir'])) : RCUBE_INSTALL_PATH . 'temp';
 
         // fix default imap folders encoding
         foreach (array('drafts_mbox', 'junk_mbox', 'sent_mbox', 'trash_mbox') as $folder)
@@ -153,7 +156,7 @@ class rcube_config
         }
 
         if ($fname) {
-            $this->load_from_file(RCMAIL_CONFIG_DIR . '/' . $fname);
+            $this->load_from_file(RCUBE_CONFIG_DIR . $fname);
         }
     }
 
@@ -204,8 +207,15 @@ class rcube_config
 
         $rcube = rcube::get_instance();
 
-        if ($name == 'timezone' && isset($this->prop['_timezone_value']))
+        if ($name == 'timezone' && isset($this->prop['_timezone_value'])) {
             $result = $this->prop['_timezone_value'];
+        }
+        else if ($name == 'client_mimetypes') {
+            if ($result == null && $def == null)
+                $result = 'text/plain,text/html,text/xml,image/jpeg,image/gif,image/png,image/bmp,image/tiff,application/x-javascript,application/pdf,application/x-shockwave-flash';
+            if ($result && is_string($result))
+                $result = explode(',', $result);
+        }
 
         $plugin = $rcube->plugins->exec_hook('config_get', array(
             'name' => $name, 'default' => $def, 'result' => $result));
@@ -412,7 +422,20 @@ class rcube_config
      */
     private function client_timezone()
     {
-        return isset($_SESSION['timezone']) && ($ctz = timezone_name_from_abbr("", $_SESSION['timezone'] * 3600, 0)) ? $ctz : date_default_timezone_get();
+        if (isset($_SESSION['timezone']) && is_numeric($_SESSION['timezone'])
+              && ($ctz = timezone_name_from_abbr("", $_SESSION['timezone'] * 3600, 0))) {
+            return $ctz;
+        }
+        else if (!empty($_SESSION['timezone'])) {
+            try {
+                $tz = timezone_open($_SESSION['timezone']);
+                return $tz->getName();
+            }
+            catch (Exception $e) { /* gracefully ignore */ }
+        }
+
+        // fallback to server's timezone
+        return date_default_timezone_get();
     }
 
 }
diff --git a/lib/ext/Roundcube/rcube_contacts.php b/lib/ext/Roundcube/rcube_contacts.php
index 534a65c..e4500c7 100644
--- a/lib/ext/Roundcube/rcube_contacts.php
+++ b/lib/ext/Roundcube/rcube_contacts.php
@@ -23,7 +23,8 @@
 /**
  * Model class for the local address book database
  *
- * @package Addressbook
+ * @package    Framework
+ * @subpackage Addressbook
  */
 class rcube_contacts extends rcube_addressbook
 {
diff --git a/lib/ext/Roundcube/rcube_content_filter.php b/lib/ext/Roundcube/rcube_content_filter.php
index 36e61a2..99916a3 100644
--- a/lib/ext/Roundcube/rcube_content_filter.php
+++ b/lib/ext/Roundcube/rcube_content_filter.php
@@ -21,6 +21,9 @@
 
 /**
  * PHP stream filter to detect html/javascript code in attachments
+ *
+ * @package    Framework
+ * @subpackage Core
  */
 class rcube_content_filter extends php_user_filter
 {
diff --git a/lib/ext/Roundcube/rcube_csv2vcard.php b/lib/ext/Roundcube/rcube_csv2vcard.php
new file mode 100644
index 0000000..ec7a3ab
--- /dev/null
+++ b/lib/ext/Roundcube/rcube_csv2vcard.php
@@ -0,0 +1,382 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | program/include/rcube_csv2vcard.php                                   |
+ |                                                                       |
+ | This file is part of the Roundcube Webmail client                     |
+ | Copyright (C) 2008-2012, The Roundcube Dev Team                       |
+ |                                                                       |
+ | Licensed under the GNU General Public License version 3 or            |
+ | any later version with exceptions for skins & plugins.                |
+ | See the README file for a full license statement.                     |
+ |                                                                       |
+ | PURPOSE:                                                              |
+ |   CSV to vCard data conversion                                        |
+ +-----------------------------------------------------------------------+
+ | Author: Aleksander Machniak <alec at alec.pl>                            |
+ +-----------------------------------------------------------------------+
+*/
+
+/**
+ * CSV to vCard data converter
+ *
+ * @package    Framework
+ * @subpackage Addressbook
+ * @author     Aleksander Machniak <alec at alec.pl>
+ */
+class rcube_csv2vcard
+{
+    /**
+     * CSV to vCard fields mapping
+     *
+     * @var array
+     */
+    protected $csv2vcard_map = array(
+        // MS Outlook 2010
+        'anniversary'           => 'anniversary',
+        'assistants_name'       => 'assistant',
+        'assistants_phone'      => 'phone:assistant',
+        'birthday'              => 'birthday',
+        'business_city'         => 'locality:work',
+        'business_countryregion' => 'country:work',
+        'business_fax'          => 'phone:work,fax',
+        'business_phone'        => 'phone:work',
+        'business_phone_2'      => 'phone:work2',
+        'business_postal_code'  => 'zipcode:work',
+        'business_state'        => 'region:work',
+        'business_street'       => 'street:work',
+        //'business_street_2'     => '',
+        //'business_street_3'     => '',
+        'car_phone'             => 'phone:car',
+        'categories'            => 'categories',
+        //'children'              => '',
+        'company'               => 'organization',
+        //'company_main_phone'    => '',
+        'department'            => 'department',
+        //'email_2_address'       => '', //@TODO
+        //'email_2_type'          => '',
+        //'email_3_address'       => '', //@TODO
+        //'email_3_type'          => '',
+        'email_address'         => 'email:main',
+        //'email_type'            => '',
+        'first_name'            => 'firstname',
+        'gender'                => 'gender',
+        'home_city'             => 'locality:home',
+        'home_countryregion'    => 'country:home',
+        'home_fax'              => 'phone:home,fax',
+        'home_phone'            => 'phone:home',
+        'home_phone_2'          => 'phone:home2',
+        'home_postal_code'      => 'zipcode:home',
+        'home_state'            => 'region:home',
+        'home_street'           => 'street:home',
+        //'home_street_2'         => '',
+        //'home_street_3'         => '',
+        //'initials'              => '',
+        //'isdn'                  => '',
+        'job_title'             => 'jobtitle',
+        //'keywords'              => '',
+        //'language'              => '',
+        'last_name'             => 'surname',
+        //'location'              => '',
+        'managers_name'         => 'manager',
+        'middle_name'           => 'middlename',
+        //'mileage'               => '',
+        'mobile_phone'          => 'phone:cell',
+        'notes'                 => 'notes',
+        //'office_location'       => '',
+        'other_city'            => 'locality:other',
+        'other_countryregion'   => 'country:other',
+        'other_fax'             => 'phone:other,fax',
+        'other_phone'           => 'phone:other',
+        'other_postal_code'     => 'zipcode:other',
+        'other_state'           => 'region:other',
+        'other_street'          => 'street:other',
+        //'other_street_2'        => '',
+        //'other_street_3'        => '',
+        'pager'                 => 'phone:pager',
+        'primary_phone'         => 'phone:pref',
+        //'profession'            => '',
+        //'radio_phone'           => '',
+        'spouse'                => 'spouse',
+        'suffix'                => 'suffix',
+        'title'                 => 'title',
+        'web_page'              => 'website:homepage',
+
+        // Thunderbird
+        'birth_day'             => 'birthday-d',
+        'birth_month'           => 'birthday-m',
+        'birth_year'            => 'birthday-y',
+        'display_name'          => 'displayname',
+        'fax_number'            => 'phone:fax',
+        'home_address'          => 'street:home',
+        //'home_address_2'        => '',
+        'home_country'          => 'country:home',
+        'home_zipcode'          => 'zipcode:home',
+        'mobile_number'         => 'phone:cell',
+        'nickname'              => 'nickname',
+        'organization'          => 'organization',
+        'pager_number'          => 'phone:pager',
+        'primary_email'         => 'email:pref',
+        'secondary_email'       => 'email:other',
+        'web_page_1'            => 'website:homepage',
+        'web_page_2'            => 'website:other',
+        'work_phone'            => 'phone:work',
+        'work_address'          => 'street:work',
+        //'work_address_2'        => '',
+        'work_country'          => 'country:work',
+        'work_zipcode'          => 'zipcode:work',
+    );
+
+    /**
+     * CSV label to text mapping for English
+     *
+     * @var array
+     */
+    protected $label_map = array(
+        // MS Outlook 2010
+        'anniversary'       => "Anniversary",
+        'assistants_name'   => "Assistant's Name",
+        'assistants_phone'  => "Assistant's Phone",
+        'birthday'          => "Birthday",
+        'business_city'     => "Business City",
+        'business_countryregion' => "Business Country/Region",
+        'business_fax'      => "Business Fax",
+        'business_phone'    => "Business Phone",
+        'business_phone_2'  => "Business Phone 2",
+        'business_postal_code' => "Business Postal Code",
+        'business_state'    => "Business State",
+        'business_street'   => "Business Street",
+        //'business_street_2' => "Business Street 2",
+        //'business_street_3' => "Business Street 3",
+        'car_phone'         => "Car Phone",
+        'categories'        => "Categories",
+        //'children'          => "Children",
+        'company'           => "Company",
+        //'company_main_phone' => "Company Main Phone",
+        'department'        => "Department",
+        //'directory_server'  => "Directory Server",
+        //'email_2_address'   => "E-mail 2 Address",
+        //'email_2_type'      => "E-mail 2 Type",
+        //'email_3_address'   => "E-mail 3 Address",
+        //'email_3_type'      => "E-mail 3 Type",
+        'email_address'     => "E-mail Address",
+        //'email_type'        => "E-mail Type",
+        'first_name'        => "First Name",
+        'gender'            => "Gender",
+        'home_city'         => "Home City",
+        'home_countryregion' => "Home Country/Region",
+        'home_fax'          => "Home Fax",
+        'home_phone'        => "Home Phone",
+        'home_phone_2'      => "Home Phone 2",
+        'home_postal_code'  => "Home Postal Code",
+        'home_state'        => "Home State",
+        'home_street'       => "Home Street",
+        //'home_street_2'     => "Home Street 2",
+        //'home_street_3'     => "Home Street 3",
+        //'initials'          => "Initials",
+        //'isdn'              => "ISDN",
+        'job_title'         => "Job Title",
+        //'keywords'          => "Keywords",
+        //'language'          => "Language",
+        'last_name'         => "Last Name",
+        //'location'          => "Location",
+        'managers_name'     => "Manager's Name",
+        'middle_name'       => "Middle Name",
+        //'mileage'           => "Mileage",
+        'mobile_phone'      => "Mobile Phone",
+        'notes'             => "Notes",
+        //'office_location'   => "Office Location",
+        'other_city'        => "Other City",
+        'other_countryregion' => "Other Country/Region",
+        'other_fax'         => "Other Fax",
+        'other_phone'       => "Other Phone",
+        'other_postal_code' => "Other Postal Code",
+        'other_state'       => "Other State",
+        'other_street'      => "Other Street",
+        //'other_street_2'    => "Other Street 2",
+        //'other_street_3'    => "Other Street 3",
+        'pager'             => "Pager",
+        'primary_phone'     => "Primary Phone",
+        //'profession'        => "Profession",
+        //'radio_phone'       => "Radio Phone",
+        'spouse'            => "Spouse",
+        'suffix'            => "Suffix",
+        'title'             => "Title",
+        'web_page'          => "Web Page",
+
+        // Thunderbird
+        'birth_day'         => "Birth Day",
+        'birth_month'       => "Birth Month",
+        'birth_year'        => "Birth Year",
+        'display_name'      => "Display Name",
+        'fax_number'        => "Fax Number",
+        'home_address'      => "Home Address",
+        //'home_address_2'    => "Home Address 2",
+        'home_country'      => "Home Country",
+        'home_zipcode'      => "Home ZipCode",
+        'mobile_number'     => "Mobile Number",
+        'nickname'          => "Nickname",
+        'organization'      => "Organization",
+        'pager_number'      => "Pager Namber",
+        'primary_email'     => "Primary Email",
+        'secondary_email'   => "Secondary Email",
+        'web_page_1'        => "Web Page 1",
+        'web_page_2'        => "Web Page 2",
+        'work_phone'        => "Work Phone",
+        'work_address'      => "Work Address",
+        //'work_address_2'    => "Work Address 2",
+        'work_country'      => "Work Country",
+        'work_zipcode'      => "Work ZipCode",
+    );
+
+    protected $local_label_map = array();
+    protected $vcards = array();
+    protected $map = array();
+
+
+    /**
+     * Class constructor
+     *
+     * @param string $lang File language
+     */
+    public function __construct($lang = 'en_US')
+    {
+        // Localize fields map
+        if ($lang && $lang != 'en_US') {
+            if (file_exists(RCUBE_LOCALIZATION_DIR . "$lang/csv2vcard.inc")) {
+                include RCUBE_LOCALIZATION_DIR . "$lang/csv2vcard.inc";
+            }
+
+            if (!empty($map)) {
+                $this->local_label_map = array_merge($this->label_map, $map);
+            }
+        }
+
+        $this->label_map = array_flip($this->label_map);
+        $this->local_label_map = array_flip($this->local_label_map);
+    }
+
+    /**
+     *
+     */
+    public function import($csv)
+    {
+        // convert to UTF-8
+        $head     = substr($csv, 0, 4096);
+        $fallback = rcube::get_instance()->config->get('default_charset', 'ISO-8859-1'); // fallback to Latin-1?
+        $charset  = rcube_charset::detect($head, RCMAIL_CHARSET);
+        $csv      = rcube_charset::convert($csv, $charset);
+        $head     = '';
+
+        $this->map = array();
+
+        // Parse file
+        foreach (preg_split("/[\r\n]+/", $csv) as $i => $line) {
+            $line = trim($line);
+            if (empty($line)) {
+                continue;
+            }
+
+            $elements = rcube_utils::explode_quoted_string(',', $line);
+
+            if (empty($elements)) {
+                continue;
+            }
+
+            // Parse header
+            if (empty($this->map)) {
+                $this->parse_header($elements);
+                if (empty($this->map)) {
+                    break;
+                }
+            }
+            // Parse data row
+            else {
+                $this->csv_to_vcard($elements);
+            }
+        }
+    }
+
+    /**
+     * @return array rcube_vcard List of vcards
+     */
+    public function export()
+    {
+        return $this->vcards;
+    }
+
+    /**
+     * Parse CSV header line, detect fields mapping
+     */
+    protected function parse_header($elements)
+    {
+        $map1 = array();
+        $map2 = array();
+        $size = count($elements);
+
+        // check English labels
+        for ($i = 0; $i < $size; $i++) {
+            $label = $this->label_map[$elements[$i]];
+            if ($label && !empty($this->csv2vcard_map[$label])) {
+                $map1[$i] = $this->csv2vcard_map[$label];
+            }
+        }
+        // check localized labels
+        if (!empty($this->local_label_map)) {
+            for ($i = 0; $i < $size; $i++) {
+                $label = $this->local_label_map[$elements[$i]];
+                if ($label && !empty($this->csv2vcard_map[$label])) {
+                    $map2[$i] = $this->csv2vcard_map[$label];
+                }
+            }
+        }
+
+        $this->map = count($map1) >= count($map2) ? $map1 : $map2;
+    }
+
+    /**
+     * Convert CSV data row to vCard
+     */
+    protected function csv_to_vcard($data)
+    {
+        $contact = array();
+        foreach ($this->map as $idx => $name) {
+            $value = $data[$idx];
+            if ($value !== null && $value !== '') {
+                $contact[$name] = $value;
+            }
+        }
+
+        if (empty($contact)) {
+            return;
+        }
+
+        // Handle special values
+        if (!empty($contact['birthday-d']) && !empty($contact['birthday-m']) && !empty($contact['birthday-y'])) {
+            $contact['birthday'] = $contact['birthday-y'] .'-' .$contact['birthday-m'] . '-' . $contact['birthday-d'];
+        }
+
+        foreach (array('birthday', 'anniversary') as $key) {
+            if (!empty($contact[$key]) && $contact[$key] == '0/0/00') { // @TODO: localization?
+                unset($contact[$key]);
+            }
+        }
+
+        if (!empty($contact['gender']) && ($gender = strtolower($contact['gender']))) {
+            if (!in_array($gender, array('male', 'female'))) {
+                unset($contact['gender']);
+            }
+        }
+
+        // Create vcard object
+        $vcard = new rcube_vcard();
+        foreach ($contact as $name => $value) {
+            $name = explode(':', $name);
+            $vcard->set($name[0], $value, $name[1]);
+        }
+
+        // add to the list
+        $this->vcards[] = $vcard;
+    }
+}
diff --git a/lib/ext/Roundcube/rcube_db.php b/lib/ext/Roundcube/rcube_db.php
index b066101..5d8c4a5 100644
--- a/lib/ext/Roundcube/rcube_db.php
+++ b/lib/ext/Roundcube/rcube_db.php
@@ -21,12 +21,11 @@
 
 
 /**
- * Database independent query interface
+ * Database independent query interface.
+ * This is a wrapper for the PHP PDO.
  *
- * This is a wrapper for the PHP PDO
- *
- * @package Database
- * @version 1.0
+ * @package   Framework
+ * @sbpackage Database
  */
 class rcube_db
 {
diff --git a/lib/ext/Roundcube/rcube_db_mssql.php b/lib/ext/Roundcube/rcube_db_mssql.php
index 119647d..c95663c 100644
--- a/lib/ext/Roundcube/rcube_db_mssql.php
+++ b/lib/ext/Roundcube/rcube_db_mssql.php
@@ -23,11 +23,10 @@
 
 /**
  * Database independent query interface
- *
  * This is a wrapper for the PHP PDO
  *
- * @package Database
- * @version 1.0
+ * @package    Framework
+ * @subpackage Database
  */
 class rcube_db_mssql extends rcube_db
 {
diff --git a/lib/ext/Roundcube/rcube_db_mysql.php b/lib/ext/Roundcube/rcube_db_mysql.php
index 6f0acba..1c5ba1d 100644
--- a/lib/ext/Roundcube/rcube_db_mysql.php
+++ b/lib/ext/Roundcube/rcube_db_mysql.php
@@ -26,8 +26,8 @@
  *
  * This is a wrapper for the PHP PDO
  *
- * @package Database
- * @version 1.0
+ * @package    Framework
+ * @subpackage Database
  */
 class rcube_db_mysql extends rcube_db
 {
diff --git a/lib/ext/Roundcube/rcube_db_pgsql.php b/lib/ext/Roundcube/rcube_db_pgsql.php
index 0d0caad..797860a 100644
--- a/lib/ext/Roundcube/rcube_db_pgsql.php
+++ b/lib/ext/Roundcube/rcube_db_pgsql.php
@@ -23,11 +23,10 @@
 
 /**
  * Database independent query interface
- *
  * This is a wrapper for the PHP PDO
  *
- * @package Database
- * @version 1.0
+ * @package    Framework
+ * @subpackage Database
  */
 class rcube_db_pgsql extends rcube_db
 {
diff --git a/lib/ext/Roundcube/rcube_db_sqlite.php b/lib/ext/Roundcube/rcube_db_sqlite.php
index a739767..65dcb6d 100644
--- a/lib/ext/Roundcube/rcube_db_sqlite.php
+++ b/lib/ext/Roundcube/rcube_db_sqlite.php
@@ -23,11 +23,10 @@
 
 /**
  * Database independent query interface
- *
  * This is a wrapper for the PHP PDO
  *
- * @package Database
- * @version 1.0
+ * @package    Framework
+ * @subpackage Database
  */
 class rcube_db_sqlite extends rcube_db
 {
@@ -67,7 +66,7 @@ class rcube_db_sqlite extends rcube_db
 
         // Initialize database structure in file is empty
         if (!empty($dsn['database']) && !filesize($dsn['database'])) {
-            $data = file_get_contents(INSTALL_PATH . 'SQL/sqlite.initial.sql');
+            $data = file_get_contents(RCUBE_INSTALL_PATH . 'SQL/sqlite.initial.sql');
 
             if (strlen($data)) {
                 $this->debug('INITIALIZE DATABASE');
diff --git a/lib/ext/Roundcube/rcube_db_sqlsrv.php b/lib/ext/Roundcube/rcube_db_sqlsrv.php
index e58bf07..8b6ffe8 100644
--- a/lib/ext/Roundcube/rcube_db_sqlsrv.php
+++ b/lib/ext/Roundcube/rcube_db_sqlsrv.php
@@ -23,11 +23,10 @@
 
 /**
  * Database independent query interface
- *
  * This is a wrapper for the PHP PDO
  *
- * @package Database
- * @version 1.0
+ * @package    Framework
+ * @subpackage Database
  */
 class rcube_db_sqlsrv extends rcube_db
 {
diff --git a/lib/ext/Roundcube/rcube_image.php b/lib/ext/Roundcube/rcube_image.php
index 80e8bd4..b72a24c 100644
--- a/lib/ext/Roundcube/rcube_image.php
+++ b/lib/ext/Roundcube/rcube_image.php
@@ -21,6 +21,12 @@
  +-----------------------------------------------------------------------+
 */
 
+/**
+ * Image resizer and converter
+ *
+ * @package    Framework
+ * @subpackage Utils
+ */
 class rcube_image
 {
     private $image_file;
@@ -78,10 +84,11 @@ class rcube_image
      *
      * @param int    $size      Max width/height size
      * @param string $filename  Output filename
+     * @param boolean $browser_compat  Convert to image type displayable by any browser
      *
-     * @return bool True on success, False on failure
+     * @return mixed Output type on success, False on failure
      */
-    public function resize($size, $filename = null)
+    public function resize($size, $filename = null, $browser_compat = false)
     {
         $result  = false;
         $rcube   = rcube::get_instance();
@@ -104,15 +111,22 @@ class rcube_image
             }
 
             $type = strtr($type, array("jpeg" => "jpg", "tiff" => "tif", "ps" => "eps", "ept" => "eps"));
+            $p['intype'] = $type;
+
+            // convert to an image format every browser can display
+            if ($browser_compat && !in_array($type, array('jpg','gif','png'))) {
+                $type = 'jpg';
+            }
+
             $p += array('type' => $type, 'types' => "bmp,eps,gif,jp2,jpg,png,svg,tif", 'quality' => 75);
-            $p['-opts'] = array('-resize' => $size.'>');
+            $p['-opts'] = array('-resize' => $p['size'].'>');
 
             if (in_array($type, explode(',', $p['types']))) { // Valid type?
-                $result = rcube::exec($convert . ' 2>&1 -flatten -auto-orient -colorspace RGB -quality {quality} {-opts} {in} {type}:{out}', $p);
+                $result = rcube::exec($convert . ' 2>&1 -flatten -auto-orient -colorspace RGB -quality {quality} {-opts} {intype}:{in} {type}:{out}', $p);
             }
 
             if ($result === '') {
-                return true;
+                return $type;
             }
         }
 
@@ -148,16 +162,19 @@ class rcube_image
 
             if ($props['gd_type'] == IMAGETYPE_JPEG) {
                 $result = imagejpeg($image, $filename, 75);
+                $type = 'jpg';
             }
             elseif($props['gd_type'] == IMAGETYPE_GIF) {
                 $result = imagegif($image, $filename);
+                $type = 'gid';
             }
             elseif($props['gd_type'] == IMAGETYPE_PNG) {
                 $result = imagepng($image, $filename, 6, PNG_ALL_FILTERS);
+                $type = 'png';
             }
 
             if ($result) {
-                return true;
+                return $type;
             }
         }
 
diff --git a/lib/ext/Roundcube/rcube_imap.php b/lib/ext/Roundcube/rcube_imap.php
index a89fd16..ac12ec7 100644
--- a/lib/ext/Roundcube/rcube_imap.php
+++ b/lib/ext/Roundcube/rcube_imap.php
@@ -25,10 +25,10 @@
 /**
  * Interface class for accessing an IMAP server
  *
- * @package    Mail
+ * @package    Framework
+ * @subpackage Storage
  * @author     Thomas Bruederli <roundcube at gmail.com>
  * @author     Aleksander Machniak <alec at alec.pl>
- * @version    2.0
  */
 class rcube_imap extends rcube_storage
 {
@@ -141,8 +141,8 @@ class rcube_imap extends rcube_storage
             $this->set_debug(true);
 
             $this->options['ident'] = array(
-                'name' => 'Roundcube Webmail',
-                'version' => RCMAIL_VERSION,
+                'name' => 'Roundcube',
+                'version' => RCUBE_VERSION,
                 'php' => PHP_VERSION,
                 'os' => PHP_OS,
                 'command' => $_SERVER['REQUEST_URI'],
@@ -2074,7 +2074,7 @@ class rcube_imap extends rcube_storage
 
         if ($o_part && $o_part->size) {
             $body = $this->conn->handlePartBody($this->folder, $uid, true,
-                $part ? $part : 'TEXT', $o_part->encoding, $print, $fp);
+                $part ? $part : 'TEXT', $o_part->encoding, $print, $fp, $o_part->ctype_primary == 'text');
         }
 
         if ($fp || $print) {
@@ -2188,10 +2188,10 @@ class rcube_imap extends rcube_storage
             $result = $this->conn->flag($folder, $uids, $flag);
         }
 
-        if ($result) {
+        if ($result && !$skip_cache) {
             // reload message headers if cached
-            // @TODO: update flags instead removing from cache
-            if (!$skip_cache && ($mcache = $this->get_mcache_engine())) {
+            // update flags instead removing from cache
+            if ($mcache = $this->get_mcache_engine()) {
                 $status = strpos($flag, 'UN') !== 0;
                 $mflag  = preg_replace('/^UN/', '', $flag);
                 $mcache->change_flag($folder, $all_mode ? null : explode(',', $uids),
@@ -2203,8 +2203,12 @@ class rcube_imap extends rcube_storage
                 $this->clear_messagecount($folder, 'SEEN');
                 $this->clear_messagecount($folder, 'UNSEEN');
             }
-            else if ($flag == 'DELETED') {
+            else if ($flag == 'DELETED' || $flag == 'UNDELETED') {
                 $this->clear_messagecount($folder, 'DELETED');
+                // remove cached messages
+                if ($this->options['skip_deleted']) {
+                    $this->clear_message_cache($folder, $all_mode ? null : explode(',', $uids));
+                }
             }
         }
 
diff --git a/lib/ext/Roundcube/rcube_imap_cache.php b/lib/ext/Roundcube/rcube_imap_cache.php
index f36ace0..31214cf 100644
--- a/lib/ext/Roundcube/rcube_imap_cache.php
+++ b/lib/ext/Roundcube/rcube_imap_cache.php
@@ -24,10 +24,10 @@
 /**
  * Interface class for accessing Roundcube messages cache
  *
- * @package    Cache
+ * @package    Framework
+ * @subpackage Storage
  * @author     Thomas Bruederli <roundcube at gmail.com>
  * @author     Aleksander Machniak <alec at alec.pl>
- * @version    1.0
  */
 class rcube_imap_cache
 {
diff --git a/lib/ext/Roundcube/rcube_imap_generic.php b/lib/ext/Roundcube/rcube_imap_generic.php
index 9c525dc..a0a8f3b 100644
--- a/lib/ext/Roundcube/rcube_imap_generic.php
+++ b/lib/ext/Roundcube/rcube_imap_generic.php
@@ -30,8 +30,8 @@
 /**
  * PHP based wrapper class to connect to an IMAP server
  *
- * @package Mail
- * @author  Aleksander Machniak <alec at alec.pl>
+ * @package    Framework
+ * @subpackage Storage
  */
 class rcube_imap_generic
 {
@@ -2379,7 +2379,7 @@ class rcube_imap_generic
         return $this->handlePartBody($mailbox, $id, $is_uid, $part);
     }
 
-    function handlePartBody($mailbox, $id, $is_uid=false, $part='', $encoding=NULL, $print=NULL, $file=NULL, $formatted=true)
+    function handlePartBody($mailbox, $id, $is_uid=false, $part='', $encoding=NULL, $print=NULL, $file=NULL, $formatted=false)
     {
         if (!$this->select($mailbox)) {
             return false;
@@ -2417,6 +2417,7 @@ class rcube_imap_generic
         }
 
         if ($binary) {
+            // WARNING: Use $formatting argument with care, this may break binary data stream
             $mode = -1;
         }
 
@@ -3658,18 +3659,6 @@ class rcube_imap_generic
     }
 
     /**
-     * Unescapes quoted-string
-     *
-     * @param string  $string       IMAP string
-     *
-     * @return string String
-     */
-    static function unEscape($string)
-    {
-        return stripslashes($string);
-    }
-
-    /**
      * Set the value of the debugging flag.
      *
      * @param   boolean $debug      New value for the debugging flag.
diff --git a/lib/ext/Roundcube/rcube_ldap.php b/lib/ext/Roundcube/rcube_ldap.php
index 61a073f..c9a14d8 100644
--- a/lib/ext/Roundcube/rcube_ldap.php
+++ b/lib/ext/Roundcube/rcube_ldap.php
@@ -6,7 +6,7 @@
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
  | Copyright (C) 2006-2012, The Roundcube Dev Team                       |
- | Copyright (C) 2011, Kolab Systems AG                                  |
+ | Copyright (C) 2011-2012, Kolab Systems AG                             |
  |                                                                       |
  | Licensed under the GNU General Public License version 3 or            |
  | any later version with exceptions for skins & plugins.                |
@@ -26,7 +26,8 @@
 /**
  * Model class to access an LDAP address directory
  *
- * @package Addressbook
+ * @package    Framework
+ * @subpackage Addressbook
  */
 class rcube_ldap extends rcube_addressbook
 {
@@ -160,7 +161,8 @@ class rcube_ldap extends rcube_addressbook
         }
 
         // make sure LDAP_rdn field is required
-        if (!empty($this->prop['LDAP_rdn']) && !in_array($this->prop['LDAP_rdn'], $this->prop['required_fields'])) {
+        if (!empty($this->prop['LDAP_rdn']) && !in_array($this->prop['LDAP_rdn'], $this->prop['required_fields'])
+            && !in_array($this->prop['LDAP_rdn'], array_keys((array)$this->prop['autovalues']))) {
             $this->prop['required_fields'][] = $this->prop['LDAP_rdn'];
         }
 
@@ -267,11 +269,11 @@ class rcube_ldap extends rcube_addressbook
         if ($this->prop['user_specific']) {
             // No password set, use the session password
             if (empty($bind_pass)) {
-                $bind_pass = $rcube->decrypt($_SESSION['password']);
+                $bind_pass = $rcube->get_user_password();
             }
 
             // Get the pieces needed for variable replacement.
-            if ($fu = $rcube->get_user_name())
+            if ($fu = $rcube->get_user_email())
                 list($u, $d) = explode('@', $fu);
             else
                 $d = $this->mail_domain;
@@ -1086,6 +1088,9 @@ class rcube_ldap extends rcube_addressbook
         $newentry = $this->_map_data($save_cols);
         $newentry['objectClass'] = $this->prop['LDAP_Object_Classes'];
 
+        // add automatically generated attributes
+        $this->add_autovalues($newentry);
+
         // Verify that the required fields are set.
         $missing = null;
         foreach ($this->prop['required_fields'] as $fld) {
@@ -1389,6 +1394,30 @@ class rcube_ldap extends rcube_addressbook
         }
     }
 
+    /**
+     * Generate missing attributes as configured
+     *
+     * @param array LDAP record attributes
+     */
+    protected function add_autovalues(&$attrs)
+    {
+        $attrvals = array();
+        foreach ($attrs as $k => $v) {
+            $attrvals['{'.$k.'}'] = is_array($v) ? $v[0] : $v;
+        }
+
+        foreach ((array)$this->prop['autovalues'] as $lf => $templ) {
+            if (empty($attrs[$lf])) {
+                // replace {attr} placeholders with concrete attribute values
+                $templ = preg_replace('/\{\w+\}/', '', strtr($templ, $attrvals));
+
+                if (strpos($templ, '(') !== false)
+                    $attrs[$lf] = eval("return ($templ);");
+                else
+                    $attrs[$lf] = $templ;
+            }
+        }
+    }
 
     /**
      * Execute the LDAP search based on the stored credentials
diff --git a/lib/ext/Roundcube/rcube_message.php b/lib/ext/Roundcube/rcube_message.php
index 4e1b5a0..87319f0 100644
--- a/lib/ext/Roundcube/rcube_message.php
+++ b/lib/ext/Roundcube/rcube_message.php
@@ -24,7 +24,8 @@
  * Logical representation of a mail message with all its data
  * and related functions
  *
- * @package    Mail
+ * @package    Framework
+ * @subpackage Storage
  * @author     Thomas Bruederli <roundcube at gmail.com>
  */
 class rcube_message
@@ -198,27 +199,29 @@ class rcube_message
      * Determine if the message contains a HTML part
      *
      * @param bool $recursive Enables checking in all levels of the structure
+     * @param bool $enriched  Enables checking for text/enriched parts too
      *
      * @return bool True if a HTML is available, False if not
      */
-    function has_html_part($recursive = true)
+    function has_html_part($recursive = true, $enriched = false)
     {
         // check all message parts
         foreach ($this->parts as $part) {
-            if ($part->mimetype == 'text/html') {
+            if ($part->mimetype == 'text/html' || ($enriched && $part->mimetype == 'text/enriched')) {
                 // Level check, we'll skip e.g. HTML attachments
                 if (!$recursive) {
                     $level = explode('.', $part->mime_id);
 
-                    // Level too high
-                    if (count($level) > 2) {
+                    // Skip if level too deep or part has a file name
+                    if (count($level) > 2 || $part->filename) {
                         continue;
                     }
 
                     // HTML part can be on the lower level, if not...
                     if (count($level) > 1) {
-                        // It can be an alternative or related message part
-                        $parent = $this->mime_parts[0];
+                        array_pop($level);
+                        $parent = $this->mime_parts[join('.', $level)];
+                        // ... parent isn't multipart/alternative or related
                         if ($parent->mimetype != 'multipart/alternative' && $parent->mimetype != 'multipart/related') {
                             continue;
                         }
@@ -269,10 +272,6 @@ class rcube_message
             else if ($part->mimetype == 'text/html') {
                 $out = $this->get_part_content($mime_id);
 
-                // remove special chars encoding
-                $trans = array_flip(get_html_translation_table(HTML_ENTITIES));
-                $out = strtr($out, $trans);
-
                 // create instance of html2text class
                 $txt = new html2text($out);
                 return $txt->get_text();
@@ -482,7 +481,7 @@ class rcube_message
                     if ($plugin['abort'])
                         continue;
 
-                    if ($part_mimetype == 'text/html') {
+                    if ($part_mimetype == 'text/html' && $mail_part->size) {
                         $got_html_part = true;
                     }
 
diff --git a/lib/ext/Roundcube/rcube_message_header.php b/lib/ext/Roundcube/rcube_message_header.php
index 378fb98..445d0bd 100644
--- a/lib/ext/Roundcube/rcube_message_header.php
+++ b/lib/ext/Roundcube/rcube_message_header.php
@@ -23,8 +23,9 @@
 /**
  * Struct representing an e-mail message header
  *
- * @package Mail
- * @author  Aleksander Machniak <alec at alec.pl>
+ * @package    Framework
+ * @subpackage Storage
+ * @author     Aleksander Machniak <alec at alec.pl>
  */
 class rcube_message_header
 {
@@ -194,6 +195,7 @@ class rcube_message_header
         'content-transfer-encoding' => 'encoding',
         'in-reply-to'               => 'in_reply_to',
         'content-type'              => 'ctype',
+        'charset'                   => 'charset',
         'references'                => 'references',
         'return-receipt-to'         => 'mdn_to',
         'disposition-notification-to' => 'mdn_to',
diff --git a/lib/ext/Roundcube/rcube_message_part.php b/lib/ext/Roundcube/rcube_message_part.php
index 80a019e..c9c9257 100644
--- a/lib/ext/Roundcube/rcube_message_part.php
+++ b/lib/ext/Roundcube/rcube_message_part.php
@@ -25,10 +25,10 @@
 /**
  * Class representing a message part
  *
- * @package    Mail
+ * @package    Framework
+ * @subpackage Storage
  * @author     Thomas Bruederli <roundcube at gmail.com>
  * @author     Aleksander Machniak <alec at alec.pl>
- * @version    2.0
  */
 class rcube_message_part
 {
diff --git a/lib/ext/Roundcube/rcube_mime.php b/lib/ext/Roundcube/rcube_mime.php
index d8e04a9..25ee31d 100644
--- a/lib/ext/Roundcube/rcube_mime.php
+++ b/lib/ext/Roundcube/rcube_mime.php
@@ -25,9 +25,10 @@
 /**
  * Class for parsing MIME messages
  *
- * @package Mail
- * @author  Thomas Bruederli <roundcube at gmail.com>
- * @author  Aleksander Machniak <alec at alec.pl>
+ * @package    Framework
+ * @subpackage Storage
+ * @author     Thomas Bruederli <roundcube at gmail.com>
+ * @author     Aleksander Machniak <alec at alec.pl>
  */
 class rcube_mime
 {
@@ -528,23 +529,24 @@ class rcube_mime
      *
      * @param string $text Text to wrap
      * @param int $length Length
+     * @param string $charset Character encoding of $text
      *
      * @return string Wrapped text
      */
-    public static function format_flowed($text, $length = 72)
+    public static function format_flowed($text, $length = 72, $charset=null)
     {
         $text = preg_split('/\r?\n/', $text);
 
         foreach ($text as $idx => $line) {
             if ($line != '-- ') {
-                if ($line[0] == '>' && preg_match('/^(>+)/', $line, $regs)) {
-                    $prefix = $regs[0];
-                    $level = strlen($prefix);
-                    $line  = rtrim(substr($line, $level));
-                    $line  = $prefix . self::wordwrap($line, $length - $level - 2, " \r\n$prefix ");
+                if ($line[0] == '>' && preg_match('/^(>+ {0,1})+/', $line, $regs)) {
+                    $level  = substr_count($regs[0], '>');
+                    $prefix = str_repeat('>', $level) . ' ';
+                    $line   = rtrim(substr($line, strlen($regs[0])));
+                    $line   = $prefix . self::wordwrap($line, $length - $level - 2, " \r\n$prefix", false, $charset);
                 }
                 else if ($line) {
-                    $line = self::wordwrap(rtrim($line), $length - 2, " \r\n");
+                    $line = self::wordwrap(rtrim($line), $length - 2, " \r\n", false, $charset);
                     // space-stuffing
                     $line = preg_replace('/(^|\r\n)(From| |>)/', '\\1 \\2', $line);
                 }
@@ -564,12 +566,16 @@ class rcube_mime
      * @param int    $width   Line width
      * @param string $break   Line separator
      * @param bool   $cut     Enable to cut word
+     * @param string $charset Charset of $string
      *
      * @return string Text
      */
-    public static function wordwrap($string, $width=75, $break="\n", $cut=false)
+    public static function wordwrap($string, $width=75, $break="\n", $cut=false, $charset=null)
     {
-        $para   = explode($break, $string);
+        if ($charset && function_exists('mb_internal_encoding'))
+            mb_internal_encoding($charset);
+
+        $para   = preg_split('/\r?\n/', $string);
         $string = '';
 
         while (count($para)) {
@@ -623,6 +629,9 @@ class rcube_mime
             }
         }
 
+        if ($charset && function_exists('mb_internal_encoding'))
+            mb_internal_encoding(RCMAIL_CHARSET);
+
         return $string;
     }
 
@@ -644,7 +653,7 @@ class rcube_mime
     {
         $mime_type = null;
         $mime_magic = rcube::get_instance()->config->get('mime_magic');
-        $mime_ext = @include RCMAIL_CONFIG_DIR . '/mimetypes.php';
+        $mime_ext = @include RCUBE_CONFIG_DIR . '/mimetypes.php';
 
         // use file name suffix with hard-coded mime-type map
         if (is_array($mime_ext) && $name) {
diff --git a/lib/ext/Roundcube/rcube_output.php b/lib/ext/Roundcube/rcube_output.php
deleted file mode 100644
index 5c582e6..0000000
--- a/lib/ext/Roundcube/rcube_output.php
+++ /dev/null
@@ -1,283 +0,0 @@
-<?php
-
-/*
- +-----------------------------------------------------------------------+
- | program/include/rcube_output.php                                      |
- |                                                                       |
- | This file is part of the Roundcube PHP suite                          |
- | 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.                |
- | See the README file for a full license statement.                     |
- | CONTENTS:                                                             |
- |   Abstract class for output generation                                |
- |                                                                       |
- +-----------------------------------------------------------------------+
- | Author: Thomas Bruederli <roundcube at gmail.com>                        |
- | Author: Aleksander Machniak <alec at alec.pl>                            |
- +-----------------------------------------------------------------------+
-*/
-
-/**
- * Class for output generation
- *
- * @package HTML
- */
-abstract class rcube_output
-{
-    public $browser;
-    public $type = 'html';
-    public $ajax_call = false;
-    public $framed = false;
-
-    protected $app;
-    protected $config;
-    protected $charset = RCMAIL_CHARSET;
-    protected $env = array();
-    protected $pagetitle = '';
-    protected $object_handlers = array();
-
-
-    /**
-     * Object constructor
-     */
-    public function __construct($task = null, $framed = false)
-    {
-        $this->app     = rcube::get_instance();
-        $this->config  = $this->app->config;
-        $this->browser = new rcube_browser();
-    }
-
-
-    /**
-     * Magic getter
-     */
-    public function __get($var)
-    {
-        // allow read-only access to $env
-        if ($var == 'env')
-            return $this->env;
-
-        return null;
-    }
-
-    /**
-     * Setter for page title
-     *
-     * @param string $title Page title
-     */
-    public function set_pagetitle($title)
-    {
-        $this->pagetitle = $title;
-    }
-
-
-    /**
-     * Setter for output charset.
-     * To be specified in a meta tag and sent as http-header
-     *
-     * @param string $charset Charset name
-     */
-    public function set_charset($charset)
-    {
-        $this->charset = $charset;
-    }
-
-
-    /**
-     * Getter for output charset
-     *
-     * @return string Output charset name
-     */
-    public function get_charset()
-    {
-        return $this->charset;
-    }
-
-
-    /**
-     * Getter for the current skin path property
-     */
-    public function get_skin_path()
-    {
-        return $this->config->get('skin_path');
-    }
-
-
-    /**
-     * Set environment variable
-     *
-     * @param string $name   Property name
-     * @param mixed  $value  Property value
-     */
-    public function set_env($name, $value)
-    {
-        $this->env[$name] = $value;
-    }
-
-
-    /**
-     * Environment variable getter.
-     *
-     * @param string $name  Property name
-     *
-     * @return mixed Property value
-     */
-    public function get_env($name)
-    {
-        return $this->env[$name];
-    }
-
-
-    /**
-     * Delete all stored env variables and commands
-     */
-    public function reset()
-    {
-        $this->env = array();
-        $this->object_handlers = array();
-        $this->pagetitle = '';
-    }
-
-
-    /**
-     * Call a client method
-     *
-     * @param string Method to call
-     * @param ... Additional arguments
-     */
-    abstract function command();
-
-
-    /**
-     * Add a localized label to the client environment
-     */
-    abstract function add_label();
-
-
-    /**
-     * Invoke display_message command
-     *
-     * @param string  $message  Message to display
-     * @param string  $type     Message type [notice|confirm|error]
-     * @param array   $vars     Key-value pairs to be replaced in localized text
-     * @param boolean $override Override last set message
-     * @param int     $timeout  Message displaying time in seconds
-     */
-    abstract function show_message($message, $type = 'notice', $vars = null, $override = true, $timeout = 0);
-
-
-    /**
-     * Redirect to a certain url.
-     *
-     * @param mixed $p     Either a string with the action or url parameters as key-value pairs
-     * @param int   $delay Delay in seconds
-     */
-    abstract function redirect($p = array(), $delay = 1);
-
-
-    /**
-     * Send output to the client.
-     */
-    abstract function send();
-
-
-    /**
-     * Register a template object handler
-     *
-     * @param  string Object name
-     * @param  string Function name to call
-     * @return void
-     */
-    public function add_handler($obj, $func)
-    {
-        $this->object_handlers[$obj] = $func;
-    }
-
-
-    /**
-     * Register a list of template object handlers
-     *
-     * @param  array Hash array with object=>handler pairs
-     * @return void
-     */
-    public function add_handlers($arr)
-    {
-        $this->object_handlers = array_merge($this->object_handlers, $arr);
-    }
-
-
-    /**
-     * Send HTTP headers to prevent caching a page
-     */
-    public function nocacheing_headers()
-    {
-        if (headers_sent()) {
-            return;
-        }
-
-        header("Expires: ".gmdate("D, d M Y H:i:s")." GMT");
-        header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
-
-        // Request browser to disable DNS prefetching (CVE-2010-0464)
-        header("X-DNS-Prefetch-Control: off");
-
-        // We need to set the following headers to make downloads work using IE in HTTPS mode.
-        if ($this->browser->ie && rcube_utils::https_check()) {
-            header('Pragma: private');
-            header("Cache-Control: private, must-revalidate");
-        }
-        else {
-            header("Cache-Control: private, no-cache, must-revalidate, post-check=0, pre-check=0");
-            header("Pragma: no-cache");
-        }
-    }
-
-    /**
-     * Send header with expire date 30 days in future
-     *
-     * @param int Expiration time in seconds
-     */
-    public function future_expire_header($offset = 2600000)
-    {
-        if (headers_sent())
-            return;
-
-        header("Expires: " . gmdate("D, d M Y H:i:s", time()+$offset) . " GMT");
-        header("Cache-Control: max-age=$offset");
-        header("Pragma: ");
-    }
-
-
-    /**
-     * Show error page and terminate script execution
-     *
-     * @param int    $code     Error code
-     * @param string $message  Error message
-     */
-    public function raise_error($code, $message)
-    {
-        // STUB: to be overloaded by specific output classes
-        fputs(STDERR, "Error $code: $message\n");
-        exit(-1);
-    }
-
-
-    /**
-     * Convert a variable into a javascript object notation
-     *
-     * @param mixed Input value
-     *
-     * @return string Serialized JSON string
-     */
-    public static function json_serialize($input)
-    {
-        $input = rcube_charset::clean($input);
-
-        // sometimes even using rcube_charset::clean() the input contains invalid UTF-8 sequences
-        // that's why we have @ here
-        return @json_encode($input);
-    }
-
-}
diff --git a/lib/ext/Roundcube/rcube_output_html.php b/lib/ext/Roundcube/rcube_output_html.php
deleted file mode 100644
index 6138e2a..0000000
--- a/lib/ext/Roundcube/rcube_output_html.php
+++ /dev/null
@@ -1,1672 +0,0 @@
-<?php
-
-/*
- +-----------------------------------------------------------------------+
- | program/include/rcubeoutput_html.php                                  |
- |                                                                       |
- | This file is part of the Roundcube Webmail client                     |
- | Copyright (C) 2006-2012, The Roundcube Dev Team                       |
- |                                                                       |
- | Licensed under the GNU General Public License version 3 or            |
- | any later version with exceptions for skins & plugins.                |
- | See the README file for a full license statement.                     |
- |                                                                       |
- | PURPOSE:                                                              |
- |   Class to handle HTML page output using a skin template.             |
- |                                                                       |
- +-----------------------------------------------------------------------+
- | Author: Thomas Bruederli <roundcube at gmail.com>                        |
- +-----------------------------------------------------------------------+
-*/
-
-
-/**
- * Class to create HTML page output using a skin template
- *
- * @package View
- */
-class rcube_output_html extends rcube_output
-{
-    public $type = 'html';
-
-    protected $message = null;
-    protected $js_env = array();
-    protected $js_labels = array();
-    protected $js_commands = array();
-    protected $plugin_skin_path;
-    protected $template_name;
-    protected $scripts_path = '';
-    protected $script_files = array();
-    protected $css_files = array();
-    protected $scripts = array();
-    protected $default_template = "<html>\n<head><title></title></head>\n<body></body>\n</html>";
-    protected $header = '';
-    protected $footer = '';
-    protected $body = '';
-    protected $base_path = '';
-
-    // deprecated names of templates used before 0.5
-    protected $deprecated_templates = array(
-        'contact'      => 'showcontact',
-        'contactadd'   => 'addcontact',
-        'contactedit'  => 'editcontact',
-        'identityedit' => 'editidentity',
-        'messageprint' => 'printmessage',
-    );
-
-    /**
-     * Constructor
-     *
-     * @todo   Replace $this->config with the real rcube_config object
-     */
-    public function __construct($task = null, $framed = false)
-    {
-        parent::__construct();
-
-        //$this->framed = $framed;
-        $this->set_env('task', $task);
-        $this->set_env('x_frame_options', $this->config->get('x_frame_options', 'sameorigin'));
-
-        // add cookie info
-        $this->set_env('cookie_domain', ini_get('session.cookie_domain'));
-        $this->set_env('cookie_path', ini_get('session.cookie_path'));
-        $this->set_env('cookie_secure', ini_get('session.cookie_secure'));
-
-        // load the correct skin (in case user-defined)
-        $skin = $this->config->get('skin');
-        $this->set_skin($skin);
-        $this->set_env('skin', $skin);
-
-        // add common javascripts
-        $this->add_script('var '.rcmail::JS_OBJECT_NAME.' = new rcube_webmail();', 'head_top');
-
-        // don't wait for page onload. Call init at the bottom of the page (delayed)
-        $this->add_script(rcmail::JS_OBJECT_NAME.'.init();', 'docready');
-
-        $this->scripts_path = 'program/js/';
-        $this->include_script('jquery.min.js');
-        $this->include_script('common.js');
-        $this->include_script('app.js');
-
-        // register common UI objects
-        $this->add_handlers(array(
-            'loginform'       => array($this, 'login_form'),
-            'preloader'       => array($this, 'preloader'),
-            'username'        => array($this, 'current_username'),
-            'message'         => array($this, 'message_container'),
-            'charsetselector' => array($this, 'charset_selector'),
-            'aboutcontent'    => array($this, 'about_content'),
-        ));
-    }
-
-
-    /**
-     * Set environment variable
-     *
-     * @param string Property name
-     * @param mixed Property value
-     * @param boolean True if this property should be added to client environment
-     */
-    public function set_env($name, $value, $addtojs = true)
-    {
-        $this->env[$name] = $value;
-        if ($addtojs || isset($this->js_env[$name])) {
-            $this->js_env[$name] = $value;
-        }
-    }
-
-
-    /**
-     * Getter for the current page title
-     *
-     * @return string The page title
-     */
-    protected function get_pagetitle()
-    {
-        if (!empty($this->pagetitle)) {
-            $title = $this->pagetitle;
-        }
-        else if ($this->env['task'] == 'login') {
-            $title = $this->app->gettext(array(
-                'name' => 'welcome',
-                'vars' => array('product' => $this->config->get('product_name')
-            )));
-        }
-        else {
-            $title = ucfirst($this->env['task']);
-        }
-
-        return $title;
-    }
-
-
-    /**
-     * Set skin
-     */
-    public function set_skin($skin)
-    {
-        $valid = false;
-
-        if (!empty($skin) && is_dir('skins/'.$skin) && is_readable('skins/'.$skin)) {
-            $skin_path = 'skins/'.$skin;
-            $valid = true;
-        }
-        else {
-            $skin_path = $this->config->get('skin_path');
-            if (!$skin_path) {
-                $skin_path = 'skins/' . rcube_config::DEFAULT_SKIN;
-            }
-            $valid = !$skin;
-        }
-
-        $this->config->set('skin_path', $skin_path);
-
-        return $valid;
-    }
-
-
-    /**
-     * Check if a specific template exists
-     *
-     * @param string Template name
-     * @return boolean True if template exists
-     */
-    public function template_exists($name)
-    {
-        $filename = $this->config->get('skin_path') . '/templates/' . $name . '.html';
-        return (is_file($filename) && is_readable($filename)) || ($this->deprecated_templates[$name] && $this->template_exists($this->deprecated_templates[$name]));
-    }
-
-
-    /**
-     * Register a GUI object to the client script
-     *
-     * @param  string Object name
-     * @param  string Object ID
-     * @return void
-     */
-    public function add_gui_object($obj, $id)
-    {
-        $this->add_script(rcmail::JS_OBJECT_NAME.".gui_object('$obj', '$id');");
-    }
-
-
-    /**
-     * Call a client method
-     *
-     * @param string Method to call
-     * @param ... Additional arguments
-     */
-    public function command()
-    {
-        $cmd = func_get_args();
-        if (strpos($cmd[0], 'plugin.') !== false)
-          $this->js_commands[] = array('triggerEvent', $cmd[0], $cmd[1]);
-        else
-          $this->js_commands[] = $cmd;
-    }
-
-
-    /**
-     * Add a localized label to the client environment
-     */
-    public function add_label()
-    {
-        $args = func_get_args();
-        if (count($args) == 1 && is_array($args[0]))
-          $args = $args[0];
-
-        foreach ($args as $name) {
-            $this->js_labels[$name] = $this->app->gettext($name);
-        }
-    }
-
-
-    /**
-     * Invoke display_message command
-     *
-     * @param string  $message  Message to display
-     * @param string  $type     Message type [notice|confirm|error]
-     * @param array   $vars     Key-value pairs to be replaced in localized text
-     * @param boolean $override Override last set message
-     * @param int     $timeout  Message display time in seconds
-     * @uses self::command()
-     */
-    public function show_message($message, $type='notice', $vars=null, $override=true, $timeout=0)
-    {
-        if ($override || !$this->message) {
-            if ($this->app->text_exists($message)) {
-                if (!empty($vars))
-                    $vars = array_map('Q', $vars);
-                $msgtext = $this->app->gettext(array('name' => $message, 'vars' => $vars));
-            }
-            else
-                $msgtext = $message;
-
-            $this->message = $message;
-            $this->command('display_message', $msgtext, $type, $timeout * 1000);
-        }
-    }
-
-
-    /**
-     * Delete all stored env variables and commands
-     */
-    public function reset()
-    {
-        parent::reset();
-        $this->js_env = array();
-        $this->js_labels = array();
-        $this->js_commands = array();
-        $this->script_files = array();
-        $this->scripts      = array();
-        $this->header       = '';
-        $this->footer       = '';
-        $this->body         = '';
-    }
-
-
-    /**
-     * Redirect to a certain url
-     *
-     * @param mixed $p     Either a string with the action or url parameters as key-value pairs
-     * @param int   $delay Delay in seconds
-     */
-    public function redirect($p = array(), $delay = 1)
-    {
-        $location = $this->app->url($p);
-        header('Location: ' . $location);
-        exit;
-    }
-
-
-    /**
-     * Send the request output to the client.
-     * This will either parse a skin tempalte or send an AJAX response
-     *
-     * @param string  Template name
-     * @param boolean True if script should terminate (default)
-     */
-    public function send($templ = null, $exit = true)
-    {
-        if ($templ != 'iframe') {
-            // prevent from endless loops
-            if ($exit != 'recur' && $this->app->plugins->is_processing('render_page')) {
-                rcube::raise_error(array('code' => 505, 'type' => 'php',
-                  'file' => __FILE__, 'line' => __LINE__,
-                  'message' => 'Recursion alert: ignoring output->send()'), true, false);
-                return;
-            }
-            $this->parse($templ, false);
-        }
-        else {
-            $this->framed = $templ == 'iframe' ? true : $this->framed;
-            $this->write();
-        }
-
-        // set output asap
-        ob_flush();
-        flush();
-
-        if ($exit) {
-            exit;
-        }
-    }
-
-
-    /**
-     * Process template and write to stdOut
-     *
-     * @param string $template HTML template content
-     */
-    public function write($template = '')
-    {
-        // unlock interface after iframe load
-        $unlock = preg_replace('/[^a-z0-9]/i', '', $_REQUEST['_unlock']);
-        if ($this->framed) {
-            array_unshift($this->js_commands, array('set_busy', false, null, $unlock));
-        }
-        else if ($unlock) {
-            array_unshift($this->js_commands, array('hide_message', $unlock));
-        }
-
-        if (!empty($this->script_files))
-          $this->set_env('request_token', $this->app->get_request_token());
-
-        // write all env variables to client
-        $js = $this->framed ? "if(window.parent) {\n" : '';
-        $js .= $this->get_js_commands() . ($this->framed ? ' }' : '');
-        $this->add_script($js, 'head_top');
-
-        // send clickjacking protection headers
-        $iframe = $this->framed || !empty($_REQUEST['_framed']);
-        if (!headers_sent() && ($xframe = $this->app->config->get('x_frame_options', 'sameorigin')))
-            header('X-Frame-Options: ' . ($iframe && $xframe == 'deny' ? 'sameorigin' : $xframe));
-
-        // call super method
-        $this->_write($template, $this->config->get('skin_path'));
-    }
-
-
-    /**
-     * Parse a specific skin template and deliver to stdout (or return)
-     *
-     * @param  string  Template name
-     * @param  boolean Exit script
-     * @param  boolean Don't write to stdout, return parsed content instead
-     *
-     * @link   http://php.net/manual/en/function.exit.php
-     */
-    function parse($name = 'main', $exit = true, $write = true)
-    {
-        $skin_path = $this->config->get('skin_path');
-        $plugin    = false;
-        $realname  = $name;
-        $temp      = explode('.', $name, 2);
-
-        $this->plugin_skin_path = null;
-        $this->template_name    = $realname;
-
-        if (count($temp) > 1) {
-            $plugin    = $temp[0];
-            $name      = $temp[1];
-            $skin_dir  = $plugin . '/skins/' . $this->config->get('skin');
-            $skin_path = $this->plugin_skin_path = $this->app->plugins->dir . $skin_dir;
-
-            // fallback to default skin
-            if (!is_dir($skin_path)) {
-                $skin_dir = $plugin . '/skins/default';
-                $skin_path = $this->plugin_skin_path = $this->app->plugins->dir . $skin_dir;
-            }
-        }
-
-        $path = "$skin_path/templates/$name.html";
-
-        if (!is_readable($path) && $this->deprecated_templates[$realname]) {
-            $path = "$skin_path/templates/".$this->deprecated_templates[$realname].".html";
-            if (is_readable($path))
-                rcube::raise_error(array('code' => 502, 'type' => 'php',
-                    'file' => __FILE__, 'line' => __LINE__,
-                    'message' => "Using deprecated template '".$this->deprecated_templates[$realname]
-                        ."' in $skin_path/templates. Please rename to '".$realname."'"),
-                true, false);
-        }
-
-        // read template file
-        if (($templ = @file_get_contents($path)) === false) {
-            rcube::raise_error(array(
-                'code' => 501,
-                'type' => 'php',
-                'line' => __LINE__,
-                'file' => __FILE__,
-                'message' => 'Error loading template for '.$realname
-                ), true, $write);
-            return false;
-        }
-
-        // replace all path references to plugins/... with the configured plugins dir
-        // and /this/ to the current plugin skin directory
-        if ($plugin) {
-            $templ = preg_replace(array('/\bplugins\//', '/(["\']?)\/this\//'), array($this->app->plugins->url, '\\1'.$this->app->plugins->url.$skin_dir.'/'), $templ);
-        }
-
-        // parse for specialtags
-        $output = $this->parse_conditions($templ);
-        $output = $this->parse_xml($output);
-
-        // trigger generic hook where plugins can put additional content to the page
-        $hook = $this->app->plugins->exec_hook("render_page", array('template' => $realname, 'content' => $output));
-
-        // save some memory
-        $output = $hook['content'];
-        unset($hook['content']);
-
-        $output = $this->parse_with_globals($output);
-
-        // make sure all <form> tags have a valid request token
-        $output = preg_replace_callback('/<form\s+([^>]+)>/Ui', array($this, 'alter_form_tag'), $output);
-        $this->footer = preg_replace_callback('/<form\s+([^>]+)>/Ui', array($this, 'alter_form_tag'), $this->footer);
-
-        if ($write) {
-            // add debug console
-            if ($realname != 'error' && ($this->config->get('debug_level') & 8)) {
-                $this->add_footer('<div id="console" style="position:absolute;top:5px;left:5px;width:405px;padding:2px;background:white;z-index:9000;display:none">
-                    <a href="#toggle" onclick="con=$(\'#dbgconsole\');con[con.is(\':visible\')?\'hide\':\'show\']();return false">console</a>
-                    <textarea name="console" id="dbgconsole" rows="20" cols="40" style="display:none;width:400px;border:none;font-size:10px" spellcheck="false"></textarea></div>'
-                );
-                $this->add_script(
-                    "if (!window.console || !window.console.log) {\n".
-                    "  window.console = new rcube_console();\n".
-                    "  $('#console').show();\n".
-                    "}", 'foot');
-            }
-            $this->write(trim($output));
-        }
-        else {
-            return $output;
-        }
-
-        if ($exit) {
-            exit;
-        }
-    }
-
-
-    /**
-     * Return executable javascript code for all registered commands
-     *
-     * @return string $out
-     */
-    protected function get_js_commands()
-    {
-        $out = '';
-        if (!$this->framed && !empty($this->js_env)) {
-            $out .= rcmail::JS_OBJECT_NAME . '.set_env('.self::json_serialize($this->js_env).");\n";
-        }
-        if (!empty($this->js_labels)) {
-            $this->command('add_label', $this->js_labels);
-        }
-        foreach ($this->js_commands as $i => $args) {
-            $method = array_shift($args);
-            foreach ($args as $i => $arg) {
-                $args[$i] = self::json_serialize($arg);
-            }
-            $parent = $this->framed || preg_match('/^parent\./', $method);
-            $out .= sprintf(
-                "%s.%s(%s);\n",
-                ($parent ? 'if(window.parent && parent.'.rcmail::JS_OBJECT_NAME.') parent.' : '') . rcmail::JS_OBJECT_NAME,
-                preg_replace('/^parent\./', '', $method),
-                implode(',', $args)
-            );
-        }
-
-        return $out;
-    }
-
-
-    /**
-     * Make URLs starting with a slash point to skin directory
-     *
-     * @param  string Input string
-     * @return string
-     */
-    public function abs_url($str)
-    {
-        if ($str[0] == '/')
-            return $this->config->get('skin_path') . $str;
-        else
-            return $str;
-    }
-
-
-    /**
-     * Show error page and terminate script execution
-     *
-     * @param int    $code     Error code
-     * @param string $message  Error message
-     */
-    public function raise_error($code, $message)
-    {
-        global $__page_content, $ERROR_CODE, $ERROR_MESSAGE;
-
-        $ERROR_CODE    = $code;
-        $ERROR_MESSAGE = $message;
-
-        include INSTALL_PATH . 'program/steps/utils/error.inc';
-        exit;
-    }
-
-
-    /*****  Template parsing methods  *****/
-
-    /**
-     * Replace all strings ($varname)
-     * with the content of the according global variable.
-     */
-    protected function parse_with_globals($input)
-    {
-        $GLOBALS['__version']   = html::quote(RCMAIL_VERSION);
-        $GLOBALS['__comm_path'] = html::quote($this->app->comm_path);
-        $GLOBALS['__skin_path'] = html::quote($this->config->get('skin_path'));
-
-        return preg_replace_callback('/\$(__[a-z0-9_\-]+)/',
-            array($this, 'globals_callback'), $input);
-    }
-
-
-    /**
-     * Callback funtion for preg_replace_callback() in parse_with_globals()
-     */
-    protected function globals_callback($matches)
-    {
-        return $GLOBALS[$matches[1]];
-    }
-
-
-    /**
-     * Public wrapper to dipp into template parsing.
-     *
-     * @param  string $input
-     * @return string
-     * @uses   rcube_output_html::parse_xml()
-     * @since  0.1-rc1
-     */
-    public function just_parse($input)
-    {
-        return $this->parse_xml($input);
-    }
-
-
-    /**
-     * Parse for conditional tags
-     *
-     * @param  string $input
-     * @return string
-     */
-    protected function parse_conditions($input)
-    {
-        $matches = preg_split('/<roundcube:(if|elseif|else|endif)\s+([^>]+)>\n?/is', $input, 2, PREG_SPLIT_DELIM_CAPTURE);
-        if ($matches && count($matches) == 4) {
-            if (preg_match('/^(else|endif)$/i', $matches[1])) {
-                return $matches[0] . $this->parse_conditions($matches[3]);
-            }
-            $attrib = html::parse_attrib_string($matches[2]);
-            if (isset($attrib['condition'])) {
-                $condmet = $this->check_condition($attrib['condition']);
-                $submatches = preg_split('/<roundcube:(elseif|else|endif)\s+([^>]+)>\n?/is', $matches[3], 2, PREG_SPLIT_DELIM_CAPTURE);
-                if ($condmet) {
-                    $result = $submatches[0];
-                    $result.= ($submatches[1] != 'endif' ? preg_replace('/.*<roundcube:endif\s+[^>]+>\n?/Uis', '', $submatches[3], 1) : $submatches[3]);
-                }
-                else {
-                    $result = "<roundcube:$submatches[1] $submatches[2]>" . $submatches[3];
-                }
-                return $matches[0] . $this->parse_conditions($result);
-            }
-            rcube::raise_error(array(
-                'code' => 500,
-                'type' => 'php',
-                'line' => __LINE__,
-                'file' => __FILE__,
-                'message' => "Unable to parse conditional tag " . $matches[2]
-            ), true, false);
-        }
-        return $input;
-    }
-
-
-    /**
-     * Determines if a given condition is met
-     *
-     * @todo   Get rid off eval() once I understand what this does.
-     * @todo   Extend this to allow real conditions, not just "set"
-     * @param  string Condition statement
-     * @return boolean True if condition is met, False if not
-     */
-    protected function check_condition($condition)
-    {
-        return eval("return (".$this->parse_expression($condition).");");
-    }
-
-
-    /**
-     * Inserts hidden field with CSRF-prevention-token into POST forms
-     */
-    protected function alter_form_tag($matches)
-    {
-        $out    = $matches[0];
-        $attrib = html::parse_attrib_string($matches[1]);
-
-        if (strtolower($attrib['method']) == 'post') {
-            $hidden = new html_hiddenfield(array('name' => '_token', 'value' => $this->app->get_request_token()));
-            $out .= "\n" . $hidden->show();
-        }
-
-        return $out;
-    }
-
-
-    /**
-     * Parses expression and replaces variables
-     *
-     * @param  string Expression statement
-     * @return string Expression value
-     */
-    protected function parse_expression($expression)
-    {
-        return preg_replace(
-            array(
-                '/session:([a-z0-9_]+)/i',
-                '/config:([a-z0-9_]+)(:([a-z0-9_]+))?/i',
-                '/env:([a-z0-9_]+)/i',
-                '/request:([a-z0-9_]+)/i',
-                '/cookie:([a-z0-9_]+)/i',
-                '/browser:([a-z0-9_]+)/i',
-                '/template:name/i',
-            ),
-            array(
-                "\$_SESSION['\\1']",
-                "\$this->app->config->get('\\1',get_boolean('\\3'))",
-                "\$this->env['\\1']",
-                "rcube_utils::get_input_value('\\1', rcube_utils::INPUT_GPC)",
-                "\$_COOKIE['\\1']",
-                "\$this->browser->{'\\1'}",
-                $this->template_name,
-            ),
-            $expression);
-    }
-
-
-    /**
-     * Search for special tags in input and replace them
-     * with the appropriate content
-     *
-     * @param  string Input string to parse
-     * @return string Altered input string
-     * @todo   Use DOM-parser to traverse template HTML
-     * @todo   Maybe a cache.
-     */
-    protected function parse_xml($input)
-    {
-        return preg_replace_callback('/<roundcube:([-_a-z]+)\s+((?:[^>]|\\\\>)+)(?<!\\\\)>/Ui', array($this, 'xml_command'), $input);
-    }
-
-
-    /**
-     * Callback function for parsing an xml command tag
-     * and turn it into real html content
-     *
-     * @param  array Matches array of preg_replace_callback
-     * @return string Tag/Object content
-     */
-    protected function xml_command($matches)
-    {
-        $command = strtolower($matches[1]);
-        $attrib  = html::parse_attrib_string($matches[2]);
-
-        // empty output if required condition is not met
-        if (!empty($attrib['condition']) && !$this->check_condition($attrib['condition'])) {
-            return '';
-        }
-
-        // execute command
-        switch ($command) {
-            // return a button
-            case 'button':
-                if ($attrib['name'] || $attrib['command']) {
-                    return $this->button($attrib);
-                }
-                break;
-
-            // frame
-            case 'frame':
-                return $this->frame($attrib);
-                break;
-
-            // show a label
-            case 'label':
-                if ($attrib['name'] || $attrib['command']) {
-                    // @FIXME: 'noshow' is useless, remove?
-                    if ($attrib['noshow']) {
-                        return '';
-                    }
-
-                    $vars = $attrib + array('product' => $this->config->get('product_name'));
-                    unset($vars['name'], $vars['command']);
-
-                    $label   = $this->app->gettext($attrib + array('vars' => $vars));
-                    $quoting = !empty($attrib['quoting']) ? strtolower($attrib['quoting']) : (get_boolean((string)$attrib['html']) ? 'no' : '');
-
-                    switch ($quoting) {
-                        case 'no':
-                        case 'raw':
-                            break;
-                        case 'javascript':
-                        case 'js':
-                            $label = rcmail::JQ($label);
-                            break;
-                        default:
-                            $label = html::quote($label);
-                            break;
-                    }
-
-                    return $label;
-                }
-                break;
-
-            // include a file
-            case 'include':
-                if (!$this->plugin_skin_path || !is_file($path = realpath($this->plugin_skin_path . $attrib['file'])))
-                    $path = realpath(($attrib['skin_path'] ? $attrib['skin_path'] : $this->config->get('skin_path')).$attrib['file']);
-
-                if (is_readable($path)) {
-                    if ($this->config->get('skin_include_php')) {
-                        $incl = $this->include_php($path);
-                    }
-                    else {
-                      $incl = file_get_contents($path);
-                    }
-                    $incl = $this->parse_conditions($incl);
-                    return $this->parse_xml($incl);
-                }
-                break;
-
-            case 'plugin.include':
-                $hook = $this->app->plugins->exec_hook("template_plugin_include", $attrib);
-                return $hook['content'];
-                break;
-
-            // define a container block
-            case 'container':
-                if ($attrib['name'] && $attrib['id']) {
-                    $this->command('gui_container', $attrib['name'], $attrib['id']);
-                    // let plugins insert some content here
-                    $hook = $this->app->plugins->exec_hook("template_container", $attrib);
-                    return $hook['content'];
-                }
-                break;
-
-            // return code for a specific application object
-            case 'object':
-                $object = strtolower($attrib['name']);
-                $content = '';
-
-                // we are calling a class/method
-                if (($handler = $this->object_handlers[$object]) && is_array($handler)) {
-                    if ((is_object($handler[0]) && method_exists($handler[0], $handler[1])) ||
-                    (is_string($handler[0]) && class_exists($handler[0])))
-                    $content = call_user_func($handler, $attrib);
-                }
-                // execute object handler function
-                else if (function_exists($handler)) {
-                    $content = call_user_func($handler, $attrib);
-                }
-                else if ($object == 'doctype') {
-                    $content = html::doctype($attrib['value']);
-                }
-                else if ($object == 'logo') {
-                    $attrib += array('alt' => $this->xml_command(array('', 'object', 'name="productname"')));
-                    if ($logo = $this->config->get('skin_logo'))
-                        $attrib['src'] = $logo;
-                    $content = html::img($attrib);
-                }
-                else if ($object == 'productname') {
-                    $name = $this->config->get('product_name', 'Roundcube Webmail');
-                    $content = html::quote($name);
-                }
-                else if ($object == 'version') {
-                    $ver = (string)RCMAIL_VERSION;
-                    if (is_file(INSTALL_PATH . '.svn/entries')) {
-                        if (preg_match('/Revision:\s(\d+)/', @shell_exec('svn info'), $regs))
-                          $ver .= ' [SVN r'.$regs[1].']';
-                    }
-                    else if (is_file(INSTALL_PATH . '.git/index')) {
-                        if (preg_match('/Date:\s+([^\n]+)/', @shell_exec('git log -1'), $regs)) {
-                            if ($date = date('Ymd.Hi', strtotime($regs[1]))) {
-                                $ver .= ' [GIT '.$date.']';
-                            }
-                        }
-                    }
-                    $content = html::quote($ver);
-                }
-                else if ($object == 'steptitle') {
-                  $content = html::quote($this->get_pagetitle());
-                }
-                else if ($object == 'pagetitle') {
-                    if ($this->config->get('devel_mode') && !empty($_SESSION['username']))
-                        $title = $_SESSION['username'].' :: ';
-                    else if ($prod_name = $this->config->get('product_name'))
-                        $title = $prod_name . ' :: ';
-                    else
-                        $title = '';
-                    $title .= $this->get_pagetitle();
-                    $content = html::quote($title);
-                }
-
-                // exec plugin hooks for this template object
-                $hook = $this->app->plugins->exec_hook("template_object_$object", $attrib + array('content' => $content));
-                return $hook['content'];
-
-            // return code for a specified eval expression
-            case 'exp':
-                $value = $this->parse_expression($attrib['expression']);
-                return eval("return html::quote($value);");
-
-            // return variable
-            case 'var':
-                $var = explode(':', $attrib['name']);
-                $name = $var[1];
-                $value = '';
-
-                switch ($var[0]) {
-                    case 'env':
-                        $value = $this->env[$name];
-                        break;
-                    case 'config':
-                        $value = $this->config->get($name);
-                        if (is_array($value) && $value[$_SESSION['storage_host']]) {
-                            $value = $value[$_SESSION['storage_host']];
-                        }
-                        break;
-                    case 'request':
-                        $value = rcube_utils::get_input_value($name, rcube_utils::INPUT_GPC);
-                        break;
-                    case 'session':
-                        $value = $_SESSION[$name];
-                        break;
-                    case 'cookie':
-                        $value = htmlspecialchars($_COOKIE[$name]);
-                        break;
-                    case 'browser':
-                        $value = $this->browser->{$name};
-                        break;
-                }
-
-                if (is_array($value)) {
-                    $value = implode(', ', $value);
-                }
-
-                return html::quote($value);
-                break;
-        }
-        return '';
-    }
-
-
-    /**
-     * Include a specific file and return it's contents
-     *
-     * @param string File path
-     * @return string Contents of the processed file
-     */
-    protected function include_php($file)
-    {
-        ob_start();
-        include $file;
-        $out = ob_get_contents();
-        ob_end_clean();
-
-        return $out;
-    }
-
-
-    /**
-     * Create and register a button
-     *
-     * @param  array Named button attributes
-     * @return string HTML button
-     * @todo   Remove all inline JS calls and use jQuery instead.
-     * @todo   Remove all sprintf()'s - they are pretty, but also slow.
-     */
-    public function button($attrib)
-    {
-        static $s_button_count = 100;
-
-        // these commands can be called directly via url
-        $a_static_commands = array('compose', 'list', 'preferences', 'folders', 'identities');
-
-        if (!($attrib['command'] || $attrib['name'])) {
-            return '';
-        }
-
-        // try to find out the button type
-        if ($attrib['type']) {
-            $attrib['type'] = strtolower($attrib['type']);
-        }
-        else {
-            $attrib['type'] = ($attrib['image'] || $attrib['imagepas'] || $attrib['imageact']) ? 'image' : 'link';
-        }
-
-        $command = $attrib['command'];
-
-        if ($attrib['task'])
-          $command = $attrib['task'] . '.' . $command;
-
-        if (!$attrib['image']) {
-            $attrib['image'] = $attrib['imagepas'] ? $attrib['imagepas'] : $attrib['imageact'];
-        }
-
-        if (!$attrib['id']) {
-            $attrib['id'] =  sprintf('rcmbtn%d', $s_button_count++);
-        }
-        // get localized text for labels and titles
-        if ($attrib['title']) {
-            $attrib['title'] = html::quote($this->app->gettext($attrib['title'], $attrib['domain']));
-        }
-        if ($attrib['label']) {
-            $attrib['label'] = html::quote($this->app->gettext($attrib['label'], $attrib['domain']));
-        }
-        if ($attrib['alt']) {
-            $attrib['alt'] = html::quote($this->app->gettext($attrib['alt'], $attrib['domain']));
-        }
-
-        // set title to alt attribute for IE browsers
-        if ($this->browser->ie && !$attrib['title'] && $attrib['alt']) {
-            $attrib['title'] = $attrib['alt'];
-        }
-
-        // add empty alt attribute for XHTML compatibility
-        if (!isset($attrib['alt'])) {
-            $attrib['alt'] = '';
-        }
-
-        // register button in the system
-        if ($attrib['command']) {
-            $this->add_script(sprintf(
-                "%s.register_button('%s', '%s', '%s', '%s', '%s', '%s');",
-                rcmail::JS_OBJECT_NAME,
-                $command,
-                $attrib['id'],
-                $attrib['type'],
-                $attrib['imageact'] ? $this->abs_url($attrib['imageact']) : $attrib['classact'],
-                $attrib['imagesel'] ? $this->abs_url($attrib['imagesel']) : $attrib['classsel'],
-                $attrib['imageover'] ? $this->abs_url($attrib['imageover']) : ''
-            ));
-
-            // make valid href to specific buttons
-            if (in_array($attrib['command'], rcmail::$main_tasks)) {
-                $attrib['href']    = $this->app->url(array('task' => $attrib['command']));
-                $attrib['onclick'] = sprintf("%s.command('switch-task','%s',null,event); return false", rcmail::JS_OBJECT_NAME, $attrib['command']);
-            }
-            else if ($attrib['task'] && in_array($attrib['task'], rcmail::$main_tasks)) {
-                $attrib['href'] = $this->app->url(array('action' => $attrib['command'], 'task' => $attrib['task']));
-            }
-            else if (in_array($attrib['command'], $a_static_commands)) {
-                $attrib['href'] = $this->app->url(array('action' => $attrib['command']));
-            }
-            else if ($attrib['command'] == 'permaurl' && !empty($this->env['permaurl'])) {
-              $attrib['href'] = $this->env['permaurl'];
-            }
-        }
-
-        // overwrite attributes
-        if (!$attrib['href']) {
-            $attrib['href'] = '#';
-        }
-        if ($attrib['task']) {
-            if ($attrib['classact'])
-                $attrib['class'] = $attrib['classact'];
-        }
-        else if ($command && !$attrib['onclick']) {
-            $attrib['onclick'] = sprintf(
-                "return %s.command('%s','%s',this,event)",
-                rcmail::JS_OBJECT_NAME,
-                $command,
-                $attrib['prop']
-            );
-        }
-
-        $out = '';
-
-        // generate image tag
-        if ($attrib['type'] == 'image') {
-            $attrib_str = html::attrib_string(
-                $attrib,
-                array(
-                    'style', 'class', 'id', 'width', 'height', 'border', 'hspace',
-                    'vspace', 'align', 'alt', 'tabindex', 'title'
-                )
-            );
-            $btn_content = sprintf('<img src="%s"%s />', $this->abs_url($attrib['image']), $attrib_str);
-            if ($attrib['label']) {
-                $btn_content .= ' '.$attrib['label'];
-            }
-            $link_attrib = array('href', 'onclick', 'onmouseover', 'onmouseout', 'onmousedown', 'onmouseup', 'target');
-        }
-        else if ($attrib['type'] == 'link') {
-            $btn_content = isset($attrib['content']) ? $attrib['content'] : ($attrib['label'] ? $attrib['label'] : $attrib['command']);
-            $link_attrib = array('href', 'onclick', 'title', 'id', 'class', 'style', 'tabindex', 'target');
-            if ($attrib['innerclass'])
-                $btn_content = html::span($attrib['innerclass'], $btn_content);
-        }
-        else if ($attrib['type'] == 'input') {
-            $attrib['type'] = 'button';
-
-            if ($attrib['label']) {
-                $attrib['value'] = $attrib['label'];
-            }
-            if ($attrib['command']) {
-              $attrib['disabled'] = 'disabled';
-            }
-
-            $out = html::tag('input', $attrib, null, array('type', 'value', 'onclick', 'id', 'class', 'style', 'tabindex', 'disabled'));
-        }
-
-        // generate html code for button
-        if ($btn_content) {
-            $attrib_str = html::attrib_string($attrib, $link_attrib);
-            $out = sprintf('<a%s>%s</a>', $attrib_str, $btn_content);
-        }
-
-        return $out;
-    }
-
-
-    /**
-     * Link an external script file
-     *
-     * @param string File URL
-     * @param string Target position [head|foot]
-     */
-    public function include_script($file, $position='head')
-    {
-        static $sa_files = array();
-
-        if (!preg_match('|^https?://|i', $file) && $file[0] != '/') {
-            $file = $this->scripts_path . $file;
-            if ($fs = @filemtime($file)) {
-                $file .= '?s=' . $fs;
-            }
-        }
-
-        if (in_array($file, $sa_files)) {
-            return;
-        }
-
-        $sa_files[] = $file;
-
-        if (!is_array($this->script_files[$position])) {
-            $this->script_files[$position] = array();
-        }
-
-        $this->script_files[$position][] = $file;
-    }
-
-
-    /**
-     * Add inline javascript code
-     *
-     * @param string JS code snippet
-     * @param string Target position [head|head_top|foot]
-     */
-    public function add_script($script, $position='head')
-    {
-        if (!isset($this->scripts[$position])) {
-            $this->scripts[$position] = "\n" . rtrim($script);
-        }
-        else {
-            $this->scripts[$position] .= "\n" . rtrim($script);
-        }
-    }
-
-
-    /**
-     * Link an external css file
-     *
-     * @param string File URL
-     */
-    public function include_css($file)
-    {
-        $this->css_files[] = $file;
-    }
-
-
-    /**
-     * Add HTML code to the page header
-     *
-     * @param string $str HTML code
-     */
-    public function add_header($str)
-    {
-        $this->header .= "\n" . $str;
-    }
-
-
-    /**
-     * Add HTML code to the page footer
-     * To be added right befor </body>
-     *
-     * @param string $str HTML code
-     */
-    public function add_footer($str)
-    {
-        $this->footer .= "\n" . $str;
-    }
-
-
-    /**
-     * Process template and write to stdOut
-     *
-     * @param string HTML template
-     * @param string Base for absolute paths
-     */
-    public function _write($templ = '', $base_path = '')
-    {
-        $output = empty($templ) ? $this->default_template : trim($templ);
-
-        // set default page title
-        if (empty($this->pagetitle)) {
-            $this->pagetitle = 'Roundcube Mail';
-        }
-
-        // replace specialchars in content
-        $page_title  = html::quote($this->pagetitle);
-        $page_header = '';
-        $page_footer = '';
-
-        // include meta tag with charset
-        if (!empty($this->charset)) {
-            if (!headers_sent()) {
-                header('Content-Type: text/html; charset=' . $this->charset);
-            }
-            $page_header = '<meta http-equiv="content-type"';
-            $page_header.= ' content="text/html; charset=';
-            $page_header.= $this->charset . '" />'."\n";
-        }
-
-        // definition of the code to be placed in the document header and footer
-        if (is_array($this->script_files['head'])) {
-            foreach ($this->script_files['head'] as $file) {
-                $page_header .= html::script($file);
-            }
-        }
-
-        $head_script = $this->scripts['head_top'] . $this->scripts['head'];
-        if (!empty($head_script)) {
-            $page_header .= html::script(array(), $head_script);
-        }
-
-        if (!empty($this->header)) {
-            $page_header .= $this->header;
-        }
-
-        // put docready commands into page footer
-        if (!empty($this->scripts['docready'])) {
-            $this->add_script('$(document).ready(function(){ ' . $this->scripts['docready'] . "\n});", 'foot');
-        }
-
-        if (is_array($this->script_files['foot'])) {
-            foreach ($this->script_files['foot'] as $file) {
-                $page_footer .= html::script($file);
-            }
-        }
-
-        if (!empty($this->footer)) {
-            $page_footer .= $this->footer . "\n";
-        }
-
-        if (!empty($this->scripts['foot'])) {
-            $page_footer .= html::script(array(), $this->scripts['foot']);
-        }
-
-        // find page header
-        if ($hpos = stripos($output, '</head>')) {
-            $page_header .= "\n";
-        }
-        else {
-            if (!is_numeric($hpos)) {
-                $hpos = stripos($output, '<body');
-            }
-            if (!is_numeric($hpos) && ($hpos = stripos($output, '<html'))) {
-                while ($output[$hpos] != '>') {
-                    $hpos++;
-                }
-                $hpos++;
-            }
-            $page_header = "<head>\n<title>$page_title</title>\n$page_header\n</head>\n";
-        }
-
-        // add page hader
-        if ($hpos) {
-            $output = substr_replace($output, $page_header, $hpos, 0);
-        }
-        else {
-            $output = $page_header . $output;
-        }
-
-        // add page footer
-        if (($fpos = strripos($output, '</body>')) || ($fpos = strripos($output, '</html>'))) {
-            $output = substr_replace($output, $page_footer."\n", $fpos, 0);
-        }
-        else {
-            $output .= "\n".$page_footer;
-        }
-
-        // add css files in head, before scripts, for speed up with parallel downloads
-        if (!empty($this->css_files) && 
-            (($pos = stripos($output, '<script ')) || ($pos = stripos($output, '</head>')))
-        ) {
-            $css = '';
-            foreach ($this->css_files as $file) {
-                $css .= html::tag('link', array('rel' => 'stylesheet',
-                    'type' => 'text/css', 'href' => $file, 'nl' => true));
-            }
-            $output = substr_replace($output, $css, $pos, 0);
-        }
-
-        $this->base_path = $base_path;
-
-        // correct absolute paths in images and other tags
-        // add timestamp to .js and .css filename
-        $output = preg_replace_callback(
-            '!(src|href|background)=(["\']?)([a-z0-9/_.-]+)(["\'\s>])!i',
-            array($this, 'file_callback'), $output);
-
-        // trigger hook with final HTML content to be sent
-        $hook = $this->app->plugins->exec_hook("send_page", array('content' => $output));
-        if (!$hook['abort']) {
-            if ($this->charset != RCMAIL_CHARSET) {
-                echo rcube_charset::convert($hook['content'], RCMAIL_CHARSET, $this->charset);
-            }
-            else {
-                echo $hook['content'];
-            }
-        }
-    }
-
-
-    /**
-     * Callback function for preg_replace_callback in write()
-     *
-     * @return string Parsed string
-     */
-    protected function file_callback($matches)
-    {
-        $file = $matches[3];
-
-        // correct absolute paths
-        if ($file[0] == '/') {
-            $file = $this->base_path . $file;
-        }
-
-        // add file modification timestamp
-        if (preg_match('/\.(js|css)$/', $file)) {
-            if ($fs = @filemtime($file)) {
-                $file .= '?s=' . $fs;
-            }
-        }
-
-        return $matches[1] . '=' . $matches[2] . $file . $matches[4];
-    }
-
-
-    /**
-     * 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 **************  */
-
-
-    /**
-     * Create a form tag with the necessary hidden fields
-     *
-     * @param array Named tag parameters
-     * @return string HTML code for the form
-     */
-    public function form_tag($attrib, $content = null)
-    {
-      if ($this->framed || !empty($_REQUEST['_framed'])) {
-        $hiddenfield = new html_hiddenfield(array('name' => '_framed', 'value' => '1'));
-        $hidden = $hiddenfield->show();
-      }
-
-      if (!$content)
-        $attrib['noclose'] = true;
-
-      return html::tag('form',
-        $attrib + array('action' => "./", 'method' => "get"),
-        $hidden . $content,
-        array('id','class','style','name','method','action','enctype','onsubmit'));
-    }
-
-
-    /**
-     * Build a form tag with a unique request token
-     *
-     * @param array Named tag parameters including 'action' and 'task' values which will be put into hidden fields
-     * @param string Form content
-     * @return string HTML code for the form
-     */
-    public function request_form($attrib, $content = '')
-    {
-        $hidden = new html_hiddenfield();
-        if ($attrib['task']) {
-            $hidden->add(array('name' => '_task', 'value' => $attrib['task']));
-        }
-        if ($attrib['action']) {
-            $hidden->add(array('name' => '_action', 'value' => $attrib['action']));
-        }
-
-        unset($attrib['task'], $attrib['request']);
-        $attrib['action'] = './';
-
-        // we already have a <form> tag
-        if ($attrib['form']) {
-            if ($this->framed || !empty($_REQUEST['_framed']))
-                $hidden->add(array('name' => '_framed', 'value' => '1'));
-            return $hidden->show() . $content;
-        }
-        else
-            return $this->form_tag($attrib, $hidden->show() . $content);
-    }
-
-
-    /**
-     * GUI object 'username'
-     * Showing IMAP username of the current session
-     *
-     * @param array Named tag parameters (currently not used)
-     * @return string HTML code for the gui object
-     */
-    public function current_username($attrib)
-    {
-        static $username;
-
-        // alread fetched
-        if (!empty($username)) {
-            return $username;
-        }
-
-        // Current username is an e-mail address
-        if (strpos($_SESSION['username'], '@')) {
-            $username = $_SESSION['username'];
-        }
-        // get e-mail address from default identity
-        else if ($sql_arr = $this->app->user->get_identity()) {
-            $username = $sql_arr['email'];
-        }
-        else {
-            $username = $this->app->user->get_username();
-        }
-
-        return rcube_utils::idn_to_utf8($username);
-    }
-
-
-    /**
-     * GUI object 'loginform'
-     * Returns code for the webmail login form
-     *
-     * @param array Named parameters
-     * @return string HTML code for the gui object
-     */
-    protected function login_form($attrib)
-    {
-        $default_host = $this->config->get('default_host');
-        $autocomplete = (int) $this->config->get('login_autocomplete');
-
-        $_SESSION['temp'] = true;
-
-        // save original url
-        $url = rcube_utils::get_input_value('_url', rcube_utils::INPUT_POST);
-        if (empty($url) && !preg_match('/_(task|action)=logout/', $_SERVER['QUERY_STRING']))
-            $url = $_SERVER['QUERY_STRING'];
-
-        // Disable autocapitalization on iPad/iPhone (#1488609)
-        $attrib['autocapitalize'] = 'off';
-
-        // set atocomplete attribute
-        $user_attrib = $autocomplete > 0 ? array() : array('autocomplete' => 'off');
-        $host_attrib = $autocomplete > 0 ? array() : array('autocomplete' => 'off');
-        $pass_attrib = $autocomplete > 1 ? array() : array('autocomplete' => 'off');
-
-        $input_task   = new html_hiddenfield(array('name' => '_task', 'value' => 'login'));
-        $input_action = new html_hiddenfield(array('name' => '_action', 'value' => 'login'));
-        $input_tzone  = new html_hiddenfield(array('name' => '_timezone', 'id' => 'rcmlogintz', 'value' => '_default_'));
-        $input_dst    = new html_hiddenfield(array('name' => '_dstactive', 'id' => 'rcmlogindst', 'value' => '_default_'));
-        $input_url    = new html_hiddenfield(array('name' => '_url', 'id' => 'rcmloginurl', 'value' => $url));
-        $input_user   = new html_inputfield(array('name' => '_user', 'id' => 'rcmloginuser')
-            + $attrib + $user_attrib);
-        $input_pass   = new html_passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd')
-            + $attrib + $pass_attrib);
-        $input_host   = null;
-
-        if (is_array($default_host) && count($default_host) > 1) {
-            $input_host = new html_select(array('name' => '_host', 'id' => 'rcmloginhost'));
-
-            foreach ($default_host as $key => $value) {
-                if (!is_array($value)) {
-                    $input_host->add($value, (is_numeric($key) ? $value : $key));
-                }
-                else {
-                    $input_host = null;
-                    break;
-                }
-            }
-        }
-        else if (is_array($default_host) && ($host = array_pop($default_host))) {
-            $hide_host = true;
-            $input_host = new html_hiddenfield(array(
-                'name' => '_host', 'id' => 'rcmloginhost', 'value' => $host) + $attrib);
-        }
-        else if (empty($default_host)) {
-            $input_host = new html_inputfield(array('name' => '_host', 'id' => 'rcmloginhost')
-                + $attrib + $host_attrib);
-        }
-
-        $form_name  = !empty($attrib['form']) ? $attrib['form'] : 'form';
-        $this->add_gui_object('loginform', $form_name);
-
-        // create HTML table with two cols
-        $table = new html_table(array('cols' => 2));
-
-        $table->add('title', html::label('rcmloginuser', html::quote($this->app->gettext('username'))));
-        $table->add('input', $input_user->show(rcube_utils::get_input_value('_user', rcube_utils::INPUT_GPC)));
-
-        $table->add('title', html::label('rcmloginpwd', html::quote($this->app->gettext('password'))));
-        $table->add('input', $input_pass->show());
-
-        // add host selection row
-        if (is_object($input_host) && !$hide_host) {
-            $table->add('title', html::label('rcmloginhost', html::quote($this->app->gettext('server'))));
-            $table->add('input', $input_host->show(rcube_utils::get_input_value('_host', rcube_utils::INPUT_GPC)));
-        }
-
-        $out  = $input_task->show();
-        $out .= $input_action->show();
-        $out .= $input_tzone->show();
-        $out .= $input_dst->show();
-        $out .= $input_url->show();
-        $out .= $table->show();
-
-        if ($hide_host) {
-            $out .= $input_host->show();
-        }
-
-        // surround html output with a form tag
-        if (empty($attrib['form'])) {
-            $out = $this->form_tag(array('name' => $form_name, 'method' => 'post'), $out);
-        }
-
-        return $out;
-    }
-
-
-    /**
-     * GUI object 'preloader'
-     * Loads javascript code for images preloading
-     *
-     * @param array Named parameters
-     * @return void
-     */
-    protected function preloader($attrib)
-    {
-        $images = preg_split('/[\s\t\n,]+/', $attrib['images'], -1, PREG_SPLIT_NO_EMPTY);
-        $images = array_map(array($this, 'abs_url'), $images);
-
-        if (empty($images) || $this->app->task == 'logout')
-            return;
-
-        $this->add_script('var images = ' . self::json_serialize($images) .';
-            for (var i=0; i<images.length; i++) {
-                img = new Image();
-                img.src = images[i];
-            }', 'docready');
-    }
-
-
-    /**
-     * GUI object 'searchform'
-     * Returns code for search function
-     *
-     * @param array Named parameters
-     * @return string HTML code for the gui object
-     */
-    protected function search_form($attrib)
-    {
-        // add some labels to client
-        $this->add_label('searching');
-
-        $attrib['name'] = '_q';
-
-        if (empty($attrib['id'])) {
-            $attrib['id'] = 'rcmqsearchbox';
-        }
-        if ($attrib['type'] == 'search' && !$this->browser->khtml) {
-            unset($attrib['type'], $attrib['results']);
-        }
-
-        $input_q = new html_inputfield($attrib);
-        $out = $input_q->show();
-
-        $this->add_gui_object('qsearchbox', $attrib['id']);
-
-        // add form tag around text field
-        if (empty($attrib['form'])) {
-            $out = $this->form_tag(array(
-                'name' => "rcmqsearchform",
-                'onsubmit' => rcmail::JS_OBJECT_NAME . ".command('search'); return false",
-                'style' => "display:inline"),
-                $out);
-        }
-
-        return $out;
-    }
-
-
-    /**
-     * Builder for GUI object 'message'
-     *
-     * @param array Named tag parameters
-     * @return string HTML code for the gui object
-     */
-    protected function message_container($attrib)
-    {
-        if (isset($attrib['id']) === false) {
-            $attrib['id'] = 'rcmMessageContainer';
-        }
-
-        $this->add_gui_object('message', $attrib['id']);
-
-        return html::div($attrib, '');
-    }
-
-
-    /**
-     * GUI object 'charsetselector'
-     *
-     * @param array Named parameters for the select tag
-     * @return string HTML code for the gui object
-     */
-    public function charset_selector($attrib)
-    {
-        // pass the following attributes to the form class
-        $field_attrib = array('name' => '_charset');
-        foreach ($attrib as $attr => $value) {
-            if (in_array($attr, array('id', 'name', 'class', 'style', 'size', 'tabindex'))) {
-                $field_attrib[$attr] = $value;
-            }
-        }
-
-        $charsets = array(
-            'UTF-8'        => 'UTF-8 ('.$this->app->gettext('unicode').')',
-            'US-ASCII'     => 'ASCII ('.$this->app->gettext('english').')',
-            'ISO-8859-1'   => 'ISO-8859-1 ('.$this->app->gettext('westerneuropean').')',
-            'ISO-8859-2'   => 'ISO-8859-2 ('.$this->app->gettext('easterneuropean').')',
-            'ISO-8859-4'   => 'ISO-8859-4 ('.$this->app->gettext('baltic').')',
-            'ISO-8859-5'   => 'ISO-8859-5 ('.$this->app->gettext('cyrillic').')',
-            'ISO-8859-6'   => 'ISO-8859-6 ('.$this->app->gettext('arabic').')',
-            'ISO-8859-7'   => 'ISO-8859-7 ('.$this->app->gettext('greek').')',
-            'ISO-8859-8'   => 'ISO-8859-8 ('.$this->app->gettext('hebrew').')',
-            'ISO-8859-9'   => 'ISO-8859-9 ('.$this->app->gettext('turkish').')',
-            'ISO-8859-10'   => 'ISO-8859-10 ('.$this->app->gettext('nordic').')',
-            'ISO-8859-11'   => 'ISO-8859-11 ('.$this->app->gettext('thai').')',
-            'ISO-8859-13'   => 'ISO-8859-13 ('.$this->app->gettext('baltic').')',
-            'ISO-8859-14'   => 'ISO-8859-14 ('.$this->app->gettext('celtic').')',
-            'ISO-8859-15'   => 'ISO-8859-15 ('.$this->app->gettext('westerneuropean').')',
-            'ISO-8859-16'   => 'ISO-8859-16 ('.$this->app->gettext('southeasterneuropean').')',
-            'WINDOWS-1250' => 'Windows-1250 ('.$this->app->gettext('easterneuropean').')',
-            'WINDOWS-1251' => 'Windows-1251 ('.$this->app->gettext('cyrillic').')',
-            'WINDOWS-1252' => 'Windows-1252 ('.$this->app->gettext('westerneuropean').')',
-            'WINDOWS-1253' => 'Windows-1253 ('.$this->app->gettext('greek').')',
-            'WINDOWS-1254' => 'Windows-1254 ('.$this->app->gettext('turkish').')',
-            'WINDOWS-1255' => 'Windows-1255 ('.$this->app->gettext('hebrew').')',
-            'WINDOWS-1256' => 'Windows-1256 ('.$this->app->gettext('arabic').')',
-            'WINDOWS-1257' => 'Windows-1257 ('.$this->app->gettext('baltic').')',
-            'WINDOWS-1258' => 'Windows-1258 ('.$this->app->gettext('vietnamese').')',
-            'ISO-2022-JP'  => 'ISO-2022-JP ('.$this->app->gettext('japanese').')',
-            'ISO-2022-KR'  => 'ISO-2022-KR ('.$this->app->gettext('korean').')',
-            'ISO-2022-CN'  => 'ISO-2022-CN ('.$this->app->gettext('chinese').')',
-            'EUC-JP'       => 'EUC-JP ('.$this->app->gettext('japanese').')',
-            'EUC-KR'       => 'EUC-KR ('.$this->app->gettext('korean').')',
-            'EUC-CN'       => 'EUC-CN ('.$this->app->gettext('chinese').')',
-            'BIG5'         => 'BIG5 ('.$this->app->gettext('chinese').')',
-            'GB2312'       => 'GB2312 ('.$this->app->gettext('chinese').')',
-        );
-
-        if (!empty($_POST['_charset'])) {
-            $set = $_POST['_charset'];
-        }
-        else if (!empty($attrib['selected'])) {
-            $set = $attrib['selected'];
-        }
-        else {
-            $set = $this->get_charset();
-        }
-
-        $set = strtoupper($set);
-        if (!isset($charsets[$set])) {
-            $charsets[$set] = $set;
-        }
-
-        $select = new html_select($field_attrib);
-        $select->add(array_values($charsets), array_keys($charsets));
-
-        return $select->show($set);
-    }
-
-    /**
-     * Include content from config/about.<LANG>.html if available
-     */
-    protected function about_content($attrib)
-    {
-        $content = '';
-        $filenames = array(
-            'about.' . $_SESSION['language'] . '.html',
-            'about.' . substr($_SESSION['language'], 0, 2) . '.html',
-            'about.html',
-        );
-        foreach ($filenames as $file) {
-            $fn = RCMAIL_CONFIG_DIR . '/' . $file;
-            if (is_readable($fn)) {
-                $content = file_get_contents($fn);
-                $content = $this->parse_conditions($content);
-                $content = $this->parse_xml($content);
-                break;
-            }
-        }
-
-        return $content;
-    }
-
-}
diff --git a/lib/ext/Roundcube/rcube_output_json.php b/lib/ext/Roundcube/rcube_output_json.php
deleted file mode 100644
index eb1a938..0000000
--- a/lib/ext/Roundcube/rcube_output_json.php
+++ /dev/null
@@ -1,257 +0,0 @@
-<?php
-
-/*
- +-----------------------------------------------------------------------+
- | program/include/rcube_output_json.php                                 |
- |                                                                       |
- | This file is part of the Roundcube Webmail client                     |
- | Copyright (C) 2008-2012, The Roundcube Dev Team                       |
- |                                                                       |
- | Licensed under the GNU General Public License version 3 or            |
- | any later version with exceptions for skins & plugins.                |
- | See the README file for a full license statement.                     |
- |                                                                       |
- | PURPOSE:                                                              |
- |   Class to handle JSON (AJAX) output                                  |
- +-----------------------------------------------------------------------+
- | Author: Thomas Bruederli <roundcube at gmail.com>                        |
- | Author: Aleksander Machniak <alec at alec.pl>                            |
- +-----------------------------------------------------------------------+
-*/
-
-
-/**
- * View class to produce JSON responses
- *
- * @package View
- */
-class rcube_output_json extends rcube_output
-{
-    protected $texts = array();
-    protected $commands = array();
-    protected $callbacks = array();
-    protected $message = null;
-
-    public $type = 'js';
-    public $ajax_call = true;
-
-
-    /**
-     * Issue command to set page title
-     *
-     * @param string $title New page title
-     */
-    public function set_pagetitle($title)
-    {
-        if ($this->config->get('devel_mode') && !empty($_SESSION['username']))
-            $name = $_SESSION['username'];
-        else
-            $name = $this->config->get('product_name');
-
-        $this->command('set_pagetitle', empty($name) ? $title : $name.' :: '.$title);
-    }
-
-
-    /**
-     * Register a template object handler
-     *
-     * @param  string $obj Object name
-     * @param  string $func Function name to call
-     */
-    public function add_handler($obj, $func)
-    {
-        // ignore
-    }
-
-
-    /**
-     * Register a list of template object handlers
-     *
-     * @param  array $arr Hash array with object=>handler pairs
-     */
-    public function add_handlers($arr)
-    {
-        // ignore
-    }
-
-
-    /**
-     * Call a client method
-     *
-     * @param string Method to call
-     * @param ... Additional arguments
-     */
-    public function command()
-    {
-        $cmd = func_get_args();
-
-        if (strpos($cmd[0], 'plugin.') === 0)
-          $this->callbacks[] = $cmd;
-        else
-          $this->commands[] = $cmd;
-    }
-
-
-    /**
-     * Add a localized label to the client environment
-     */
-    public function add_label()
-    {
-        $args = func_get_args();
-        if (count($args) == 1 && is_array($args[0]))
-            $args = $args[0];
-
-        foreach ($args as $name) {
-            $this->texts[$name] = $this->app->gettext($name);
-        }
-    }
-
-
-    /**
-     * Invoke display_message command
-     *
-     * @param string  $message  Message to display
-     * @param string  $type     Message type [notice|confirm|error]
-     * @param array   $vars     Key-value pairs to be replaced in localized text
-     * @param boolean $override Override last set message
-     * @param int     $timeout  Message displaying time in seconds
-     * @uses self::command()
-     */
-    public function show_message($message, $type='notice', $vars=null, $override=true, $timeout=0)
-    {
-        if ($override || !$this->message) {
-            if ($this->app->text_exists($message)) {
-                if (!empty($vars)) {
-                    $vars = array_map(array('rcmail', 'Q'), $vars);
-                }
-                $msgtext = $this->app->gettext(array('name' => $message, 'vars' => $vars));
-            }
-            else
-                $msgtext = $message;
-
-            $this->message = $message;
-            $this->command('display_message', $msgtext, $type, $timeout * 1000);
-        }
-    }
-
-
-    /**
-     * Delete all stored env variables and commands
-     */
-    public function reset()
-    {
-        parent::reset();
-        $this->texts = array();
-        $this->commands = array();
-    }
-
-
-    /**
-     * Redirect to a certain url
-     *
-     * @param mixed $p Either a string with the action or url parameters as key-value pairs
-     * @param int $delay Delay in seconds
-     * @see rcmail::url()
-     */
-    public function redirect($p = array(), $delay = 1)
-    {
-        $location = $this->app->url($p);
-        $this->remote_response(sprintf("window.setTimeout(function(){ %s.redirect('%s',true); }, %d);",
-            rcmail::JS_OBJECT_NAME, $location, $delay));
-        exit;
-    }
-
-
-    /**
-     * Send an AJAX response to the client.
-     */
-    public function send()
-    {
-        $this->remote_response();
-        exit;
-    }
-
-
-    /**
-     * Show error page and terminate script execution
-     *
-     * @param int    $code     Error code
-     * @param string $message  Error message
-     */
-    public function raise_error($code, $message)
-    {
-        $this->show_message("Application Error ($code): $message", 'error');
-        $this->remote_response();
-        exit;
-    }
-
-
-    /**
-     * Send an AJAX response with executable JS code
-     *
-     * @param  string  $add Additional JS code
-     * @param  boolean True if output buffer should be flushed
-     * @return void
-     * @deprecated
-     */
-    protected function remote_response($add='')
-    {
-        static $s_header_sent = false;
-
-        if (!$s_header_sent) {
-            $s_header_sent = true;
-            $this->nocacheing_headers();
-            header('Content-Type: text/plain; charset=' . $this->get_charset());
-        }
-
-        // unset default env vars
-        unset($this->env['task'], $this->env['action'], $this->env['comm_path']);
-
-        $rcmail = rcmail::get_instance();
-        $response['action'] = $rcmail->action;
-
-        if ($unlock = rcube_utils::get_input_value('_unlock', rcube_utils::INPUT_GPC)) {
-            $response['unlock'] = $unlock;
-        }
-
-        if (!empty($this->env))
-            $response['env'] = $this->env;
-
-        if (!empty($this->texts))
-            $response['texts'] = $this->texts;
-
-        // send function calls
-        $response['exec'] = $this->get_js_commands() . $add;
-
-        if (!empty($this->callbacks))
-            $response['callbacks'] = $this->callbacks;
-
-        echo self::json_serialize($response);
-    }
-
-
-    /**
-     * Return executable javascript code for all registered commands
-     *
-     * @return string $out
-     */
-    protected function get_js_commands()
-    {
-        $out = '';
-
-        foreach ($this->commands as $i => $args) {
-            $method = array_shift($args);
-            foreach ($args as $i => $arg) {
-                $args[$i] = self::json_serialize($arg);
-            }
-
-            $out .= sprintf(
-                "this.%s(%s);\n",
-                preg_replace('/^parent\./', '', $method),
-                implode(',', $args)
-            );
-        }
-
-        return $out;
-    }
-}
diff --git a/lib/ext/Roundcube/rcube_plugin.php b/lib/ext/Roundcube/rcube_plugin.php
index 4508885..dbb15e8 100644
--- a/lib/ext/Roundcube/rcube_plugin.php
+++ b/lib/ext/Roundcube/rcube_plugin.php
@@ -22,7 +22,8 @@
 /**
  * Plugin interface class
  *
- * @package PluginAPI
+ * @package    Framework
+ * @subpackage PluginAPI
  */
 abstract class rcube_plugin
 {
diff --git a/lib/ext/Roundcube/rcube_plugin_api.php b/lib/ext/Roundcube/rcube_plugin_api.php
index 107c810..51cf5d2 100644
--- a/lib/ext/Roundcube/rcube_plugin_api.php
+++ b/lib/ext/Roundcube/rcube_plugin_api.php
@@ -20,14 +20,15 @@
 */
 
 // location where plugins are loade from
-if (!defined('RCMAIL_PLUGINS_DIR'))
-  define('RCMAIL_PLUGINS_DIR', INSTALL_PATH . 'plugins/');
+if (!defined('RCUBE_PLUGINS_DIR'))
+  define('RCUBE_PLUGINS_DIR', RCUBE_INSTALL_PATH . 'plugins/');
 
 
 /**
  * The plugin loader and global API
  *
- * @package PluginAPI
+ * @package    Framework
+ * @subpackage PluginAPI
  */
 class rcube_plugin_api
 {
@@ -100,7 +101,7 @@ class rcube_plugin_api
    */
   protected function __construct()
   {
-    $this->dir = slashify(RCMAIL_PLUGINS_DIR);
+    $this->dir = slashify(RCUBE_PLUGINS_DIR);
   }
 
 
@@ -327,7 +328,7 @@ class rcube_plugin_api
     if (isset($this->actions[$action])) {
       call_user_func($this->actions[$action]);
     }
-    else {
+    else if (rcube::get_instance()->action != 'refresh') {
       rcube::raise_error(array('code' => 524, 'type' => 'php',
         'file' => __FILE__, 'line' => __LINE__,
         'message' => "No handler found for action $action"), true, true);
@@ -369,6 +370,10 @@ class rcube_plugin_api
    */
   public function register_task($task, $owner)
   {
+    // tasks are irrelevant in framework mode
+    if (!class_exists('rcmail', false))
+      return true;
+
     if ($task != asciiwords($task)) {
       rcube::raise_error(array('code' => 526, 'type' => 'php',
         'file' => __FILE__, 'line' => __LINE__,
diff --git a/lib/ext/Roundcube/rcube_result_index.php b/lib/ext/Roundcube/rcube_result_index.php
index 334ec85..4d1ae13 100644
--- a/lib/ext/Roundcube/rcube_result_index.php
+++ b/lib/ext/Roundcube/rcube_result_index.php
@@ -24,6 +24,9 @@
 
 /**
  * Class for accessing IMAP's SORT/SEARCH/ESEARCH result
+ *
+ * @package    Framework
+ * @subpackage Storage
  */
 class rcube_result_index
 {
diff --git a/lib/ext/Roundcube/rcube_result_set.php b/lib/ext/Roundcube/rcube_result_set.php
index 809d874..456d1c9 100644
--- a/lib/ext/Roundcube/rcube_result_set.php
+++ b/lib/ext/Roundcube/rcube_result_set.php
@@ -24,7 +24,8 @@
  * Roundcube result set class.
  * Representing an address directory result set.
  *
- * @package Addressbook
+ * @package    Framework
+ * @subpackage Addressbook
  */
 class rcube_result_set
 {
diff --git a/lib/ext/Roundcube/rcube_result_thread.php b/lib/ext/Roundcube/rcube_result_thread.php
index b2325a4..c609bdc 100644
--- a/lib/ext/Roundcube/rcube_result_thread.php
+++ b/lib/ext/Roundcube/rcube_result_thread.php
@@ -24,6 +24,9 @@
 
 /**
  * Class for accessing IMAP's THREAD result
+ *
+ * @package    Framework
+ * @subpackage Storage
  */
 class rcube_result_thread
 {
diff --git a/lib/ext/Roundcube/rcube_session.php b/lib/ext/Roundcube/rcube_session.php
index 6192466..fdbf668 100644
--- a/lib/ext/Roundcube/rcube_session.php
+++ b/lib/ext/Roundcube/rcube_session.php
@@ -24,7 +24,8 @@
 /**
  * Class to provide database supported session storage
  *
- * @package    Core
+ * @package    Framework
+ * @subpackage Core
  * @author     Thomas Bruederli <roundcube at gmail.com>
  * @author     Aleksander Machniak <alec at alec.pl>
  */
@@ -43,7 +44,6 @@ class rcube_session
   private $secret = '';
   private $ip_check = false;
   private $logging = false;
-  private $keep_alive = 0;
   private $memcache;
 
   /**
@@ -525,24 +525,6 @@ class rcube_session
       $this->now = $now - ($now % ($this->lifetime / 2));
   }
 
-  /**
-   * Setter for keep_alive interval
-   */
-  public function set_keep_alive($keep_alive)
-  {
-    $this->keep_alive = $keep_alive;
-
-    if ($this->lifetime < $keep_alive)
-        $this->set_lifetime($keep_alive + 30);
-  }
-
-  /**
-   * Getter for keep_alive interval
-   */
-  public function get_keep_alive()
-  {
-    return $this->keep_alive;
-  }
 
   /**
    * Getter for remote IP saved with this session
@@ -552,6 +534,7 @@ class rcube_session
     return $this->ip;
   }
 
+
   /**
    * Setter for cookie encryption secret
    */
diff --git a/lib/ext/Roundcube/rcube_smtp.php b/lib/ext/Roundcube/rcube_smtp.php
index b28be52..96534c0 100644
--- a/lib/ext/Roundcube/rcube_smtp.php
+++ b/lib/ext/Roundcube/rcube_smtp.php
@@ -25,7 +25,8 @@ define('SMTP_MIME_CRLF', "\r\n");
 /**
  * Class to provide SMTP functionality using PEAR Net_SMTP
  *
- * @package    Mail
+ * @package    Framework
+ * @subpackage Mail
  * @author     Thomas Bruederli <roundcube at gmail.com>
  * @author     Aleksander Machniak <alec at alec.pl>
  */
@@ -134,8 +135,8 @@ class rcube_smtp
       $this->conn->setTimeout($timeout);
     }
 
-    $smtp_user = str_replace('%u', $_SESSION['username'], $CONFIG['smtp_user']);
-    $smtp_pass = str_replace('%p', $rcube->decrypt($_SESSION['password']), $CONFIG['smtp_pass']);
+    $smtp_user = str_replace('%u', $rcube->get_user_name(), $CONFIG['smtp_user']);
+    $smtp_pass = str_replace('%p', $rcube->get_user_password(), $CONFIG['smtp_pass']);
     $smtp_auth_type = empty($CONFIG['smtp_auth_type']) ? NULL : $CONFIG['smtp_auth_type'];
 
     if (!empty($CONFIG['smtp_auth_cid'])) {
diff --git a/lib/ext/Roundcube/rcube_spellchecker.php b/lib/ext/Roundcube/rcube_spellchecker.php
index 219dca7..30d15d7 100644
--- a/lib/ext/Roundcube/rcube_spellchecker.php
+++ b/lib/ext/Roundcube/rcube_spellchecker.php
@@ -25,7 +25,8 @@
 /**
  * Helper class for spellchecking with Googielspell and PSpell support.
  *
- * @package Core
+ * @package    Framework
+ * @subpackage Utils
  */
 class rcube_spellchecker
 {
diff --git a/lib/ext/Roundcube/rcube_storage.php b/lib/ext/Roundcube/rcube_storage.php
index 933ebcc..1556aae 100644
--- a/lib/ext/Roundcube/rcube_storage.php
+++ b/lib/ext/Roundcube/rcube_storage.php
@@ -25,10 +25,10 @@
 /**
  * Abstract class for accessing mail messages storage server
  *
- * @package Mail
- * @author  Thomas Bruederli <roundcube at gmail.com>
- * @author  Aleksander Machniak <alec at alec.pl>
- * @version 2.0
+ * @package    Framework
+ * @subpackage Storage
+ * @author     Thomas Bruederli <roundcube at gmail.com>
+ * @author     Aleksander Machniak <alec at alec.pl>
  */
 abstract class rcube_storage
 {
diff --git a/lib/ext/Roundcube/rcube_string_replacer.php b/lib/ext/Roundcube/rcube_string_replacer.php
index c29f0e4..9af6b33 100644
--- a/lib/ext/Roundcube/rcube_string_replacer.php
+++ b/lib/ext/Roundcube/rcube_string_replacer.php
@@ -23,7 +23,8 @@
 /**
  * Helper class for string replacements based on preg_replace_callback
  *
- * @package Core
+ * @package    Framework
+ * @subpackage Utils
  */
 class rcube_string_replacer
 {
@@ -37,16 +38,16 @@ class rcube_string_replacer
   {
     // Simplified domain expression for UTF8 characters handling
     // Support unicode/punycode in top-level domain part
-    $utf_domain = '[^?&@"\'\\/()\s\r\t\n]+\\.([^\\x00-\\x2f\\x3b-\\x40\\x5b-\\x60\\x7b-\\x7f]{2,}|xn--[a-z0-9]{2,})';
+    $utf_domain = '[^?&@"\'\\/()\s\r\t\n]+\\.?([^\\x00-\\x2f\\x3b-\\x40\\x5b-\\x60\\x7b-\\x7f]{2,}|xn--[a-zA-Z0-9]{2,})';
     $url1 = '.:;,';
-    $url2 = 'a-z0-9%=#@+?!&\\/_~\\[\\]{}-';
+    $url2 = 'a-zA-Z0-9%=#$@+?!&\\/_~\\[\\]{}\*-';
 
-    $this->link_pattern = "/([\w]+:\/\/|\Wwww\.)($utf_domain([$url1]?[$url2]+)*)/i";
+    $this->link_pattern = "/([\w]+:\/\/|\W[Ww][Ww][Ww]\.|^[Ww][Ww][Ww]\.)($utf_domain([$url1]?[$url2]+)*)/";
     $this->mailto_pattern = "/("
         ."[-\w!\#\$%&\'*+~\/^`|{}=]+(?:\.[-\w!\#\$%&\'*+~\/^`|{}=]+)*"  // local-part
         ."@$utf_domain"                                                 // domain-part
         ."(\?[$url1$url2]+)?"                                           // e.g. ?subject=test...
-        .")/i";
+        .")/";
   }
 
   /**
@@ -81,11 +82,11 @@ class rcube_string_replacer
     $i = -1;
     $scheme = strtolower($matches[1]);
 
-    if (preg_match('!^(http|ftp|file)s?://!', $scheme)) {
+    if (preg_match('!^(http|ftp|file)s?://!i', $scheme)) {
       $url = $matches[1] . $matches[2];
     }
-    else if (preg_match('/^(\W)www\.$/', $matches[1], $m)) {
-      $url        = 'www.' . $matches[2];
+    else if (preg_match('/^(\W*)(www\.)$/i', $matches[1], $m)) {
+      $url        = $m[2] . $matches[2];
       $url_prefix = 'http://';
       $prefix     = $m[1];
     }
@@ -134,6 +135,22 @@ class rcube_string_replacer
   }
 
   /**
+   * Replace all defined (link|mailto) patterns with replacement string
+   *
+   * @param string $str Text
+   *
+   * @return string Text
+   */
+  public function replace($str)
+  {
+    // search for patterns like links and e-mail addresses
+    $str = preg_replace_callback($this->link_pattern, array($this, 'link_callback'), $str);
+    $str = preg_replace_callback($this->mailto_pattern, array($this, 'mailto_callback'), $str);
+
+    return $str;
+  }
+
+  /**
    * Replace substituted strings with original values
    */
   public function resolve($str)
diff --git a/lib/ext/Roundcube/rcube_user.php b/lib/ext/Roundcube/rcube_user.php
index 5a65a51..864f2e0 100644
--- a/lib/ext/Roundcube/rcube_user.php
+++ b/lib/ext/Roundcube/rcube_user.php
@@ -5,7 +5,7 @@
  | program/include/rcube_user.inc                                        |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
- | Copyright (C) 2005-2010, 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.                |
@@ -17,6 +17,7 @@
  |                                                                       |
  +-----------------------------------------------------------------------+
  | Author: Thomas Bruederli <roundcube at gmail.com>                        |
+ | Author: Aleksander Machniak <alec at alec.pl>                            |
  +-----------------------------------------------------------------------+
 */
 
@@ -24,8 +25,8 @@
 /**
  * Class representing a system user
  *
- * @package    Core
- * @author     Thomas Bruederli <roundcube at gmail.com>
+ * @package    Framework
+ * @subpackage Core
  */
 class rcube_user
 {
@@ -47,6 +48,13 @@ class rcube_user
      */
     private $rc;
 
+    /**
+     * Internal identities cache
+     *
+     * @var array
+     */
+    private $identities = array();
+
     const SEARCH_ADDRESSBOOK = 1;
     const SEARCH_MAIL = 2;
 
@@ -78,12 +86,17 @@ class rcube_user
     /**
      * Build a user name string (as e-mail address)
      *
-     * @param  string $part Username part (empty or 'local' or 'domain')
+     * @param  string $part Username part (empty or 'local' or 'domain', 'mail')
      * @return string Full user name or its part
      */
     function get_username($part = null)
     {
         if ($this->data['username']) {
+            // return real name
+            if (!$part) {
+                return $this->data['username'];
+            }
+
             list($local, $domain) = explode('@', $this->data['username']);
 
             // at least we should always have the local part
@@ -163,7 +176,7 @@ class rcube_user
 
         // don't save prefs with default values if they haven't been changed yet
         foreach ($a_user_prefs as $key => $value) {
-            if (!isset($old_prefs[$key]) && ($value == $config->get($key)))
+            if ($value === null || (!isset($old_prefs[$key]) && ($value == $config->get($key))))
                 unset($save_prefs[$key]);
         }
 
@@ -213,8 +226,14 @@ class rcube_user
      */
     function get_identity($id = null)
     {
-        $result = $this->list_identities($id ? sprintf('AND identity_id = %d', $id) : '');
-        return $result[0];
+        $id = (int)$id;
+        // cache identities for better performance
+        if (!array_key_exists($id, $this->identities)) {
+            $result = $this->list_identities($id ? 'AND identity_id = ' . $id : '');
+            $this->identities[$id] = $result[0];
+        }
+
+        return $this->identities[$id];
     }
 
 
@@ -273,6 +292,8 @@ class rcube_user
         call_user_func_array(array($this->db, 'query'),
             array_merge(array($sql), $query_params));
 
+        $this->identities = array();
+
         return $this->db->affected_rows();
     }
 
@@ -305,6 +326,8 @@ class rcube_user
         call_user_func_array(array($this->db, 'query'),
             array_merge(array($sql), $insert_values));
 
+        $this->identities = array();
+
         return $this->db->insert_id('identities');
     }
 
@@ -339,6 +362,8 @@ class rcube_user
             $this->ID,
             $iid);
 
+        $this->identities = array();
+
         return $this->db->affected_rows();
     }
 
@@ -359,6 +384,8 @@ class rcube_user
                     " AND del <> 1",
                 $this->ID,
                 $iid);
+
+            unset($this->identities[0]);
         }
     }
 
@@ -449,6 +476,7 @@ class rcube_user
             'user_name'  => $user_name,
             'user_email' => $user_email,
             'email_list' => $email_list,
+            'language'   =>  $_SESSION['language'],
         ));
 
         // plugin aborted this operation
@@ -462,13 +490,17 @@ class rcube_user
             " VALUES (".$dbh->now().", ".$dbh->now().", ?, ?, ?)",
             strip_newlines($data['user']),
             strip_newlines($data['host']),
-            strip_newlines($data['language'] ? $data['language'] : $_SESSION['language']));
+            strip_newlines($data['language']));
 
         if ($user_id = $dbh->insert_id('users')) {
             // create rcube_user instance to make plugin hooks work
-            $user_instance = new rcube_user($user_id);
-            $rcube->user   = $user_instance;
-
+            $user_instance = new rcube_user($user_id, array(
+                'user_id'   => $user_id,
+                'username'  => $data['user'],
+                'mail_host' => $data['host'],
+                'language'  => $data['language'],
+            ));
+            $rcube->user = $user_instance;
             $mail_domain = $rcube->config->mail_domain($data['host']);
             $user_name   = $data['user_name'];
             $user_email  = $data['user_email'];
diff --git a/lib/ext/Roundcube/rcube_utils.php b/lib/ext/Roundcube/rcube_utils.php
index 2a4d4c4..df77dfe 100644
--- a/lib/ext/Roundcube/rcube_utils.php
+++ b/lib/ext/Roundcube/rcube_utils.php
@@ -24,7 +24,8 @@
 /**
  * Utility class providing common functions
  *
- * @package Core
+ * @package    Framework
+ * @subpackage Utils
  */
 class rcube_utils
 {
@@ -133,12 +134,12 @@ class rcube_utils
             }
 
             // find MX record(s)
-            if (getmxrr($domain_part, $mx_records)) {
+            if (!function_exists('getmxrr') || getmxrr($domain_part, $mx_records)) {
                 return true;
             }
 
             // find any DNS record
-            if (checkdnsrr($domain_part, 'ANY')) {
+            if (!function_exists('checkdnsrr') || checkdnsrr($domain_part, 'ANY')) {
                 return true;
             }
         }
@@ -761,7 +762,7 @@ class rcube_utils
             }
         }
 
-        $result[] = substr($string, $p);
+        $result[] = (string) substr($string, $p);
 
         return $result;
     }
@@ -882,4 +883,95 @@ class rcube_utils
         return $as_array ? $arr : join(" ", $arr);
     }
 
+    /**
+     * Parse commandline arguments into a hash array
+     *
+     * @param array $aliases Argument alias names
+     *
+     * @return array Argument values hash
+     */
+    public static function get_opt($aliases = array())
+    {
+        $args = array();
+
+        for ($i=1; $i < count($_SERVER['argv']); $i++) {
+            $arg   = $_SERVER['argv'][$i];
+            $value = true;
+            $key   = null;
+
+            if ($arg[0] == '-') {
+                $key = preg_replace('/^-+/', '', $arg);
+                $sp  = strpos($arg, '=');
+                if ($sp > 0) {
+                    $key   = substr($key, 0, $sp - 2);
+                    $value = substr($arg, $sp+1);
+                }
+                else if (strlen($_SERVER['argv'][$i+1]) && $_SERVER['argv'][$i+1][0] != '-') {
+                    $value = $_SERVER['argv'][++$i];
+                }
+
+                $args[$key] = is_string($value) ? preg_replace(array('/^["\']/', '/["\']$/'), '', $value) : $value;
+            }
+            else {
+                $args[] = $arg;
+            }
+
+            if ($alias = $aliases[$key]) {
+                $args[$alias] = $args[$key];
+            }
+        }
+
+        return $args;
+    }
+
+    /**
+     * Safe password prompt for command line
+     * from http://blogs.sitepoint.com/2009/05/01/interactive-cli-password-prompt-in-php/
+     *
+     * @return string Password
+     */
+    public static function prompt_silent($prompt = "Password:")
+    {
+        if (preg_match('/^win/i', PHP_OS)) {
+            $vbscript  = sys_get_temp_dir() . 'prompt_password.vbs';
+            $vbcontent = 'wscript.echo(InputBox("' . addslashes($prompt) . '", "", "password here"))';
+            file_put_contents($vbscript, $vbcontent);
+
+            $command  = "cscript //nologo " . escapeshellarg($vbscript);
+            $password = rtrim(shell_exec($command));
+            unlink($vbscript);
+
+            return $password;
+        }
+        else {
+            $command = "/usr/bin/env bash -c 'echo OK'";
+            if (rtrim(shell_exec($command)) !== 'OK') {
+                echo $prompt;
+                $pass = trim(fgets(STDIN));
+                echo chr(8)."\r" . $prompt . str_repeat("*", strlen($pass))."\n";
+                return $pass;
+            }
+
+            $command = "/usr/bin/env bash -c 'read -s -p \"" . addslashes($prompt) . "\" mypassword && echo \$mypassword'";
+            $password = rtrim(shell_exec($command));
+            echo "\n";
+            return $password;
+        }
+    }
+
+
+    /**
+     * Find out if the string content means true or false
+     *
+     * @param string $str Input value
+     *
+     * @return boolean Boolean value
+     */
+    public static function get_boolean($str)
+    {
+        $str = strtolower($str);
+
+        return !in_array($str, array('false', '0', 'no', 'off', 'nein', ''), true);
+    }
+
 }
diff --git a/lib/ext/Roundcube/rcube_vcard.php b/lib/ext/Roundcube/rcube_vcard.php
index 00903c2..7b59e20 100644
--- a/lib/ext/Roundcube/rcube_vcard.php
+++ b/lib/ext/Roundcube/rcube_vcard.php
@@ -5,7 +5,7 @@
  | program/include/rcube_vcard.php                                       |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
- | Copyright (C) 2008-2011, The Roundcube Dev Team                       |
+ | Copyright (C) 2008-2012, The Roundcube Dev Team                       |
  |                                                                       |
  | Licensed under the GNU General Public License version 3 or            |
  | any later version with exceptions for skins & plugins.                |
@@ -15,6 +15,7 @@
  |   Logical representation of a vcard address record                    |
  +-----------------------------------------------------------------------+
  | Author: Thomas Bruederli <roundcube at gmail.com>                        |
+ | Author: Aleksander Machniak <alec at alec.pl>                            |
  +-----------------------------------------------------------------------+
 */
 
@@ -23,8 +24,8 @@
  * Logical representation of a vcard-based address record
  * Provides functions to parse and export vCard data format
  *
- * @package    Addressbook
- * @author     Thomas Bruederli <roundcube at gmail.com>
+ * @package    Framework
+ * @subpackage Addressbook
  */
 class rcube_vcard
 {
@@ -51,7 +52,7 @@ class rcube_vcard
     'edit'        => 'X-AB-EDIT',
   );
   private $typemap = array('IPHONE' => 'mobile', 'CELL' => 'mobile', 'WORK,FAX' => 'workfax');
-  private $phonetypemap = array('HOME1' => 'HOME', 'BUSINESS1' => 'WORK', 'BUSINESS2' => 'WORK2', 'BUSINESSFAX' => 'WORK,FAX');
+  private $phonetypemap = array('HOME1' => 'HOME', 'BUSINESS1' => 'WORK', 'BUSINESS2' => 'WORK2', 'BUSINESSFAX' => 'WORK,FAX', 'MOBILE' => 'CELL');
   private $addresstypemap = array('BUSINESS' => 'WORK');
   private $immap = array('X-JABBER' => 'jabber', 'X-ICQ' => 'icq', 'X-MSN' => 'msn', 'X-AIM' => 'aim', 'X-YAHOO' => 'yahoo', 'X-SKYPE' => 'skype', 'X-SKYPE-USERNAME' => 'skype');
 
@@ -62,7 +63,6 @@ class rcube_vcard
   public $middlename;
   public $nickname;
   public $organization;
-  public $notes;
   public $email = array();
 
   public static $eol = "\r\n";
@@ -101,7 +101,7 @@ class rcube_vcard
       ($detected_charset = self::detect_encoding(self::vcard_encode($this->raw))) && $detected_charset != RCMAIL_CHARSET) {
         $this->raw = self::charset_convert($this->raw, $detected_charset);
     }
-    
+
     // consider FN empty if the same as the primary e-mail address
     if ($this->raw['FN'][0][0] == $this->raw['EMAIL'][0][0])
       $this->raw['FN'][0][0] = '';
@@ -265,26 +265,25 @@ class rcube_vcard
    */
   public function set($field, $value, $type = 'HOME')
   {
-    $field = strtolower($field);
+    $field   = strtolower($field);
     $type_uc = strtoupper($type);
-    $typemap = array_flip($this->typemap);
 
     switch ($field) {
       case 'name':
       case 'displayname':
-        $this->raw['FN'][0][0] = $value;
+        $this->raw['FN'][0][0] = $this->displayname = $value;
         break;
 
       case 'surname':
-        $this->raw['N'][0][0] = $value;
+        $this->raw['N'][0][0] = $this->surname = $value;
         break;
 
       case 'firstname':
-        $this->raw['N'][0][1] = $value;
+        $this->raw['N'][0][1] = $this->firstname = $value;
         break;
 
       case 'middlename':
-        $this->raw['N'][0][2] = $value;
+        $this->raw['N'][0][2] = $this->middlename = $value;
         break;
 
       case 'prefix':
@@ -296,11 +295,11 @@ class rcube_vcard
         break;
 
       case 'nickname':
-        $this->raw['NICKNAME'][0][0] = $value;
+        $this->raw['NICKNAME'][0][0] = $this->nickname = $value;
         break;
 
       case 'organization':
-        $this->raw['ORG'][0][0] = $value;
+        $this->raw['ORG'][0][0] = $this->organization = $value;
         break;
 
       case 'photo':
@@ -348,8 +347,10 @@ class rcube_vcard
         if (($tag = self::$fieldmap[$field]) && (is_array($value) || strlen($value))) {
           $index = count($this->raw[$tag]);
           $this->raw[$tag][$index] = (array)$value;
-          if ($type)
+          if ($type) {
+            $typemap = array_flip($this->typemap);
             $this->raw[$tag][$index]['type'] = explode(',', ($typemap[$type_uc] ? $typemap[$type_uc] : $type));
+          }
         }
         break;
     }
@@ -784,42 +785,9 @@ class rcube_vcard
    */
   private static function detect_encoding($string)
   {
-    if (substr($string, 0, 4) == "\0\0\xFE\xFF") return 'UTF-32BE';  // Big Endian
-    if (substr($string, 0, 4) == "\xFF\xFE\0\0") return 'UTF-32LE';  // Little Endian
-    if (substr($string, 0, 2) == "\xFE\xFF")     return 'UTF-16BE';  // Big Endian
-    if (substr($string, 0, 2) == "\xFF\xFE")     return 'UTF-16LE';  // Little Endian
-    if (substr($string, 0, 3) == "\xEF\xBB\xBF") return 'UTF-8';
-
-    // heuristics
-    if ($string[0] == "\0" && $string[1] == "\0" && $string[2] == "\0" && $string[3] != "\0") return 'UTF-32BE';
-    if ($string[0] != "\0" && $string[1] == "\0" && $string[2] == "\0" && $string[3] == "\0") return 'UTF-32LE';
-    if ($string[0] == "\0" && $string[1] != "\0" && $string[2] == "\0" && $string[3] != "\0") return 'UTF-16BE';
-    if ($string[0] != "\0" && $string[1] == "\0" && $string[2] != "\0" && $string[3] == "\0") return 'UTF-16LE';
-
-    // use mb_detect_encoding()
-    $encodings = array('UTF-8', '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', 'BIG5', 'GB2312');
-
-    if (function_exists('mb_detect_encoding') && ($enc = mb_detect_encoding($string, $encodings)))
-      return $enc;
-
-    // No match, check for UTF-8
-    // from http://w3.org/International/questions/qa-forms-utf-8.html
-    if (preg_match('/\A(
-        [\x09\x0A\x0D\x20-\x7E]
-        | [\xC2-\xDF][\x80-\xBF]
-        | \xE0[\xA0-\xBF][\x80-\xBF]
-        | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}
-        | \xED[\x80-\x9F][\x80-\xBF]
-        | \xF0[\x90-\xBF][\x80-\xBF]{2}
-        | [\xF1-\xF3][\x80-\xBF]{3}
-        | \xF4[\x80-\x8F][\x80-\xBF]{2}
-        )*\z/xs', substr($string, 0, 2048)))
-      return 'UTF-8';
-
-    return rcube::get_instance()->config->get('default_charset', 'ISO-8859-1'); # fallback to Latin-1
+    $fallback = rcube::get_instance()->config->get('default_charset', 'ISO-8859-1'); // fallback to Latin-1
+
+    return rcube_charset::detect($string, $fallback);
   }
 
 }
diff --git a/lib/init.php b/lib/init.php
index 9105152..87256c6 100644
--- a/lib/init.php
+++ b/lib/init.php
@@ -23,54 +23,29 @@
  +--------------------------------------------------------------------------+
 */
 
+define('KOLAB_SYNC_START', microtime(true));
+
 // Roundcube Framework constants
-define('RCMAIL_START', microtime(true));
-define('RCMAIL_VERSION', '0.9-git');
+define('RCUBE_VERSION', '0.9-git');
 define('RCMAIL_CHARSET', 'UTF-8');
-define('INSTALL_PATH', realpath(dirname(__FILE__) . '/../') . '/');
-define('RCMAIL_CONFIG_DIR', INSTALL_PATH . 'config');
-define('RCMAIL_PLUGINS_DIR', INSTALL_PATH . 'lib/plugins');
-
-// PHP configuration
-$config = array(
-    'error_reporting'         => E_ALL &~ (E_NOTICE | E_STRICT),
-    'mbstring.func_overload'  => 0,
-//    'suhosin.session.encrypt' => 0,
-//    'session.auto_start'      => 0,
-//    'file_uploads'            => 1,
-    'magic_quotes_runtime'    => 0,
-    'magic_quotes_sybase'     => 0,
-);
-foreach ($config as $optname => $optval) {
-    if ($optval != ini_get($optname) && @ini_set($optname, $optval) === false) {
-        die("ERROR: Wrong '$optname' option value!");
-    }
-}
+define('RCUBE_INSTALL_PATH', realpath(dirname(__FILE__) . '/../') . '/');
+define('RCUBE_PLUGINS_DIR', RCUBE_INSTALL_PATH . 'lib/plugins/');
 
 // Define include path
-$include_path  = INSTALL_PATH . 'lib' . PATH_SEPARATOR;
-$include_path .= INSTALL_PATH . 'lib/ext' . PATH_SEPARATOR;
+$include_path  = RCUBE_INSTALL_PATH . 'lib' . PATH_SEPARATOR;
+$include_path .= RCUBE_INSTALL_PATH . 'lib/ext' . PATH_SEPARATOR;
 $include_path .= ini_get('include_path');
 set_include_path($include_path);
 
 // @TODO: what is a reasonable value for ActiveSync?
 @set_time_limit(600);
 
-// set internal encoding for mbstring extension
-if (extension_loaded('mbstring')) {
-    mb_internal_encoding(RCMAIL_CHARSET);
-    @mb_regex_encoding(RCMAIL_CHARSET);
-}
-
 // include global functions from Roundcube Framework
-require_once 'Roundcube/rcube_shared.inc';
+require_once 'Roundcube/bootstrap.php';
 
 // Register main autoloader
 spl_autoload_register('kolab_sync_autoload');
 
-// set PEAR error handling (will also load the PEAR main class)
-PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'rcube_pear_error');
-
 // Autoloader for Syncroton
 //require_once 'Zend/Loader/Autoloader.php';
 //$autoloader = Zend_Loader_Autoloader::getInstance();
@@ -81,6 +56,7 @@ PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'rcube_pear_error');
  */
 function kolab_sync_autoload($classname)
 {
+/*
     // Roundcube Framework
     $filename = preg_replace(
         array(
@@ -107,7 +83,7 @@ function kolab_sync_autoload($classname)
         include_once "$filename.php";
         return true;
     }
-
+*/
     // Syncroton, replacement for Zend autoloader
     $filename = str_replace('_', DIRECTORY_SEPARATOR, $classname);
 
diff --git a/lib/kolab_sync.php b/lib/kolab_sync.php
index 27ad3d9..03001b7 100644
--- a/lib/kolab_sync.php
+++ b/lib/kolab_sync.php
@@ -129,6 +129,9 @@ class kolab_sync extends rcube
             exit;
         }
 
+        // Save user password for Roundcube Framework
+        $this->password = $_SERVER['PHP_AUTH_PW'];
+
         // Register Syncroton backends
         Syncroton_Registry::set('loggerBackend',                         $this->logger);
         Syncroton_Registry::set(Syncroton_Registry::DATABASE,            new kolab_sync_db);
@@ -329,8 +332,8 @@ class kolab_sync extends rcube
             $query = $_SERVER['QUERY_STRING'];
             $log   = $query . ($mem ? ($query ? ' ' : '') . "[$mem]" : '');
 
-            if (defined('RCMAIL_START'))
-                self::print_timer(RCMAIL_START, $log);
+            if (defined('KOLAB_SYNC_START'))
+                self::print_timer(KOLAB_SYNC_START, $log);
             else
                 self::console($log);
         }


commit 54a3d2f5f53681ce3982f45ef845f8c4db9eb15b
Author: Aleksander Machniak <alec at alec.pl>
Date:   Mon Nov 26 11:54:15 2012 +0100

    Fix INBOX folder detection, in flat mode assign all "non-special" folders to it,
    set correct folder type for INBOX

diff --git a/lib/kolab_sync_backend.php b/lib/kolab_sync_backend.php
index dd29629..46d16de 100644
--- a/lib/kolab_sync_backend.php
+++ b/lib/kolab_sync_backend.php
@@ -596,12 +596,20 @@ class kolab_sync_backend
         // Folder UID
         $folder_id = $this->folder_id($folder);
 
+        // Folder type
+        $type = self::type_kolab2activesync($type);
+        // fix type, if there's no type annotation it's detected as UNKNOWN
+        // we'll use 'mail' (12) or 'mail.inbox' (2)
+        if ($type == 1) {
+            $type = $folder == 'INBOX' ? 2 : 12;
+        }
+
         // Syncroton folder data array
         return array(
             'serverId'    => $folder_id,
             'parentId'    => count($items) ? self::folder_id(implode($delim, $items)) : 0,
             'displayName' => rcube_charset::convert($name, 'UTF7-IMAP', kolab_sync::CHARSET),
-            'type'        => self::type_kolab2activesync($type),
+            'type'        => $type,
         );
     }
 
diff --git a/lib/kolab_sync_data_email.php b/lib/kolab_sync_data_email.php
index 3f1606a..f808b5a 100644
--- a/lib/kolab_sync_data_email.php
+++ b/lib/kolab_sync_data_email.php
@@ -420,15 +420,14 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
             $types  = $this->folder_types;
 
             foreach ($list as $idx => $folder) {
-                if (isset($types[$folder['type']])) {
-                    $folder_id = $types[$folder['type']];
+                $type = $folder['type'] == 12 ? 2 : $folder['type']; // unknown to Inbox
+                if ($folder_id = $types[$type]) {
                     $result[$folder_id] = array(
                         'displayName' => $folder_id,
                         'serverId'    => $folder_id,
                         'parentId'    => 0,
-                        'type'        => $folder['type'],
+                        'type'        => $type,
                     );
-                    unset($types[$folder['type']]);
                 }
             }
 





More information about the commits mailing list