Projects
Kolab:3.4:Updates
kolab-syncroton
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 67
View file
kolab-syncroton.spec
Changed
@@ -30,15 +30,14 @@ %global _ap_sysconfdir %{_sysconfdir}/%{httpd_name} Name: kolab-syncroton -Version: 2.3 -Release: 0.2.dev20141017.git92b081cf%{?dist} +Version: 2.3.0 +Release: 1%{?dist} Summary: ActiveSync for Kolab Groupware Group: Applications/Internet License: LGPLv2 URL: http://www.syncroton.org -# From 92b081cf384a7c5158a2852f52a3c11a717f936a Source0: http://mirror.kolabsys.com/pub/releases/%{name}-%{version}.tar.gz Source1: kolab-syncroton.logrotate @@ -46,9 +45,9 @@ # Use this build requirement to make sure we are using # up to date vendorized copies of the plugins. -BuildRequires: roundcubemail-plugin-kolab_auth >= 3.1.12 -BuildRequires: roundcubemail-plugin-kolab_folders >= 3.1.12 -BuildRequires: roundcubemail-plugin-libkolab >= 3.1.12 +BuildRequires: roundcubemail-plugin-kolab_auth >= 3.2 +BuildRequires: roundcubemail-plugin-kolab_folders >= 3.2 +BuildRequires: roundcubemail-plugin-libkolab >= 3.2 %if 0%{?suse_version} BuildRequires: roundcubemail @@ -69,9 +68,9 @@ Requires: logrotate Requires: roundcubemail(core) -Requires: roundcubemail-plugin-kolab_auth -Requires: roundcubemail-plugin-kolab_folders -Requires: roundcubemail-plugin-libkolab +Requires: roundcubemail-plugin-kolab_auth >= 3.2 +Requires: roundcubemail-plugin-kolab_folders >= 3.2 +Requires: roundcubemail-plugin-libkolab >= 3.2 Requires: php-kolabformat Requires: php-pear-MDB2 Requires: php-ZendFramework @@ -210,6 +209,11 @@ %attr(0770,%{httpd_user},%{httpd_group}) %{_var}/log/%{name} %changelog +* Tue Jan 27 2015 Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> - 2.3.0-1 +- Release of version 2.3.0, see; + + https://issues.kolab.org/buglist.cgi?target_milestone=2.3.0&product=Syncroton + * Mon Sep 15 2014 Daniel Hoffend <dh@dotlan.net> - 2.3-0.2.git - New upstream version
View file
debian.changelog
Changed
@@ -1,3 +1,11 @@ +kolab-syncroton (2.3.0-0~kolab1) unstable; urgency=low + + * Release of version 2.3.0, see: + + https://issues.kolab.org/buglist.cgi?target_milestone=2.3.0&product=Syncroton + + -- Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> Tue, 27 Jan 2015 15:13:40 +0200 + kolab-syncroton (2.3~dev20141017-0~kolab2) unstable; urgency=low * fix prerm script for Debian to make clean removal of package possible
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/bootstrap.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/bootstrap.php
Changed
@@ -3,7 +3,7 @@ /* +-----------------------------------------------------------------------+ | This file is part of the Roundcube PHP suite | - | Copyright (C) 2005-2013, The Roundcube Dev Team | + | Copyright (C) 2005-2014, The Roundcube Dev Team | | | | Licensed under the GNU General Public License version 3 or | | any later version with exceptions for skins & plugins. | @@ -54,11 +54,11 @@ } // framework constants -define('RCUBE_VERSION', '1.0.2'); +define('RCUBE_VERSION', '1.1-git'); define('RCUBE_CHARSET', 'UTF-8'); if (!defined('RCUBE_LIB_DIR')) { - define('RCUBE_LIB_DIR', dirname(__FILE__).DIRECTORY_SEPARATOR); + define('RCUBE_LIB_DIR', __DIR__ . '/'); } if (!defined('RCUBE_INSTALL_PATH')) { @@ -464,16 +464,14 @@ '/Net_(.+)/', '/Auth_(.+)/', '/^html_.+/', - '/^rcube(.*)/', - '/^utf8$/', + '/^rcube(.*)/' ), array( 'Mail/\\1', 'Net/\\1', 'Auth/\\1', 'Roundcube/html', - 'Roundcube/rcube\\1', - 'utf8.class', + 'Roundcube/rcube\\1' ), $classname );
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/html.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/html.php
Changed
@@ -32,7 +32,7 @@ public static $doctype = 'xhtml'; public static $lc_tags = true; - public static $common_attrib = array('id','class','style','title','align','unselectable'); + public static $common_attrib = array('id','class','style','title','align','unselectable','tabindex','role'); public static $containers = array('iframe','div','span','p','h1','h2','h3','ul','form','textarea','table','thead','tbody','tr','th','td','style','script'); @@ -218,7 +218,7 @@ $attr = array('src' => $attr); } return self::tag('iframe', $attr, $cont, array_merge(self::$common_attrib, - array('src','name','width','height','border','frameborder','onload'))); + array('src','name','width','height','border','frameborder','onload','allowfullscreen'))); } /** @@ -283,10 +283,11 @@ continue; } - // ignore not allowed attributes + // ignore not allowed attributes, except aria-* and data-* if (!empty($allowed)) { $is_data_attr = @substr_compare($key, 'data-', 0, 5) === 0; - if (!isset($allowed_f[$key]) && (!$is_data_attr || !isset($allowed_f['data-*']))) { + $is_aria_attr = @substr_compare($key, 'aria-', 0, 5) === 0; + if (!$is_aria_attr && !$is_data_attr && !isset($allowed_f[$key])) { continue; } } @@ -836,7 +837,7 @@ if (!empty($this->header)) { $rowcontent = ''; foreach ($this->header as $c => $col) { - $rowcontent .= self::tag($this->_col_tagname(), $col->attrib, $col->content); + $rowcontent .= self::tag($this->_head_tagname(), $col->attrib, $col->content); } $thead = $this->tagname == 'table' ? self::tag('thead', null, self::tag('tr', null, $rowcontent, parent::$common_attrib)) : self::tag($this->_row_tagname(), array('class' => 'thead'), $rowcontent, parent::$common_attrib); @@ -889,7 +890,16 @@ private function _row_tagname() { static $row_tagnames = array('table' => 'tr', 'ul' => 'li', '*' => 'div'); - return $row_tagnames[$this->tagname] ? $row_tagnames[$this->tagname] : $row_tagnames['*']; + return $row_tagnames[$this->tagname] ?: $row_tagnames['*']; + } + + /** + * Getter for the corresponding tag name for table row elements + */ + private function _head_tagname() + { + static $head_tagnames = array('table' => 'th', '*' => 'span'); + return $head_tagnames[$this->tagname] ?: $head_tagnames['*']; } /** @@ -898,7 +908,7 @@ private function _col_tagname() { static $col_tagnames = array('table' => 'td', '*' => 'span'); - return $col_tagnames[$this->tagname] ? $col_tagnames[$this->tagname] : $col_tagnames['*']; + return $col_tagnames[$this->tagname] ?: $col_tagnames['*']; } }
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube.php
Changed
@@ -3,8 +3,8 @@ /* +-----------------------------------------------------------------------+ | This file is part of the Roundcube Webmail client | - | Copyright (C) 2008-2012, The Roundcube Dev Team | - | Copyright (C) 2011-2012, Kolab Systems AG | + | Copyright (C) 2008-2014, The Roundcube Dev Team | + | Copyright (C) 2011-2014, Kolab Systems AG | | | | Licensed under the GNU General Public License version 3 or | | any later version with exceptions for skins & plugins. | @@ -94,6 +94,13 @@ */ public $plugins; + /** + * Instance of rcube_user class. + * + * @var rcube_user + */ + public $user; + /* private/protected vars */ protected $texts; @@ -165,9 +172,13 @@ public function get_dbh() { if (!$this->db) { - $config_all = $this->config->all(); - $this->db = rcube_db::factory($config_all['db_dsnw'], $config_all['db_dsnr'], $config_all['db_persistent']); - $this->db->set_debug((bool)$config_all['sql_debug']); + $this->db = rcube_db::factory( + $this->config->get('db_dsnw'), + $this->config->get('db_dsnr'), + $this->config->get('db_persistent') + ); + + $this->db->set_debug((bool)$this->config->get('sql_debug')); } return $this->db; @@ -348,40 +359,18 @@ // for backward compat. (deprecated, will be removed) $this->imap = $this->storage; - // enable caching of mail data - $storage_cache = $this->config->get("{$driver}_cache"); - $messages_cache = $this->config->get('messages_cache'); - // for backward compatybility - if ($storage_cache === null && $messages_cache === null && $this->config->get('enable_caching')) { - $storage_cache = 'db'; - $messages_cache = true; - } - - if ($storage_cache) { - $this->storage->set_caching($storage_cache); - } - if ($messages_cache) { - $this->storage->set_messages_caching(true); - } - - // set pagesize from config - $pagesize = $this->config->get('mail_pagesize'); - if (!$pagesize) { - $pagesize = $this->config->get('pagesize', 50); - } - $this->storage->set_pagesize($pagesize); - // set class options $options = array( - 'auth_type' => $this->config->get("{$driver}_auth_type", 'check'), - 'auth_cid' => $this->config->get("{$driver}_auth_cid"), - 'auth_pw' => $this->config->get("{$driver}_auth_pw"), - 'debug' => (bool) $this->config->get("{$driver}_debug"), - 'force_caps' => (bool) $this->config->get("{$driver}_force_caps"), - 'disabled_caps' => $this->config->get("{$driver}_disabled_caps"), - 'timeout' => (int) $this->config->get("{$driver}_timeout"), - 'skip_deleted' => (bool) $this->config->get('skip_deleted'), - 'driver' => $driver, + 'auth_type' => $this->config->get("{$driver}_auth_type", 'check'), + 'auth_cid' => $this->config->get("{$driver}_auth_cid"), + 'auth_pw' => $this->config->get("{$driver}_auth_pw"), + 'debug' => (bool) $this->config->get("{$driver}_debug"), + 'force_caps' => (bool) $this->config->get("{$driver}_force_caps"), + 'disabled_caps' => $this->config->get("{$driver}_disabled_caps"), + 'socket_options' => $this->config->get("{$driver}_conn_options"), + 'timeout' => (int) $this->config->get("{$driver}_timeout"), + 'skip_deleted' => (bool) $this->config->get('skip_deleted'), + 'driver' => $driver, ); if (!empty($_SESSION['storage_host'])) { @@ -400,32 +389,89 @@ $this->storage->set_options($options); $this->set_storage_prop(); - } + // subscribe to 'storage_connected' hook for session logging + if ($this->config->get('imap_log_session', false)) { + $this->plugins->register_hook('storage_connected', array($this, 'storage_log_session')); + } + } /** * Set storage parameters. - * This must be done AFTER connecting to the server! */ protected function set_storage_prop() { $storage = $this->get_storage(); + // set pagesize from config + $pagesize = $this->config->get('mail_pagesize'); + if (!$pagesize) { + $pagesize = $this->config->get('pagesize', 50); + } + + $storage->set_pagesize($pagesize); $storage->set_charset($this->config->get('default_charset', RCUBE_CHARSET)); - if ($default_folders = $this->config->get('default_folders')) { - $storage->set_default_folders($default_folders); + // enable caching of mail data + $driver = $this->config->get('storage_driver', 'imap'); + $storage_cache = $this->config->get("{$driver}_cache"); + $messages_cache = $this->config->get('messages_cache'); + // for backward compatybility + if ($storage_cache === null && $messages_cache === null && $this->config->get('enable_caching')) { + $storage_cache = 'db'; + $messages_cache = true; + } + + if ($storage_cache) { + $storage->set_caching($storage_cache); + } + if ($messages_cache) { + $storage->set_messages_caching(true); + } + } + + + /** + * Set special folders type association. + * This must be done AFTER connecting to the server! + */ + protected function set_special_folders() + { + $storage = $this->get_storage(); + $folders = $storage->get_special_folders(true); + $prefs = array(); + + // check SPECIAL-USE flags on IMAP folders + foreach ($folders as $type => $folder) { + $idx = $type . '_mbox'; + if ($folder !== $this->config->get($idx)) { + $prefs[$idx] = $folder; + } } - if (isset($_SESSION['mbox'])) { - $storage->set_folder($_SESSION['mbox']); + + // Some special folders differ, update user preferences + if (!empty($prefs) && $this->user) { + $this->user->save_prefs($prefs); } - if (isset($_SESSION['page'])) { - $storage->set_page($_SESSION['page']); + + // create default folders (on login) + if ($this->config->get('create_default_folders')) { + $storage->create_default_folders(); } } /** + * Callback for IMAP connection events to log session identifiers + */ + public function storage_log_session($args) + { + if (!empty($args['session']) && session_id()) { + $this->write_log('imap_session', $args['session']); + } + } + + /** * Create session object and start the session. */ public function session_init() @@ -796,12 +842,19 @@ * upon decryption; see http://php.net/mcrypt_generic#68082 */ $clear = pack("a*H2", $clear, "80"); + $ckey = $this->config->get_crypto_key($key); - if (function_exists('mcrypt_module_open') && + if (function_exists('openssl_encrypt')) { + $method = 'DES-EDE3-CBC';
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_addressbook.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_addressbook.php
Changed
@@ -557,6 +557,62 @@ } /** + * Build contact display name for autocomplete listing + * + * @param array Hash array with contact data as key-value pairs + * @param string Optional email address + * @param string Optional name (self::compose_list_name() result) + * @param string Optional template to use (defaults to the 'contact_search_name' config option) + * + * @return string Display name + */ + public static function compose_search_name($contact, $email = null, $name = null, $templ = null) + { + static $template; + + if (empty($templ) && !isset($template)) { // cache this + $template = rcube::get_instance()->config->get('contact_search_name'); + if (empty($template)) { + $template = '{name} <{email}>'; + } + } + + $result = $templ ?: $template; + + if (preg_match_all('/\{[a-z]+\}/', $result, $matches)) { + foreach ($matches[0] as $key) { + $key = trim($key, '{}'); + $value = ''; + + switch ($key) { + case 'name': + $value = $name ?: self::compose_list_name($contact); + break; + + case 'email': + $value = $email; + break; + } + + if (empty($value)) { + $value = strpos($key, ':') ? $contact[$key] : self::get_col_values($key, $contact, true); + if (is_array($value)) { + $value = $value[0]; + } + } + + $result = str_replace('{' . $key . '}', $value, $result); + } + } + + $result = preg_replace('/\s+/', ' ', $result); + $result = preg_replace('/\s*(<>|\(\)|\[\])/', '', $result); + $result = trim($result, '/ '); + + return $result; + } + + /** * Create a unique key for sorting contacts */ public static function compose_contact_key($contact, $sort_col)
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_cache.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_cache.php
Changed
@@ -45,6 +45,7 @@ private $cache = array(); private $cache_changes = array(); private $cache_sums = array(); + private $max_packet = -1; /** @@ -74,7 +75,7 @@ else { $this->type = 'db'; $this->db = $rcube->get_dbh(); - $this->table = $this->db->table_name('cache'); + $this->table = $this->db->table_name('cache', true); } // convert ttl string to seconds @@ -196,10 +197,10 @@ { if ($this->type == 'db' && $this->db && $this->ttl) { $this->db->query( - "DELETE FROM ".$this->table. - " WHERE user_id = ?". - " AND cache_key LIKE ?". - " AND expires < " . $this->db->now(), + "DELETE FROM {$this->table}". + " WHERE `user_id` = ?". + " AND `cache_key` LIKE ?". + " AND `expires` < " . $this->db->now(), $this->userid, $this->prefix.'.%'); } @@ -214,7 +215,7 @@ $rcube = rcube::get_instance(); $db = $rcube->get_dbh(); - $db->query("DELETE FROM " . $db->table_name('cache') . " WHERE expires < " . $db->now()); + $db->query("DELETE FROM " . $db->table_name('cache', true) . " WHERE `expires` < " . $db->now()); } @@ -283,13 +284,12 @@ } else { $sql_result = $this->db->limitquery( - "SELECT data, cache_key". - " FROM " . $this->table. - " WHERE user_id = ?". - " AND cache_key = ?". + "SELECT `data`, `cache_key`". + " FROM {$this->table}". + " WHERE `user_id` = ? AND `cache_key` = ?". // for better performance we allow more records for one key // get the newer one - " ORDER BY created DESC", + " ORDER BY `created` DESC", 0, 1, $this->userid, $this->prefix.'.'.$key); if ($sql_arr = $this->db->fetch_assoc($sql_result)) { @@ -319,7 +319,7 @@ * Writes single cache record into DB. * * @param string $key Cache key name - * @param mxied $data Serialized cache data + * @param mixed $data Serialized cache data * * @param boolean True on success, False on failure */ @@ -329,6 +329,12 @@ return false; } + // don't attempt to write too big data sets + if (strlen($data) > $this->max_packet_size()) { + trigger_error("rcube_cache: max_packet_size ($this->max_packet) exceeded for key $key. Tried to write " . strlen($data) . " bytes", E_USER_WARNING); + return false; + } + if ($this->type == 'memcache' || $this->type == 'apc') { return $this->add_record($this->ckey($key), $data); } @@ -339,9 +345,8 @@ // Remove NULL rows (here we don't need to check if the record exist) if ($data == 'N;') { $this->db->query( - "DELETE FROM " . $this->table. - " WHERE user_id = ?". - " AND cache_key = ?", + "DELETE FROM {$this->table}". + " WHERE `user_id` = ? AND `cache_key` = ?", $this->userid, $key); return true; @@ -350,12 +355,12 @@ // update existing cache record if ($key_exists) { $result = $this->db->query( - "UPDATE " . $this->table. - " SET created = " . $this->db->now(). - ", expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL'). - ", data = ?". - " WHERE user_id = ?". - " AND cache_key = ?", + "UPDATE {$this->table}". + " SET `created` = " . $this->db->now(). + ", `expires` = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL'). + ", `data` = ?". + " WHERE `user_id` = ?". + " AND `cache_key` = ?", $data, $this->userid, $key); } // add new cache record @@ -363,8 +368,8 @@ // for better performance we allow more records for one key // so, no need to check if record exist (see rcube_cache::read_record()) $result = $this->db->query( - "INSERT INTO " . $this->table. - " (created, expires, user_id, cache_key, data)". + "INSERT INTO {$this->table}". + " (`created`, `expires`, `user_id`, `cache_key`, `data`)". " VALUES (" . $this->db->now() . ", " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", ?, ?, ?)", $this->userid, $key, $data); } @@ -414,20 +419,19 @@ // Remove all keys (in specified cache) if ($key === null) { - $where = " AND cache_key LIKE " . $this->db->quote($this->prefix.'.%'); + $where = " AND `cache_key` LIKE " . $this->db->quote($this->prefix.'.%'); } // Remove keys by name prefix else if ($prefix_mode) { - $where = " AND cache_key LIKE " . $this->db->quote($this->prefix.'.'.$key.'%'); + $where = " AND `cache_key` LIKE " . $this->db->quote($this->prefix.'.'.$key.'%'); } // Remove one key by name else { - $where = " AND cache_key = " . $this->db->quote($this->prefix.'.'.$key); + $where = " AND `cache_key` = " . $this->db->quote($this->prefix.'.'.$key); } $this->db->query( - "DELETE FROM " . $this->table. - " WHERE user_id = ?" . $where, + "DELETE FROM {$this->table} WHERE `user_id` = ?" . $where, $this->userid); } @@ -591,4 +595,30 @@ return $this->packed ? @unserialize($data) : $data; } + + /** + * Determine the maximum size for cache data to be written + */ + private function max_packet_size() + { + if ($this->max_packet < 0) { + $this->max_packet = 2097152; // default/max is 2 MB + + if ($this->type == 'db') { + $value = $this->db->get_variable('max_allowed_packet', 1048500); + $this->max_packet = min($value, $this->max_packet) - 2000; + } + else if ($this->type == 'memcache') { + $stats = $this->db->getStats(); + $remaining = $stats['limit_maxbytes'] - $stats['bytes']; + $this->max_packet = min($remaining / 5, $this->max_packet); + } + else if ($this->type == 'apc' && function_exists('apc_sma_info')) { + $stats = apc_sma_info(); + $this->max_packet = min($stats['avail_mem'] / 5, $this->max_packet); + } + } + + return $this->max_packet; + } }
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_cache_shared.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_cache_shared.php
Changed
@@ -72,7 +72,7 @@ else { $this->type = 'db'; $this->db = $rcube->get_dbh(); - $this->table = $this->db->table_name('cache_shared'); + $this->table = $this->db->table_name('cache_shared', true); } // convert ttl string to seconds @@ -193,9 +193,9 @@ { if ($this->type == 'db' && $this->db && $this->ttl) { $this->db->query( - "DELETE FROM " . $this->table - . " WHERE cache_key LIKE ?" - . " AND expires < " . $this->db->now(), + "DELETE FROM {$this->table}" + . " WHERE `cache_key` LIKE ?" + . " AND `expires` < " . $this->db->now(), $this->prefix . '.%'); } } @@ -209,7 +209,7 @@ $rcube = rcube::get_instance(); $db = $rcube->get_dbh(); - $db->query("DELETE FROM " . $db->table_name('cache_shared') . " WHERE expires < " . $db->now()); + $db->query("DELETE FROM " . $db->table_name('cache_shared', true) . " WHERE `expires` < " . $db->now()); } @@ -278,12 +278,12 @@ } else { $sql_result = $this->db->limitquery( - "SELECT data, cache_key". - " FROM " . $this->table . - " WHERE cache_key = ?". + "SELECT `data`, `cache_key`". + " FROM {$this->table}" . + " WHERE `cache_key` = ?". // for better performance we allow more records for one key // get the newer one - " ORDER BY created DESC", + " ORDER BY `created` DESC", 0, 1, $this->prefix . '.' . $key); if ($sql_arr = $this->db->fetch_assoc($sql_result)) { @@ -331,18 +331,18 @@ // Remove NULL rows (here we don't need to check if the record exist) if ($data == 'N;') { - $this->db->query("DELETE FROM " . $this->table . " WHERE cache_key = ?", $key); + $this->db->query("DELETE FROM {$this->table} WHERE `cache_key` = ?", $key); return true; } // update existing cache record if ($key_exists) { $result = $this->db->query( - "UPDATE " . $this->table . - " SET created = " . $this->db->now() . - ", expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . - ", data = ?". - " WHERE cache_key = ?", + "UPDATE {$this->table}" . + " SET `created` = " . $this->db->now() . + ", `expires` = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . + ", `data` = ?". + " WHERE `cache_key` = ?", $data, $key); } // add new cache record @@ -350,8 +350,8 @@ // for better performance we allow more records for one key // so, no need to check if record exist (see rcube_cache::read_record()) $result = $this->db->query( - "INSERT INTO ".$this->table. - " (created, expires, cache_key, data)". + "INSERT INTO {$this->table}". + " (`created`, `expires`, `cache_key`, `data`)". " VALUES (".$this->db->now().", " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", ?, ?)", $key, $data); } @@ -401,15 +401,15 @@ // Remove all keys (in specified cache) if ($key === null) { - $where = " WHERE cache_key LIKE " . $this->db->quote($this->prefix.'.%'); + $where = " WHERE `cache_key` LIKE " . $this->db->quote($this->prefix.'.%'); } // Remove keys by name prefix else if ($prefix_mode) { - $where = " WHERE cache_key LIKE " . $this->db->quote($this->prefix.'.'.$key.'%'); + $where = " WHERE `cache_key` LIKE " . $this->db->quote($this->prefix.'.'.$key.'%'); } // Remove one key by name else { - $where = " WHERE cache_key = " . $this->db->quote($this->prefix.'.'.$key); + $where = " WHERE `cache_key` = " . $this->db->quote($this->prefix.'.'.$key); } $this->db->query("DELETE FROM " . $this->table . $where);
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_charset.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_charset.php
Changed
@@ -273,17 +273,8 @@ else if ($from == 'ISO-8859-1' && function_exists('utf8_encode')) { return utf8_encode($str); } - else if (class_exists('utf8')) { - if (!$conv) { - $conv = new utf8($from); - } - else { - $conv->loadCharset($from); - } - - if ($_str = $conv->strToUtf8($str)) { - return $_str; - } + else { + user_error("No suitable function found for UTF-8 encoding", E_USER_WARNING); } } @@ -298,17 +289,8 @@ else if ($to == 'ISO-8859-1' && function_exists('utf8_decode')) { return utf8_decode($str); } - else if (class_exists('utf8')) { - if (!$conv) { - $conv = new utf8($to); - } - else { - $conv->loadCharset($from); - } - - if ($_str = $conv->strToUtf8($str)) { - return $_str; - } + else { + user_error("No suitable function found for UTF-8 decoding", E_USER_WARNING); } }
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_contacts.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_contacts.php
Changed
@@ -167,11 +167,9 @@ } $sql_result = $this->db->query( - "SELECT * FROM ".$this->db->table_name($this->db_groups). - " WHERE del<>1". - " AND user_id=?". - $sql_filter. - " ORDER BY name", + "SELECT * FROM " . $this->db->table_name($this->db_groups, true) + . " WHERE `del` <> 1 AND `user_id` = ?" . $sql_filter + . " ORDER BY `name`", $this->user_id); while ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) { @@ -192,10 +190,8 @@ function get_group($group_id) { $sql_result = $this->db->query( - "SELECT * FROM ".$this->db->table_name($this->db_groups). - " WHERE del<>1". - " AND contactgroup_id=?". - " AND user_id=?", + "SELECT * FROM " . $this->db->table_name($this->db_groups, true) + . " WHERE `del` <> 1 AND `contactgroup_id` = ? AND `user_id` = ?", $group_id, $this->user_id); if ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) { @@ -228,25 +224,25 @@ $length = $subset != 0 ? abs($subset) : $this->page_size; if ($this->group_id) - $join = " LEFT JOIN ".$this->db->table_name($this->db_groupmembers)." AS m". - " ON (m.contact_id = c.".$this->primary_key.")"; + $join = " LEFT JOIN " . $this->db->table_name($this->db_groupmembers, true) . " AS m". + " ON (m.`contact_id` = c.`".$this->primary_key."`)"; $order_col = (in_array($this->sort_col, $this->table_cols) ? $this->sort_col : 'name'); - $order_cols = array('c.'.$order_col); + $order_cols = array("c.`$order_col`"); if ($order_col == 'firstname') - $order_cols[] = 'c.surname'; + $order_cols[] = 'c.`surname`'; else if ($order_col == 'surname') - $order_cols[] = 'c.firstname'; + $order_cols[] = 'c.`firstname`'; if ($order_col != 'name') - $order_cols[] = 'c.name'; - $order_cols[] = 'c.email'; + $order_cols[] = 'c.`name`'; + $order_cols[] = 'c.`email`'; $sql_result = $this->db->limitquery( - "SELECT * FROM ".$this->db->table_name($this->db_name)." AS c" . + "SELECT * FROM " . $this->db->table_name($this->db_name, true) . " AS c" . $join . - " WHERE c.del<>1" . - " AND c.user_id=?" . - ($this->group_id ? " AND m.contactgroup_id=?" : ""). + " WHERE c.`del` <> 1" . + " AND c.`user_id` = ?" . + ($this->group_id ? " AND m.`contactgroup_id` = ?" : ""). ($this->filter ? " AND (".$this->filter.")" : "") . " ORDER BY ". $this->db->concat($order_cols) . " " . $this->sort_order, @@ -442,7 +438,7 @@ // build WHERE clause $ids = $this->db->array2list($ids, 'integer'); - $where = 'c.' . $this->primary_key.' IN ('.$ids.')'; + $where = 'c.`' . $this->primary_key.'` IN ('.$ids.')'; // reset counter unset($this->cache['count']); @@ -486,17 +482,17 @@ private function _count() { if ($this->group_id) - $join = " LEFT JOIN ".$this->db->table_name($this->db_groupmembers)." AS m". - " ON (m.contact_id=c.".$this->primary_key.")"; + $join = " LEFT JOIN " . $this->db->table_name($this->db_groupmembers, true) . " AS m". + " ON (m.`contact_id` = c.`".$this->primary_key."`)"; // count contacts for this user $sql_result = $this->db->query( - "SELECT COUNT(c.contact_id) AS rows". - " FROM ".$this->db->table_name($this->db_name)." AS c". + "SELECT COUNT(c.`contact_id`) AS rows". + " FROM " . $this->db->table_name($this->db_name, true) . " AS c". $join. - " WHERE c.del<>1". - " AND c.user_id=?". - ($this->group_id ? " AND m.contactgroup_id=?" : ""). + " WHERE c.`del` <> 1". + " AND c.`user_id` = ?". + ($this->group_id ? " AND m.`contactgroup_id` = ?" : ""). ($this->filter ? " AND (".$this->filter.")" : ""), $this->user_id, $this->group_id @@ -534,10 +530,10 @@ return $assoc ? $first : $this->result; $this->db->query( - "SELECT * FROM ".$this->db->table_name($this->db_name). - " WHERE contact_id=?". - " AND user_id=?". - " AND del<>1", + "SELECT * FROM " . $this->db->table_name($this->db_name, true). + " WHERE `contact_id` = ?". + " AND `user_id` = ?". + " AND `del` <> 1", $id, $this->user_id ); @@ -566,9 +562,11 @@ return $results; $sql_result = $this->db->query( - "SELECT cgm.contactgroup_id, cg.name FROM " . $this->db->table_name($this->db_groupmembers) . " AS cgm" . - " LEFT JOIN " . $this->db->table_name($this->db_groups) . " AS cg ON (cgm.contactgroup_id = cg.contactgroup_id AND cg.del<>1)" . - " WHERE cgm.contact_id=?", + "SELECT cgm.`contactgroup_id`, cg.`name` " + . " FROM " . $this->db->table_name($this->db_groupmembers, true) . " AS cgm" + . " LEFT JOIN " . $this->db->table_name($this->db_groups, true) . " AS cg" + . " ON (cgm.`contactgroup_id` = cg.`contactgroup_id` AND cg.`del` <> 1)" + . " WHERE cgm.`contact_id` = ?", $id ); while ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) { @@ -636,8 +634,8 @@ if (!$existing->count && !empty($a_insert_cols)) { $this->db->query( - "INSERT INTO ".$this->db->table_name($this->db_name). - " (user_id, changed, del, ".join(', ', $a_insert_cols).")". + "INSERT INTO " . $this->db->table_name($this->db_name, true). + " (`user_id`, `changed`, `del`, ".join(', ', $a_insert_cols).")". " VALUES (".intval($this->user_id).", ".$this->db->now().", 0, ".join(', ', $a_insert_values).")" ); @@ -671,11 +669,11 @@ if (!empty($write_sql)) { $this->db->query( - "UPDATE ".$this->db->table_name($this->db_name). - " SET changed=".$this->db->now().", ".join(', ', $write_sql). - " WHERE contact_id=?". - " AND user_id=?". - " AND del<>1", + "UPDATE " . $this->db->table_name($this->db_name, true). + " SET `changed` = ".$this->db->now().", ".join(', ', $write_sql). + " WHERE `contact_id` = ?". + " AND `user_id` = ?". + " AND `del` <> 1", $id, $this->user_id ); @@ -771,10 +769,10 @@ // flag record as deleted (always) $this->db->query( - "UPDATE ".$this->db->table_name($this->db_name). - " SET del=1, changed=".$this->db->now(). - " WHERE user_id=?". - " AND contact_id IN ($ids)", + "UPDATE " . $this->db->table_name($this->db_name, true). + " SET `del` = 1, `changed` = ".$this->db->now(). + " WHERE `user_id` = ?". + " AND `contact_id` IN ($ids)", $this->user_id ); @@ -798,10 +796,10 @@ // clear deleted flag $this->db->query( - "UPDATE ".$this->db->table_name($this->db_name). - " SET del=0, changed=".$this->db->now(). - " WHERE user_id=?". - " AND contact_id IN ($ids)", + "UPDATE " . $this->db->table_name($this->db_name, true). + " SET `del` = 0, `changed` = ".$this->db->now(). + " WHERE `user_id` = ?". + " AND `contact_id` IN ($ids)", $this->user_id ); @@ -822,16 +820,18 @@ { $this->cache = null; - $this->db->query("UPDATE " . $this->db->table_name($this->db_name) - . " SET del = 1, changed = " . $this->db->now() - . " WHERE user_id = ?", $this->user_id); + $now = $this->db->now(); + + $this->db->query("UPDATE " . $this->db->table_name($this->db_name, true) + . " SET `del` = 1, `changed` = $now" + . " WHERE `user_id` = ?", $this->user_id);
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_csv2vcard.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_csv2vcard.php
Changed
@@ -149,6 +149,13 @@ // GMail 'groups' => 'groups', + 'group_membership' => 'groups', + 'given_name' => 'firstname', + 'additional_name' => 'middlename', + 'family_name' => 'surname', + 'name' => 'displayname', + 'name_prefix' => 'prefix', + 'name_suffix' => 'suffix', ); /** @@ -272,12 +279,95 @@ 'work_mobile' => "Work Mobile", 'work_title' => "Work Title", 'work_zip' => "Work Zip", - 'groups' => "Group", + 'group' => "Group", + + // GMail + 'groups' => "Groups", + 'group_membership' => "Group Membership", + 'given_name' => "Given Name", + 'additional_name' => "Additional Name", + 'family_name' => "Family Name", + 'name' => "Name", + 'name_prefix' => "Name Prefix", + 'name_suffix' => "Name Suffix", + ); + + /** + * Special fields map for GMail format + * + * @var array + */ + protected $gmail_label_map = array( + 'E-mail' => array( + 'Value' => array( + 'home' => 'email:home', + 'work' => 'email:work', + ), + ), + 'Phone' => array( + 'Value' => array( + 'home' => 'phone:home', + 'homefax' => 'phone:homefax', + 'main' => 'phone:pref', + 'pager' => 'phone:pager', + 'mobile' => 'phone:cell', + 'work' => 'phone:work', + 'workfax' => 'phone:workfax', + ), + ), + 'Relation' => array( + 'Value' => array( + 'spouse' => 'spouse', + ), + ), + 'Website' => array( + 'Value' => array( + 'profile' => 'website:profile', + 'blog' => 'website:blog', + 'homepage' => 'website:homepage', + 'work' => 'website:work', + ), + ), + 'Address' => array( + 'Street' => array( + 'home' => 'street:home', + 'work' => 'street:work', + ), + 'City' => array( + 'home' => 'locality:home', + 'work' => 'locality:work', + ), + 'Region' => array( + 'home' => 'region:home', + 'work' => 'region:work', + ), + 'Postal Code' => array( + 'home' => 'zipcode:home', + 'work' => 'zipcode:work', + ), + 'Country' => array( + 'home' => 'country:home', + 'work' => 'country:work', + ), + ), + 'Organization' => array( + 'Name' => array( + '' => 'organization', + ), + 'Title' => array( + '' => 'jobtitle', + ), + 'Department' => array( + '' => 'department', + ), + ), ); + protected $local_label_map = array(); - protected $vcards = array(); - protected $map = array(); + protected $vcards = array(); + protected $map = array(); + protected $gmail_map = array(); /** @@ -308,16 +398,24 @@ public function import($csv) { // convert to UTF-8 - $head = substr($csv, 0, 4096); - $charset = rcube_charset::detect($head, RCUBE_CHARSET); - $csv = rcube_charset::convert($csv, $charset); - $head = ''; + $head = substr($csv, 0, 4096); + $charset = rcube_charset::detect($head, RCUBE_CHARSET); + $csv = rcube_charset::convert($csv, $charset); + $csv = preg_replace(array('/^[\xFE\xFF]{2}/', '/^\xEF\xBB\xBF/', '/^\x00+/'), '', $csv); // also remove BOM + $head = ''; + $prev_line = false; - $this->map = array(); + $this->map = array(); + $this->gmail_map = array(); // Parse file foreach (preg_split("/[\r\n]+/", $csv) as $line) { + if (!empty($prev_line)) { + $line = '"' . $line; + } + $elements = $this->parse_line($line); + if (empty($elements)) { continue; } @@ -331,7 +429,28 @@ } // Parse data row else { + // handle multiline elements (e.g. Gmail) + if (!empty($prev_line)) { + $first = array_shift($elements); + + if ($first[0] == '"') { + $prev_line[count($prev_line)-1] = '"' . $prev_line[count($prev_line)-1] . "\n" . substr($first, 1); + } + else { + $prev_line[count($prev_line)-1] .= "\n" . $first; + } + + $elements = array_merge($prev_line, $elements); + } + + $last_element = $elements[count($elements)-1]; + if ($last_element[0] == '"') { + $elements[count($elements)-1] = substr($last_element, 1); + $prev_line = $elements; + continue; + } $this->csv_to_vcard($elements); + $prev_line = false; } } } @@ -389,6 +508,7 @@ $map1[$i] = $this->csv2vcard_map[$label]; } } + // check localized labels if (!empty($this->local_label_map)) { for ($i = 0; $i < $size; $i++) { @@ -406,6 +526,22 @@ } $this->map = count($map1) >= count($map2) ? $map1 : $map2; + + // support special Gmail format + foreach ($this->gmail_label_map as $key => $items) { + $num = 1; + while (($_key = "$key $num - Type") && ($found = array_search($_key, $elements)) !== false) { + $this->gmail_map["$key:$num"] = array('_key' => $key, '_idx' => $found); + foreach (array_keys($items) as $item_key) { + $_key = "$key $num - $item_key"; + if (($found = array_search($_key, $elements)) !== false) { + $this->gmail_map["$key:$num"][$item_key] = $found; + } + } + + $num++; + } + }
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_db.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_db.php
Changed
@@ -1063,6 +1063,10 @@ */ public function table_name($table, $quoted = false) { + // let plugins alter the table name (#1489837) + $plugin = rcube::get_instance()->plugins->exec_hook('db_table_name', array('table' => $table)); + $table = $plugin['table']; + // add prefix to the table name if configured if (($prefix = $this->options['table_prefix']) && strpos($table, $prefix) !== 0) { $table = $prefix . $table;
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_db_oracle.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_db_oracle.php
Changed
@@ -500,7 +500,7 @@ foreach (explode("\n", $sql) as $line) { $tok = strtolower(trim($line)); - if (preg_match('/^--/', $line) || $tok == '') { + if (preg_match('/^--/', $line) || $tok == '' || $tok == '/') { continue; }
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_html2text.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_html2text.php
Changed
@@ -423,7 +423,7 @@ // Variables used for building the link list $this->_link_list = array(); - $text = trim(stripslashes($this->html)); + $text = $this->html; // Convert HTML to TXT $this->_converter($text);
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_image.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_image.php
Changed
@@ -59,11 +59,13 @@ $height = $imsize[1]; $gd_type = $imsize['2']; $type = image_type_to_extension($imsize['2'], false); + $channels = $imsize['channels']; } // use ImageMagick if (!$type && ($data = $this->identify())) { list($type, $width, $height) = $data; + $channels = null; } if ($type) { @@ -72,8 +74,11 @@ 'gd_type' => $gd_type, 'width' => $width, 'height' => $height, + 'channels' => $channels, ); } + + return null; } /** @@ -102,10 +107,10 @@ } // use Imagemagick - if ($convert) { - $p['out'] = $filename; - $p['in'] = $this->image_file; - $type = $props['type']; + if ($convert || class_exists('Imagick', false)) { + $p['out'] = $filename; + $p['in'] = $this->image_file; + $type = $props['type']; if (!$type && ($data = $this->identify())) { $type = $data[0]; @@ -129,26 +134,49 @@ $result = ($this->image_file == $filename || copy($this->image_file, $filename)) ? '' : false; } else { - if ($scale >= 1) { - $width = $props['width']; - $height = $props['height']; - } - else { - $width = intval($props['width'] * $scale); - $height = intval($props['height'] * $scale); - } - $valid_types = "bmp,eps,gif,jp2,jpg,png,svg,tif"; - $p += array( - 'type' => $type, - 'quality' => 75, - 'size' => $width . 'x' . $height, - ); - if (in_array($type, explode(',', $valid_types))) { // Valid type? - $result = rcube::exec($convert . ' 2>&1 -flatten -auto-orient -colorspace sRGB -strip' - . ' -quality {quality} -resize {size} {intype}:{in} {type}:{out}', $p); + if ($scale >= 1) { + $width = $props['width']; + $height = $props['height']; + } + else { + $width = intval($props['width'] * $scale); + $height = intval($props['height'] * $scale); + } + + // use ImageMagick in command line + if ($convert) { + $p += array( + 'type' => $type, + 'quality' => 75, + 'size' => $width . 'x' . $height, + ); + + $result = rcube::exec($convert . ' 2>&1 -flatten -auto-orient -colorspace sRGB -strip' + . ' -quality {quality} -resize {size} {intype}:{in} {type}:{out}', $p); + } + // use PHP's Imagick class + else { + try { + $image = new Imagick($this->image_file); + $image = $image->flattenImages(); + + $image->setImageColorspace(Imagick::COLORSPACE_SRGB); + $image->setImageCompressionQuality(75); + $image->setImageFormat($type); + $image->stripImage(); + $image->scaleImage($width, $height); + + if ($image->writeImage($filename)) { + $result = ''; + } + } + catch (Exception $e) { + rcube::raise_error($e, true, false); + } + } } } @@ -158,6 +186,11 @@ } } + // do we have enough memory? (#1489937) + if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' && !$this->mem_check($props)) { + return false; + } + // use GD extension if ($props['gd_type']) { if ($props['gd_type'] == IMAGETYPE_JPEG && function_exists('imagecreatefromjpeg')) { @@ -206,7 +239,7 @@ $image = $new_image; // fix rotation of image if EXIF data exists and specifies rotation (GD strips the EXIF data) - if ($this->image_file && function_exists('exif_read_data')) { + if ($this->image_file && $type == 'jpg' && function_exists('exif_read_data')) { $exif = exif_read_data($this->image_file); if ($exif && $exif['Orientation']) { switch ($exif['Orientation']) { @@ -267,7 +300,7 @@ } } - // use ImageMagick + // use ImageMagick in command line if ($convert) { $p['in'] = $this->image_file; $p['out'] = $filename; @@ -276,14 +309,40 @@ $result = rcube::exec($convert . ' 2>&1 -colorspace sRGB -strip -quality 75 {in} {type}:{out}', $p); if ($result === '') { - @chmod($filename, 0600); + chmod($filename, 0600); return true; } } + // use PHP's Imagick class + if (class_exists('Imagick', false)) { + try { + $image = new Imagick($this->image_file); + + $image->setImageColorspace(Imagick::COLORSPACE_SRGB); + $image->setImageCompressionQuality(75); + $image->setImageFormat(self::$extensions[$type]); + $image->stripImage(); + + if ($image->writeImage($filename)) { + @chmod($filename, 0600); + return true; + } + } + catch (Exception $e) { + rcube::raise_error($e, true, false); + } + } + // use GD extension (TIFF isn't supported) $props = $this->props(); + // do we have enough memory? (#1489937) + if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' && !$this->mem_check($props)) { + return false; + } + + if ($props['gd_type']) { if ($props['gd_type'] == IMAGETYPE_JPEG && function_exists('imagecreatefromjpeg')) { $image = imagecreatefromjpeg($this->image_file); @@ -320,12 +379,26 @@ } /** - * Identify command handler. + * Checks if image format conversion is supported + * + * @return boolean True if specified format can be converted to another format + */ + public static function is_convertable($mimetype = null) + { + $rcube = rcube::get_instance(); + + // @TODO: check if specified mimetype is really supported + return class_exists('Imagick', false) || $rcube->config->get('im_convert_path'); + } + + /** + * ImageMagick based image properties read. */
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_imap.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_imap.php
Changed
@@ -56,6 +56,7 @@ */ protected $icache = array(); + protected $plugins; protected $list_page = 1; protected $delimiter; protected $namespace; @@ -82,6 +83,7 @@ public function __construct() { $this->conn = new rcube_imap_generic(); + $this->plugins = rcube::get_instance()->plugins; // Set namespace and delimiter from session, // so some methods would work before connection @@ -110,13 +112,13 @@ /** * Connect to an IMAP server * - * @param string $host Host to connect - * @param string $user Username for IMAP account - * @param string $pass Password for IMAP account - * @param integer $port Port to connect to - * @param string $use_ssl SSL schema (either ssl or tls) or null if plain connection + * @param string $host Host to connect + * @param string $user Username for IMAP account + * @param string $pass Password for IMAP account + * @param integer $port Port to connect to + * @param string $use_ssl SSL schema (either ssl or tls) or null if plain connection * - * @return boolean TRUE on success, FALSE on failure + * @return boolean True on success, False on failure */ public function connect($host, $user, $pass, $port=143, $use_ssl=null) { @@ -147,7 +149,7 @@ $attempt = 0; do { - $data = rcube::get_instance()->plugins->exec_hook('storage_connect', + $data = $this->plugins->exec_hook('storage_connect', array_merge($this->options, array('host' => $host, 'user' => $user, 'attempt' => ++$attempt))); @@ -170,8 +172,20 @@ $this->connect_done = true; if ($this->conn->connected()) { + // check for session identifier + $session = null; + if (preg_match('/\s+SESSIONID=([^=\s]+)/', $this->conn->result, $m)) { + $session = $m[1]; + } + // get namespace and delimiter $this->set_env(); + + // trigger post-connect hook + $this->plugins->exec_hook('storage_connected', array( + 'host' => $host, 'user' => $user, 'session' => $session + )); + return true; } // write error log @@ -332,6 +346,10 @@ $this->search_sort_field = $set[3]; $this->search_sorted = $set[4]; $this->search_threads = is_a($this->search_set, 'rcube_result_thread'); + + if (is_a($this->search_set, 'rcube_result_multifolder')) { + $this->set_threading(false); + } } @@ -757,7 +775,7 @@ $page = $page ? $page : $this->list_page; // use saved message set - if ($this->search_string && $folder == $this->folder) { + if ($this->search_string) { return $this->list_search_messages($folder, $page, $slice); } @@ -945,6 +963,75 @@ return array(); } + // gather messages from a multi-folder search + if ($this->search_set->multi) { + $page_size = $this->page_size; + $sort_field = $this->sort_field; + $search_set = $this->search_set; + + // prepare paging + $cnt = $search_set->count(); + $from = ($page-1) * $page_size; + $to = $from + $page_size; + $slice_length = min($page_size, $cnt - $from); + + // fetch resultset headers, sort and slice them + if (!empty($sort_field)) { + $this->sort_field = null; + $this->page_size = 1000; // fetch up to 1000 matching messages per folder + $this->threading = false; + + $a_msg_headers = array(); + foreach ($search_set->sets as $resultset) { + if (!$resultset->is_empty()) { + $this->search_set = $resultset; + $this->search_threads = $resultset instanceof rcube_result_thread; + $a_msg_headers = array_merge($a_msg_headers, $this->list_search_messages($resultset->get_parameters('MAILBOX'), 1)); + } + } + + // sort headers + if (!empty($a_msg_headers)) { + $a_msg_headers = $this->conn->sortHeaders($a_msg_headers, $sort_field, $this->sort_order); + } + + // store (sorted) message index + $search_set->set_message_index($a_msg_headers, $sort_field, $this->sort_order); + + // only return the requested part of the set + $a_msg_headers = array_slice(array_values($a_msg_headers), $from, $slice_length); + } + else { + if ($this->sort_order != $search_set->get_parameters('ORDER')) { + $search_set->revert(); + } + + // slice resultset first... + $fetch = array(); + foreach (array_slice($search_set->get(), $from, $slice_length) as $msg_id) { + list($uid, $folder) = explode('-', $msg_id, 2); + $fetch[$folder][] = $uid; + } + + // ... and fetch the requested set of headers + $a_msg_headers = array(); + foreach ($fetch as $folder => $a_index) { + $a_msg_headers = array_merge($a_msg_headers, array_values($this->fetch_headers($folder, $a_index))); + } + } + + if ($slice) { + $a_msg_headers = array_slice($a_msg_headers, -$slice, $slice); + } + + // restore members + $this->sort_field = $sort_field; + $this->page_size = $page_size; + $this->search_set = $search_set; + + return $a_msg_headers; + } + // use saved messages from searching if ($this->threading) { return $this->list_search_thread_messages($folder, $page, $slice); @@ -1111,6 +1198,7 @@ } foreach ($headers as $h) { + $h->folder = $folder; $a_msg_headers[$h->uid] = $h; } @@ -1234,8 +1322,13 @@ return new rcube_result_index($folder, '* SORT'); } + if ($this->search_set instanceof rcube_result_multifolder) { + $index = $this->search_set; + $index->folder = $folder; + // TODO: handle changed sorting + } // search result is an index with the same sorting? - if (($this->search_set instanceof rcube_result_index) + else if (($this->search_set instanceof rcube_result_index) && ((!$this->sort_field && !$this->search_sorted) || ($this->search_sorted && $this->search_sort_field == $this->sort_field)) ) { @@ -1291,7 +1384,7 @@ public function index_direct($folder, $sort_field = null, $sort_order = null, $search = null) { if (!empty($search)) { - $search = $this->search_set->get_compressed(); + $search = $search->get_compressed(); } // use message index sort as default sorting @@ -1410,26 +1503,75 @@ * Invoke search request to IMAP server * * @param string $folder Folder name to search in - * @param string $str Search criteria + * @param string $search Search criteria
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_imap_cache.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_imap_cache.php
Changed
@@ -125,6 +125,11 @@ // cache all possible information by default $this->mode = self::MODE_INDEX | self::MODE_MESSAGE; + + // database tables + $this->index_table = $db->table_name('cache_index', true); + $this->thread_table = $db->table_name('cache_thread', true); + $this->messages_table = $db->table_name('cache_messages', true); } @@ -333,11 +338,11 @@ if ($this->mode & self::MODE_MESSAGE) { // Fetch messages from cache $sql_result = $this->db->query( - "SELECT uid, data, flags" - ." FROM ".$this->db->table_name('cache_messages') - ." WHERE user_id = ?" - ." AND mailbox = ?" - ." AND uid IN (".$this->db->array2list($msgs, 'integer').")", + "SELECT `uid`, `data`, `flags`" + ." FROM {$this->messages_table}" + ." WHERE `user_id` = ?" + ." AND `mailbox` = ?" + ." AND `uid` IN (".$this->db->array2list($msgs, 'integer').")", $this->userid, $mailbox); $msgs = array_flip($msgs); @@ -400,11 +405,11 @@ if ($this->mode & self::MODE_MESSAGE) { $sql_result = $this->db->query( - "SELECT flags, data" - ." FROM ".$this->db->table_name('cache_messages') - ." WHERE user_id = ?" - ." AND mailbox = ?" - ." AND uid = ?", + "SELECT `flags`, `data`" + ." FROM {$this->messages_table}" + ." WHERE `user_id` = ?" + ." AND `mailbox` = ?" + ." AND `uid` = ?", $this->userid, $mailbox, (int)$uid); if ($sql_arr = $this->db->fetch_assoc($sql_result)) { @@ -480,11 +485,11 @@ // here will work as select, assume row exist if affected_rows=0) if (!$force) { $res = $this->db->query( - "UPDATE ".$this->db->table_name('cache_messages') - ." SET flags = ?, data = ?, expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') - ." WHERE user_id = ?" - ." AND mailbox = ?" - ." AND uid = ?", + "UPDATE {$this->messages_table}" + ." SET `flags` = ?, `data` = ?, `expires` = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') + ." WHERE `user_id` = ?" + ." AND `mailbox` = ?" + ." AND `uid` = ?", $flags, $msg, $this->userid, $mailbox, (int) $message->uid); if ($this->db->affected_rows($res)) { @@ -496,8 +501,8 @@ // insert new record $res = $this->db->query( - "INSERT INTO ".$this->db->table_name('cache_messages') - ." (user_id, mailbox, uid, flags, expires, data)" + "INSERT INTO {$this->messages_table}" + ." (`user_id`, `mailbox`, `uid`, `flags`, `expires`, `data`)" ." VALUES (?, ?, ?, ?, ". ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", ?)", $this->userid, $mailbox, (int) $message->uid, $flags, $msg); @@ -505,12 +510,12 @@ // thanks to ignore_key_errors "duplicate row" errors will be ignored if ($force && !$res && !$this->db->is_error($res)) { $this->db->query( - "UPDATE ".$this->db->table_name('cache_messages') - ." SET expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') - .", flags = ?, data = ?" - ." WHERE user_id = ?" - ." AND mailbox = ?" - ." AND uid = ?", + "UPDATE {$this->messages_table}" + ." SET `expires` = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') + .", `flags` = ?, `data` = ?" + ." WHERE `user_id` = ?" + ." AND `mailbox` = ?" + ." AND `uid` = ?", $flags, $msg, $this->userid, $mailbox, (int) $message->uid); } @@ -557,14 +562,16 @@ } } + $binary_check = $this->db->db_provider == 'oracle' ? "BITAND(`flags`, %d)" : "(`flags` & %d)"; + $this->db->query( - "UPDATE ".$this->db->table_name('cache_messages') - ." SET expires = ". ($this->ttl ? $this->db->now($this->ttl) : 'NULL') - .", flags = flags ".($enabled ? "+ $idx" : "- $idx") - ." WHERE user_id = ?" - ." AND mailbox = ?" - .(!empty($uids) ? " AND uid IN (".$this->db->array2list($uids, 'integer').")" : "") - ." AND (flags & $idx) ".($enabled ? "= 0" : "= $idx"), + "UPDATE {$this->messages_table}" + ." SET `expires` = ". ($this->ttl ? $this->db->now($this->ttl) : 'NULL') + .", `flags` = `flags` ".($enabled ? "+ $idx" : "- $idx") + ." WHERE `user_id` = ?" + ." AND `mailbox` = ?" + .(!empty($uids) ? " AND `uid` IN (".$this->db->array2list($uids, 'integer').")" : "") + ." AND " . sprintf($binary_check, $idx) . ($enabled ? " = 0" : " = $idx"), $this->userid, $mailbox); } @@ -583,8 +590,8 @@ if (!strlen($mailbox)) { $this->db->query( - "DELETE FROM ".$this->db->table_name('cache_messages') - ." WHERE user_id = ?", + "DELETE FROM {$this->messages_table}" + ." WHERE `user_id` = ?", $this->userid); } else { @@ -597,10 +604,10 @@ } $this->db->query( - "DELETE FROM ".$this->db->table_name('cache_messages') - ." WHERE user_id = ?" - ." AND mailbox = ?" - .($uids !== null ? " AND uid IN (".$this->db->array2list((array)$uids, 'integer').")" : ""), + "DELETE FROM {$this->messages_table}" + ." WHERE `user_id` = ?" + ." AND `mailbox` = ?" + .($uids !== null ? " AND `uid` IN (".$this->db->array2list((array)$uids, 'integer').")" : ""), $this->userid, $mailbox); } } @@ -619,18 +626,18 @@ // otherwise use 'valid' flag to not loose HIGHESTMODSEQ value if ($remove) { $this->db->query( - "DELETE FROM ".$this->db->table_name('cache_index') - ." WHERE user_id = ?" - .(strlen($mailbox) ? " AND mailbox = ".$this->db->quote($mailbox) : ""), + "DELETE FROM {$this->index_table}" + ." WHERE `user_id` = ?" + .(strlen($mailbox) ? " AND `mailbox` = ".$this->db->quote($mailbox) : ""), $this->userid ); } else { $this->db->query( - "UPDATE ".$this->db->table_name('cache_index') - ." SET valid = 0" - ." WHERE user_id = ?" - .(strlen($mailbox) ? " AND mailbox = ".$this->db->quote($mailbox) : ""), + "UPDATE {$this->index_table}" + ." SET `valid` = 0" + ." WHERE `user_id` = ?" + .(strlen($mailbox) ? " AND `mailbox` = ".$this->db->quote($mailbox) : ""), $this->userid ); } @@ -654,9 +661,9 @@ function remove_thread($mailbox = null) { $this->db->query( - "DELETE FROM ".$this->db->table_name('cache_thread') - ." WHERE user_id = ?" - .(strlen($mailbox) ? " AND mailbox = ".$this->db->quote($mailbox) : ""), + "DELETE FROM {$this->thread_table}" + ." WHERE `user_id` = ?" + .(strlen($mailbox) ? " AND `mailbox` = ".$this->db->quote($mailbox) : ""), $this->userid ); @@ -692,15 +699,16 @@ { $rcube = rcube::get_instance(); $db = $rcube->get_dbh(); + $now = $db->now(); - $db->query("DELETE FROM ".$db->table_name('cache_messages') - ." WHERE expires < " . $db->now()); + $db->query("DELETE FROM " . $db->table_name('cache_messages', true) + ." WHERE `expires` < $now"); - $db->query("DELETE FROM ".$db->table_name('cache_index') - ." WHERE expires < " . $db->now()); + $db->query("DELETE FROM " . $db->table_name('cache_index', true) + ." WHERE `expires` < $now"); - $db->query("DELETE FROM ".$db->table_name('cache_thread') - ." WHERE expires < " . $db->now());
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_imap_generic.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_imap_generic.php
Changed
@@ -50,17 +50,17 @@ public static $mupdate; - private $fp; - private $host; - private $logged = false; - private $capability = array(); - private $capability_readed = false; - private $prefs; - private $cmd_tag; - private $cmd_num = 0; - private $resourceid; - private $_debug = false; - private $_debug_handler = false; + protected $fp; + protected $host; + protected $logged = false; + protected $capability = array(); + protected $capability_readed = false; + protected $prefs; + protected $cmd_tag; + protected $cmd_num = 0; + protected $resourceid; + protected $_debug = false; + protected $_debug_handler = false; const ERROR_OK = 0; const ERROR_NO = -1; @@ -352,7 +352,7 @@ * * @return bool True if connection is closed */ - private function eof() + protected function eof() { if (!is_resource($this->fp)) { return true; @@ -375,7 +375,7 @@ /** * Closes connection stream. */ - private function closeSocket() + protected function closeSocket() { @fclose($this->fp); $this->fp = null; @@ -421,7 +421,7 @@ return false; } - private function hasCapability($name) + protected function hasCapability($name) { if (empty($this->capability) || $name == '') { return false; @@ -723,110 +723,38 @@ // configure $this->set_prefs($options); - $auth_method = $this->prefs['auth_type']; - $result = false; - - // initialize connection - $this->error = ''; - $this->errornum = self::ERROR_OK; - $this->selected = null; - $this->user = $user; $this->host = $host; + $this->user = $user; $this->logged = false; + $this->selected = null; // check input if (empty($host)) { $this->setError(self::ERROR_BAD, "Empty host"); return false; } + if (empty($user)) { $this->setError(self::ERROR_NO, "Empty user"); return false; } + if (empty($password)) { $this->setError(self::ERROR_NO, "Empty password"); return false; } - if (!$this->prefs['port']) { - $this->prefs['port'] = 143; - } - // check for SSL - if ($this->prefs['ssl_mode'] && $this->prefs['ssl_mode'] != 'tls') { - $host = $this->prefs['ssl_mode'] . '://' . $host; - } - - if ($this->prefs['timeout'] <= 0) { - $this->prefs['timeout'] = max(0, intval(ini_get('default_socket_timeout'))); - } - // Connect - $this->fp = @fsockopen($host, $this->prefs['port'], $errno, $errstr, $this->prefs['timeout']); - - if (!$this->fp) { - if (!$errstr) { - $errstr = "Unknown reason (fsockopen() function disabled?)"; - } - $this->setError(self::ERROR_BAD, sprintf("Could not connect to %s:%d: %s", $host, $this->prefs['port'], $errstr)); + if (!$this->_connect($host)) { return false; } - if ($this->prefs['timeout'] > 0) { - stream_set_timeout($this->fp, $this->prefs['timeout']); - } - - $line = trim(fgets($this->fp, 8192)); - - if ($this->_debug) { - // set connection identifier for debug output - preg_match('/#([0-9]+)/', (string)$this->fp, $m); - $this->resourceid = strtoupper(substr(md5($m[1].$this->user.microtime()), 0, 4)); - - if ($line) - $this->debug('S: '. $line); - } - - // Connected to wrong port or connection error? - if (!preg_match('/^\* (OK|PREAUTH)/i', $line)) { - if ($line) - $error = sprintf("Wrong startup greeting (%s:%d): %s", $host, $this->prefs['port'], $line); - else - $error = sprintf("Empty startup greeting (%s:%d)", $host, $this->prefs['port']); - - $this->setError(self::ERROR_BAD, $error); - $this->closeConnection(); - return false; - } - - // RFC3501 [7.1] optional CAPABILITY response - if (preg_match('/\[CAPABILITY ([^]]+)\]/i', $line, $matches)) { - $this->parseCapability($matches[1], true); - } - - // TLS connection - if ($this->prefs['ssl_mode'] == 'tls' && $this->getCapability('STARTTLS')) { - $res = $this->execute('STARTTLS'); - - if ($res[0] != self::ERROR_OK) { - $this->closeConnection(); - return false; - } - - if (!stream_socket_enable_crypto($this->fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { - $this->setError(self::ERROR_BAD, "Unable to negotiate TLS"); - $this->closeConnection(); - return false; - } - - // Now we're secure, capabilities need to be reread - $this->clearCapability(); - } - // Send ID info if (!empty($this->prefs['ident']) && $this->getCapability('ID')) { $this->id($this->prefs['ident']); } + $auth_method = $this->prefs['auth_type']; $auth_methods = array(); $result = null; @@ -901,6 +829,103 @@ } /** + * Connects to IMAP server. + * + * @param string $host Server hostname or IP + * + * @return bool True on success, False on failure + */ + protected function _connect($host) + { + // initialize connection + $this->error = ''; + $this->errornum = self::ERROR_OK; + + if (!$this->prefs['port']) { + $this->prefs['port'] = 143; + } + + // check for SSL + if ($this->prefs['ssl_mode'] && $this->prefs['ssl_mode'] != 'tls') { + $host = $this->prefs['ssl_mode'] . '://' . $host; + } + + if ($this->prefs['timeout'] <= 0) { + $this->prefs['timeout'] = max(0, intval(ini_get('default_socket_timeout')));
View file
kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_imap_search.php
Added
@@ -0,0 +1,231 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | This file is part of the Roundcube Webmail client | + | | + | Copyright (C) 2013, The Roundcube Dev Team | + | Copyright (C) 2014, Kolab Systems AG | + | | + | 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: | + | Execute (multi-threaded) searches in multiple IMAP folders | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ +*/ + +/** + * Class to control search jobs on multiple IMAP folders. + * + * @package Framework + * @subpackage Storage + * @author Thomas Bruederli <roundcube@gmail.com> + */ +class rcube_imap_search +{ + public $options = array(); + + protected $jobs = array(); + protected $timelimit = 0; + protected $results; + protected $conn; + + /** + * Default constructor + */ + public function __construct($options, $conn) + { + $this->options = $options; + $this->conn = $conn; + } + + /** + * Invoke search request to IMAP server + * + * @param array $folders List of IMAP folders to search in + * @param string $str Search criteria + * @param string $charset Search charset + * @param string $sort_field Header field to sort by + * @param boolean $threading True if threaded listing is active + */ + public function exec($folders, $str, $charset = null, $sort_field = null, $threading=null) + { + $start = floor(microtime(true)); + $results = new rcube_result_multifolder($folders); + + // start a search job for every folder to search in + foreach ($folders as $folder) { + // a complete result for this folder already exists + $result = $this->results ? $this->results->get_set($folder) : false; + if ($result && !$result->incomplete) { + $results->add($result); + } + else { + $search = is_array($str) && $str[$folder] ? $str[$folder] : $str; + $job = new rcube_imap_search_job($folder, $search, $charset, $sort_field, $threading); + $job->worker = $this; + $this->jobs[] = $job; + } + } + + // execute jobs and gather results + foreach ($this->jobs as $job) { + // only run search if within the configured time limit + // TODO: try to estimate the required time based on folder size and previous search performance + if (!$this->timelimit || floor(microtime(true)) - $start < $this->timelimit) { + $job->run(); + } + + // add result (may have ->incomplete flag set) + $results->add($job->get_result()); + } + + return $results; + } + + /** + * Setter for timelimt property + */ + public function set_timelimit($seconds) + { + $this->timelimit = $seconds; + } + + /** + * Setter for previous (potentially incomplete) search results + */ + public function set_results($res) + { + $this->results = $res; + } + + /** + * Get connection to the IMAP server + * (used for single-thread mode) + */ + public function get_imap() + { + return $this->conn; + } +} + + +/** + * Stackable item to run the search on a specific IMAP folder + */ +class rcube_imap_search_job /* extends Stackable */ +{ + private $folder; + private $search; + private $charset; + private $sort_field; + private $threading; + private $searchset; + private $result; + private $pagesize = 100; + + public function __construct($folder, $str, $charset = null, $sort_field = null, $threading=false) + { + $this->folder = $folder; + $this->search = $str; + $this->charset = $charset; + $this->sort_field = $sort_field; + $this->threading = $threading; + + $this->result = new rcube_result_index($folder); + $this->result->incomplete = true; + } + + public function run() + { + $this->result = $this->search_index(); + } + + /** + * Copy of rcube_imap::search_index() + */ + protected function search_index() + { + $criteria = $this->search; + $charset = $this->charset; + $imap = $this->worker->get_imap(); + + if (!$imap->connected()) { + trigger_error("No IMAP connection for $this->folder", E_USER_WARNING); + + if ($this->threading) { + return new rcube_result_thread($this->folder); + } + else { + return new rcube_result_index($this->folder); + } + } + + if ($this->worker->options['skip_deleted'] && !preg_match('/UNDELETED/', $criteria)) { + $criteria = 'UNDELETED '.$criteria; + } + + // unset CHARSET if criteria string is ASCII, this way + // SEARCH won't be re-sent after "unsupported charset" response + if ($charset && $charset != 'US-ASCII' && is_ascii($criteria)) { + $charset = 'US-ASCII'; + } + + if ($this->threading) { + $threads = $imap->thread($this->folder, $this->threading, $criteria, true, $charset); + + // Error, try with US-ASCII (RFC5256: SORT/THREAD must support US-ASCII and UTF-8, + // but I've seen that Courier doesn't support UTF-8) + if ($threads->is_error() && $charset && $charset != 'US-ASCII') { + $threads = $imap->thread($this->folder, $this->threading, + rcube_imap::convert_criteria($criteria, $charset), true, 'US-ASCII'); + } + + return $threads; + } + + if ($this->sort_field) { + $messages = $imap->sort($this->folder, $this->sort_field, $criteria, true, $charset); + + // Error, try with US-ASCII (RFC5256: SORT/THREAD must support US-ASCII and UTF-8, + // but I've seen Courier with disabled UTF-8 support) + if ($messages->is_error() && $charset && $charset != 'US-ASCII') { + $messages = $imap->sort($this->folder, $this->sort_field, + rcube_imap::convert_criteria($criteria, $charset), true, 'US-ASCII'); + }
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_ldap.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_ldap.php
Changed
@@ -65,6 +65,8 @@ private $base_dn = ''; private $groups_base_dn = ''; private $group_url; + private $group_data; + private $group_search_cache; private $cache; @@ -101,8 +103,8 @@ // add group name attrib to the list of attributes to be fetched $fetch_attributes[] = $this->prop['groups']['name_attr']; } - if (is_array($p['group_filters']) && count($p['group_filters'])) { - $this->groups = true; + if (is_array($p['group_filters'])) { + $this->groups = $this->groups || count($p['group_filters']); foreach ($p['group_filters'] as $k => $group_filter) { // set default name attribute to cn @@ -232,8 +234,7 @@ // initialize ldap wrapper object $this->ldap = new rcube_ldap_generic($this->prop); - $this->ldap->set_cache($this->cache); - $this->ldap->set_debug($this->debug); + $this->ldap->config_set(array('cache' => $this->cache, 'debug' => $this->debug)); $this->_connect(); } @@ -320,8 +321,7 @@ // we need to use a separate LDAP connection if (!empty($this->prop['vlv'])) { $ldap = new rcube_ldap_generic($this->prop); - $ldap->set_debug($this->debug); - $ldap->set_cache($this->cache); + $ldap->config_set(array('cache' => $this->cache, 'debug' => $this->debug)); if (!$ldap->connect($host)) { continue; } @@ -335,7 +335,7 @@ $res = $ldap->search($search_base_dn, $search_filter, 'sub', $search_attribs); if ($res) { $res->rewind(); - $replaces['%dn'] = $res->get_dn(); + $replaces['%dn'] = key($res->entries(TRUE)); // add more replacements from 'search_bind_attrib' config if ($search_bind_attrib) { @@ -383,7 +383,7 @@ $this->prop['groups'][$k] = strtr($this->prop['groups'][$k], $replaces); } - if (!empty($this->prop['group_filters'])) { + if (is_array($this->prop['group_filters'])) { foreach ($this->prop['group_filters'] as $i => $gf) { if (!empty($gf['base_dn'])) $this->prop['group_filters'][$i]['base_dn'] = strtr($gf['base_dn'], $replaces); @@ -906,7 +906,6 @@ return $this->result; } - /** * Get a specific contact record * @@ -948,6 +947,23 @@ return $assoc ? $res : $this->result; } + /** + * Returns the last error occurred (e.g. when updating/inserting failed) + * + * @return array Hash array with the following fields: type, message + */ + function get_error() + { + $err = $this->error; + + // check ldap connection for errors + if (!$err && $this->ldap->get_error()) { + $err = array(self::ERROR_SEARCH, $this->ldap->get_error()); + } + + return $err; + } + /** * Check the given data before saving. @@ -1066,7 +1082,7 @@ } } - if (!$this->ldap->add($dn, $newentry)) { + if (!$this->ldap->add_entry($dn, $newentry)) { $this->set_error(self::ERROR_SAVING, 'errorsaving'); return false; } @@ -1078,7 +1094,7 @@ 'objectClass' => (array) $this->prop['sub_fields'][$xidx], ); - $this->ldap->add($xdn, $xf); + $this->ldap->add_entry($xdn, $xf); } $dn = self::dn_encode($dn); @@ -1221,7 +1237,7 @@ if (!empty($subdeldata)) { foreach ($subdeldata as $fld => $val) { $subdn = $fld.'='.rcube_ldap_generic::quote_string($val).','.$dn; - if (!$this->ldap->delete($subdn)) { + if (!$this->ldap->delete_entry($subdn)) { return false; } } @@ -1265,7 +1281,7 @@ $fld => $val, 'objectClass' => (array) $this->prop['sub_fields'][$fld], ); - $this->ldap->add($subdn, $xf); + $this->ldap->add_entry($subdn, $xf); } } @@ -1295,7 +1311,7 @@ if ($this->sub_filter) { if ($entries = $this->ldap->list_entries($dn, $this->sub_filter)) { foreach ($entries as $entry) { - if (!$this->ldap->delete($entry['dn'])) { + if (!$this->ldap->delete_entry($entry['dn'])) { $this->set_error(self::ERROR_SAVING, 'errorsaving'); return false; } @@ -1304,12 +1320,12 @@ } // Delete the record. - if (!$this->ldap->delete($dn)) { + if (!$this->ldap->delete_entry($dn)) { $this->set_error(self::ERROR_SAVING, 'errorsaving'); return false; } - // remove contact from all groups where he was member + // remove contact from all groups where he was a member if ($this->groups) { $dn = self::dn_encode($dn); $group_ids = $this->get_record_groups($dn); @@ -1342,7 +1358,7 @@ if ($with_groups && $this->groups && ($groups = $this->_fetch_groups()) && count($groups)) { foreach ($groups as $group) { - $this->ldap->delete($group['dn']); + $this->ldap->delete_entry($group['dn']); } if ($this->cache) { @@ -1410,6 +1426,16 @@ $fieldmap['name'] = $this->group_data['name_attr'] ? $this->group_data['name_attr'] : $this->prop['groups']['name_attr']; } + // assign object type from object class mapping + if (!empty($this->prop['class_type_map'])) { + foreach (array_map('strtolower', (array)$rec['objectclass']) as $objcls) { + if (!empty($this->prop['class_type_map'][$objcls])) { + $out['_type'] = $this->prop['class_type_map'][$objcls]; + break; + } + } + } + foreach ($fieldmap as $rf => $lf) { for ($i=0; $i < $rec[$lf]['count']; $i++) { @@ -1557,7 +1583,7 @@ $this->debug = $dbg; if ($this->ldap) { - $this->ldap->set_debug($dbg); + $this->ldap->config_set('debug', $dbg); } } @@ -1594,12 +1620,12 @@ return array(); } - $group_cache = $this->_fetch_groups(); + $group_cache = $this->_fetch_groups($search, $mode); $groups = array(); if ($search) { foreach ($group_cache as $group) { - if ($this->compare_search_value('name', $group['name'], $search, $mode)) { + if ($this->compare_search_value('name', $group['name'], mb_strtolower($search), $mode)) { $groups[] = $group; } }
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_ldap_generic.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_ldap_generic.php
Changed
@@ -5,8 +5,8 @@ | Roundcube/rcube_ldap_generic.php | | | | This file is part of the Roundcube Webmail client | - | Copyright (C) 2006-2013, The Roundcube Dev Team | - | Copyright (C) 2012-2013, Kolab Systems AG | + | Copyright (C) 2006-2014, The Roundcube Dev Team | + | Copyright (C) 2012-2014, Kolab Systems AG | | | | Licensed under the GNU General Public License version 3 or | | any later version with exceptions for skins & plugins. | @@ -21,464 +21,136 @@ +-----------------------------------------------------------------------+ */ - -/* - LDAP connection properties - -------------------------- - - $prop = array( - 'host' => '<ldap-server-address>', - // or - 'hosts' => array('directory.verisign.com'), - 'port' => 389, - 'use_tls' => true|false, - 'ldap_version' => 3, // using LDAPv3 - 'auth_method' => '', // SASL authentication method (for proxy auth), e.g. DIGEST-MD5 - 'attributes' => array('dn'), // List of attributes to read from the server - 'vlv' => false, // Enable Virtual List View to more efficiently fetch paginated data (if server supports it) - 'config_root_dn' => 'cn=config', // Root DN to read config (e.g. vlv indexes) from - 'numsub_filter' => '(objectClass=organizationalUnit)', // with VLV, we also use numSubOrdinates to query the total number of records. Set this filter to get all numSubOrdinates attributes for counting - 'sizelimit' => '0', // Enables you to limit the count of entries fetched. Setting this to 0 means no limit. - 'timelimit' => '0', // Sets the number of seconds how long is spend on the search. Setting this to 0 means no limit. - 'network_timeout' => 10, // The timeout (in seconds) for connect + bind arrempts. This is only supported in PHP >= 5.3.0 with OpenLDAP 2.x - 'referrals' => true|false, // Sets the LDAP_OPT_REFERRALS option. Mostly used in multi-domain Active Directory setups - ); -*/ - /** * Model class to access an LDAP directories * * @package Framework * @subpackage LDAP */ -class rcube_ldap_generic +class rcube_ldap_generic extends Net_LDAP3 { - const UPDATE_MOD_ADD = 1; - const UPDATE_MOD_DELETE = 2; - const UPDATE_MOD_REPLACE = 4; - const UPDATE_MOD_FULL = 7; - - public $conn; - public $vlv_active = false; - /** private properties */ protected $cache = null; - protected $config = array(); protected $attributes = array('dn'); - protected $entries = null; - protected $result = null; - protected $debug = false; - protected $list_page = 1; - protected $page_size = 10; - protected $vlv_config = null; - + protected $error; - /** - * Object constructor - * - * @param array $p LDAP connection properties - */ - function __construct($p) + function __construct($config = null) { - $this->config = $p; + parent::__construct($config); - if (is_array($p['attributes'])) - $this->attributes = $p['attributes']; - - if (!is_array($p['hosts']) && !empty($p['host'])) - $this->config['hosts'] = array($p['host']); + $this->config_set('log_hook', array($this, 'log')); } /** - * Activate/deactivate debug mode - * - * @param boolean $dbg True if LDAP commands should be logged + * Establish a connection to the LDAP server */ - public function set_debug($dbg = true) + public function connect($host = null) { - $this->debug = $dbg; - } + // Net_LDAP3 does not support IDNA yet + // also parse_host() here is very Roundcube specific + $host = rcube_utils::idn_to_ascii(rcube_utils::parse_host($host)); - /** - * Set connection options - * - * @param mixed $opt Option name as string or hash array with multiple options - * @param mixed $val Option value - */ - public function set_config($opt, $val = null) - { - if (is_array($opt)) - $this->config = array_merge($this->config, $opt); - else - $this->config[$opt] = $value; + return parent::connect($host); } /** - * Enable caching by passing an instance of rcube_cache to be used by this object + * Get a specific LDAP entry, identified by its DN * - * @param object rcube_cache Instance or False to disable caching - */ - public function set_cache($cache_engine) - { - $this->cache = $cache_engine; - } - - /** - * Set properties for VLV-based paging + * @param string $dn Record identifier * - * @param number $page Page number to list (starting at 1) - * @param number $size Number of entries to display on one page + * @return array Hash array */ - public function set_vlv_page($page, $size = 10) + function get_entry($dn) { - $this->list_page = $page; - $this->page_size = $size; + return parent::get_entry($dn, $this->attributes); } /** - * Establish a connection to the LDAP server - */ - public function connect($host = null) + * Prints debug/error info to the log + */ + public function log($level, $msg) { - if (!function_exists('ldap_connect')) { - rcube::raise_error(array('code' => 100, 'type' => 'ldap', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => "No ldap support in this installation of PHP"), - true); - return false; - } - - if (is_resource($this->conn) && $this->config['host'] == $host) - return true; + $msg = implode("\n", $msg); - if (empty($this->config['ldap_version'])) - $this->config['ldap_version'] = 3; - - // iterate over hosts if none specified - if (!$host) { - if (!is_array($this->config['hosts'])) - $this->config['hosts'] = array($this->config['hosts']); - - foreach ($this->config['hosts'] as $host) { - if ($this->connect($host)) { - return true; - } - } - - return false; - } - - // open connection to the given $host - $host = rcube_utils::idn_to_ascii(rcube_utils::parse_host($host)); - $hostname = $host . ($this->config['port'] ? ':'.$this->config['port'] : ''); - - $this->_debug("C: Connect to $hostname [{$this->config['name']}]"); - - if ($lc = @ldap_connect($host, $this->config['port'])) { - if ($this->config['use_tls'] === true) { - if (!ldap_start_tls($lc)) { - return false; - } + switch ($level) { + case LOG_DEBUG: + case LOG_INFO: + case LOG_NOTICE: + if ($this->config['debug']) { + rcube::write_log('ldap', $msg); }
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_message.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_message.php
Changed
@@ -3,7 +3,7 @@ /* +-----------------------------------------------------------------------+ | This file is part of the Roundcube Webmail client | - | Copyright (C) 2008-2010, The Roundcube Dev Team | + | Copyright (C) 2008-2014, The Roundcube Dev Team | | | | Licensed under the GNU General Public License version 3 or | | any later version with exceptions for skins & plugins. | @@ -61,6 +61,8 @@ public $sender = null; public $is_safe = false; + const BODY_MAX_SIZE = 1048576; // 1MB + /** * __construct @@ -74,6 +76,11 @@ */ function __construct($uid, $folder = null) { + // decode combined UID-folder identifier + if (preg_match('/^\d+-.+/', $uid)) { + list($uid, $folder) = explode('-', $uid, 2); + } + $this->uid = $uid; $this->app = rcube::get_instance(); $this->storage = $this->app->get_storage(); @@ -171,6 +178,7 @@ * @param boolean $formatted Enables formatting of text/* parts bodies * * @return string Part content + * @deprecated */ public function get_part_content($mime_id, $fp = null, $skip_charset_conv = false, $max_bytes = 0, $formatted = true) { @@ -193,6 +201,127 @@ /** + * Get content of a specific part of this message + * + * @param string $mime_id Part ID + * @param boolean $formatted Enables formatting of text/* parts bodies + * @param int $max_bytes Only return/read this number of bytes + * @param mixed $mode NULL to return a string, -1 to print body + * or file pointer to save the body into + * + * @return string|bool Part content or operation status + */ + public function get_part_body($mime_id, $formatted = false, $max_bytes = 0, $mode = null) + { + if (!($part = $this->mime_parts[$mime_id])) { + return; + } + + // only text parts can be formatted + $formatted = $formatted && $part->ctype_primary == 'text'; + + // part body not fetched yet... save in memory if it's small enough + if ($part->body === null && is_numeric($mime_id) && $part->size < self::BODY_MAX_SIZE) { + $this->storage->set_folder($this->folder); + // Warning: body here should be always unformatted + $part->body = $this->storage->get_message_part($this->uid, $mime_id, $part, + null, null, true, 0, false); + } + + // body stored in message structure (winmail/inline-uuencode) + if ($part->body !== null || $part->encoding == 'stream') { + $body = $part->body; + + if ($formatted && $body) { + $body = self::format_part_body($body, $part, $this->headers->charset); + } + + if ($max_bytes && strlen($body) > $max_bytes) { + $body = substr($body, 0, $max_bytes); + } + + if (is_resource($mode)) { + if ($body !== false) { + fwrite($mode, $body); + rewind($mode); + } + + return $body !== false; + } + + if ($mode === -1) { + if ($body !== false) { + print($body); + } + + return $body !== false; + } + + return $body; + } + + // get the body from IMAP + $this->storage->set_folder($this->folder); + + $body = $this->storage->get_message_part($this->uid, $mime_id, $part, + $mode === -1, is_resource($mode) ? $mode : null, + !($mode && $formatted), $max_bytes, $mode && $formatted); + + if (is_resource($mode)) { + rewind($mode); + return $body !== false; + } + + if (!$mode && $body && $formatted) { + $body = self::format_part_body($body, $part, $this->headers->charset); + } + + return $body; + } + + + /** + * Format text message part for display + * + * @param string $body Part body + * @param rcube_message_part $part Part object + * @param string $default_charset Fallback charset if part charset is not specified + * + * @return string Formatted body + */ + public static function format_part_body($body, $part, $default_charset = null) + { + // remove useless characters + $body = preg_replace('/[\t\r\0\x0B]+\n/', "\n", $body); + + // remove NULL characters if any (#1486189) + if (strpos($body, "\x00") !== false) { + $body = str_replace("\x00", '', $body); + } + + // detect charset... + if (!$part->charset || strtoupper($part->charset) == 'US-ASCII') { + // try to extract charset information from HTML meta tag (#1488125) + if ($part->ctype_secondary == 'html' && preg_match('/<meta[^>]+charset=([a-z0-9-_]+)/i', $body, $m)) { + $part->charset = strtoupper($m[1]); + } + else if ($default_charset) { + $part->charset = $default_charset; + } + else { + $rcube = rcube::get_instance(); + $part->charset = $rcube->config->get('default_charset', RCUBE_CHARSET); + } + } + + // ..convert charset encoding + $body = rcube_charset::convert($body, $part->charset); + + return $body; + } + + + /** * Determine if the message contains a HTML part. This must to be * a real part not an attachment (or its part) * @@ -288,7 +417,7 @@ // check all message parts foreach ($this->mime_parts as $pid => $part) { if ($part->mimetype == 'text/html') { - return $this->get_part_content($pid); + return $this->get_part_body($pid, true); } } } @@ -309,10 +438,10 @@ // check all message parts foreach ($this->mime_parts as $mime_id => $part) { if ($part->mimetype == 'text/plain') { - return $this->get_part_content($mime_id); + return $this->get_part_body($mime_id, true); } else if ($part->mimetype == 'text/html') { - $out = $this->get_part_content($mime_id); + $out = $this->get_part_body($mime_id, true); // create instance of html2text class $txt = new rcube_html2text($out); @@ -366,7 +495,7 @@ // parse headers from message/rfc822 part if (!isset($structure->headers['subject']) && !isset($structure->headers['from'])) { - list($headers, ) = explode("\r\n\r\n", $this->get_part_content($structure->mime_id, null, true, 32768)); + list($headers, ) = explode("\r\n\r\n", $this->get_part_body($structure->mime_id, false, 32768)); $structure->headers = rcube_mime::parse_headers($headers); } } @@ -720,20 +849,18 @@ */ function tnef_decode(&$part)
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_message_header.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_message_header.php
Changed
@@ -167,6 +167,13 @@ public $mdn_to; /** + * IMAP folder this message is stored in + * + * @var string + */ + public $folder; + + /** * Other message headers * * @var array @@ -189,6 +196,8 @@ 'reply-to' => 'replyto', 'cc' => 'cc', 'bcc' => 'bcc', + 'mbox' => 'folder', + 'folder' => 'folder', 'content-transfer-encoding' => 'encoding', 'in-reply-to' => 'in_reply_to', 'content-type' => 'ctype', @@ -216,8 +225,16 @@ } if ($decode) { - $value = rcube_mime::decode_header($value, $this->charset); - $value = rcube_charset::clean($value); + if (is_array($value)) { + foreach ($value as $key => $val) { + $value[$key] = rcube_mime::decode_header($val, $this->charset); + $value[$key] = rcube_charset::clean($val); + } + } + else { + $value = rcube_mime::decode_header($value, $this->charset); + $value = rcube_charset::clean($value); + } } return $value;
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_mime.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_mime.php
Changed
@@ -3,8 +3,8 @@ /* +-----------------------------------------------------------------------+ | This file is part of the Roundcube Webmail client | - | Copyright (C) 2005-2012, The Roundcube Dev Team | - | Copyright (C) 2011-2012, Kolab Systems AG | + | Copyright (C) 2005-2014, The Roundcube Dev Team | + | Copyright (C) 2011-2014, Kolab Systems AG | | | | Licensed under the GNU General Public License version 3 or | | any later version with exceptions for skins & plugins. | @@ -39,7 +39,6 @@ self::$default_charset = $default_charset; } - /** * Returns message/object character set name * @@ -58,7 +57,6 @@ return RCUBE_CHARSET; } - /** * Parse the given raw message source and return a structure * of rcube_message_part objects. @@ -75,7 +73,6 @@ return self::structure_part($struct); } - /** * Recursive method to convert a Mail_mimeDecode part into a rcube_message_part object * @@ -88,28 +85,30 @@ private static function structure_part($part, $count=0, $parent='') { $struct = new rcube_message_part; - $struct->mime_id = $part->mime_id ? $part->mime_id : (empty($parent) ? (string)$count : "$parent.$count"); - $struct->headers = $part->headers; - $struct->ctype_primary = $part->ctype_primary; - $struct->ctype_secondary = $part->ctype_secondary; - $struct->mimetype = $part->ctype_primary . '/' . $part->ctype_secondary; + $struct->mime_id = $part->mime_id ?: (empty($parent) ? (string)$count : "$parent.$count"); + $struct->headers = $part->headers; + $struct->mimetype = $part->ctype_primary . '/' . $part->ctype_secondary; + $struct->ctype_primary = $part->ctype_primary; + $struct->ctype_secondary = $part->ctype_secondary; $struct->ctype_parameters = $part->ctype_parameters; - if ($part->headers['content-transfer-encoding']) + if ($part->headers['content-transfer-encoding']) { $struct->encoding = $part->headers['content-transfer-encoding']; - if ($part->ctype_parameters['charset']) + } + + if ($part->ctype_parameters['charset']) { $struct->charset = $part->ctype_parameters['charset']; + } - $part_charset = $struct->charset ? $struct->charset : self::get_charset(); + $part_charset = $struct->charset ?: self::get_charset(); // determine filename if (($filename = $part->d_parameters['filename']) || ($filename = $part->ctype_parameters['name'])) { $struct->filename = rcube_mime::decode_mime_string($filename, $part_charset); } - // copy part body and convert it to UTF-8 if necessary - $struct->body = $part->ctype_primary == 'text' || !$part->ctype_parameters['charset'] ? rcube_charset::convert($part->body, $part_charset) : $part->body; - $struct->size = strlen($part->body); + $struct->body = $part->body; + $struct->size = strlen($part->body); $struct->disposition = $part->disposition; foreach ((array)$part->parts as $child_part) { @@ -119,7 +118,6 @@ return $struct; } - /** * Split an address list into a structured array list * @@ -169,7 +167,6 @@ return $out; } - /** * Decode a message header value * @@ -185,7 +182,6 @@ return $str; } - /** * Decode a mime-encoded string to internal charset * @@ -282,12 +278,12 @@ return rcube_charset::convert($input, $default_charset); } - /** * Decode a mime part * * @param string $input Input string * @param string $encoding Part encoding + * * @return string Decoded string */ public static function decode($input, $encoding = '7bit') @@ -308,10 +304,8 @@ } } - /** * Split RFC822 header string into an associative array - * @access private */ public static function parse_headers($headers) { @@ -332,7 +326,6 @@ return $a_headers; } - /** * @access private */ @@ -402,7 +395,6 @@ return $result; } - /** * Explodes header (e.g. address-list) string into array of strings * using specified separator characters with proper handling @@ -477,19 +469,20 @@ return $result; } - /** * Interpret a format=flowed message body according to RFC 2646 * - * @param string $text Raw body formatted as flowed text + * @param string $text Raw body formatted as flowed text + * @param string $mark Mark each flowed line with specified character * * @return string Interpreted text with unwrapped lines and stuffed space removed */ - public static function unfold_flowed($text) + public static function unfold_flowed($text, $mark = null) { - $text = preg_split('/\r?\n/', $text); - $last = -1; + $text = preg_split('/\r?\n/', $text); + $last = -1; $q_level = 0; + $marks = array(); foreach ($text as $idx => $line) { if (preg_match('/^(>+)/', $line, $m)) { @@ -509,6 +502,10 @@ ) { $text[$last] .= $line; unset($text[$idx]); + + if ($mark) { + $marks[$last] = true; + } } else { $last = $idx; @@ -521,7 +518,7 @@ } else { // remove space-stuffing - $line = preg_replace('/^\s/', '', $line); + $line = preg_replace('/^ /', '', $line); if (isset($text[$last]) && $line && $text[$last] != '-- ' @@ -529,6 +526,10 @@ ) { $text[$last] .= $line; unset($text[$idx]); + + if ($mark) { + $marks[$last] = true; + } } else { $text[$idx] = $line; @@ -539,15 +540,20 @@
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_output.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_output.php
Changed
@@ -3,7 +3,7 @@ /* +-----------------------------------------------------------------------+ | This file is part of the Roundcube PHP suite | - | Copyright (C) 2005-2012 The Roundcube Dev Team | + | Copyright (C) 2005-2014 The Roundcube Dev Team | | | | Licensed under the GNU General Public License version 3 or | | any later version with exceptions for skins & plugins. | @@ -31,6 +31,7 @@ protected $config; protected $charset = RCUBE_CHARSET; protected $env = array(); + protected $skins = array(); /** @@ -43,20 +44,21 @@ $this->browser = new rcube_browser(); } - /** * Magic getter */ public function __get($var) { - // allow read-only access to $env - if ($var == 'env') - return $this->env; + // allow read-only access to some members + switch ($var) { + case 'env': return $this->env; + case 'skins': return $this->skins; + case 'charset': return $this->charset; + } return null; } - /** * Setter for output charset. * To be specified in a meta tag and sent as http-header @@ -68,7 +70,6 @@ $this->charset = $charset; } - /** * Getter for output charset * @@ -79,7 +80,6 @@ return $this->charset; } - /** * Set environment variable * @@ -91,7 +91,6 @@ $this->env[$name] = $value; } - /** * Environment variable getter. * @@ -104,7 +103,6 @@ return $this->env[$name]; } - /** * Delete all stored env variables and commands */ @@ -113,7 +111,6 @@ $this->env = array(); } - /** * Invoke display_message command * @@ -125,7 +122,6 @@ */ abstract function show_message($message, $type = 'notice', $vars = null, $override = true, $timeout = 0); - /** * Redirect to a certain url. * @@ -134,13 +130,11 @@ */ abstract function redirect($p = array(), $delay = 1); - /** * Send output to the client. */ abstract function send(); - /** * Send HTTP headers to prevent caching a page */ @@ -153,9 +147,6 @@ 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'); @@ -174,14 +165,32 @@ */ public function future_expire_header($offset = 2600000) { - if (headers_sent()) + 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: "); } + /** + * Send browser compatibility/security/etc. headers + */ + public function common_headers() + { + if (headers_sent()) { + return; + } + + // Unlock IE compatibility mode + if ($this->browser->ie) { + header('X-UA-Compatible: IE=edge'); + } + + // Request browser to disable DNS prefetching (CVE-2010-0464) + header("X-DNS-Prefetch-Control: off"); + } /** * Show error page and terminate script execution @@ -196,7 +205,6 @@ exit(-1); } - /** * Create an edit field for inclusion on a form * @@ -249,7 +257,6 @@ return $out; } - /** * Convert a variable into a javascript object notation * @@ -265,5 +272,4 @@ // that's why we have @ here return @json_encode($input); } - }
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_plugin.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_plugin.php
Changed
@@ -3,7 +3,7 @@ /* +-----------------------------------------------------------------------+ | This file is part of the Roundcube Webmail client | - | Copyright (C) 2008-2012, The Roundcube Dev Team | + | Copyright (C) 2008-2014, The Roundcube Dev Team | | | | Licensed under the GNU General Public License version 3 or | | any later version with exceptions for skins & plugins. | @@ -71,6 +71,7 @@ protected $home; protected $urlbase; private $mytask; + private $loaded_config = array(); /** @@ -94,7 +95,15 @@ /** * Provide information about this * - * @return array Meta information about a plugin or false if not implemented + * @return array Meta information about a plugin or false if not implemented: + * As hash array with the following keys: + * name: The plugin name + * vendor: Name of the plugin developer + * version: Plugin version name + * license: License name (short form according to http://spdx.org/licenses/) + * uri: The URL to the plugin homepage or source repository + * src_uri: Direct download URL to the source code of this plugin + * require: List of plugins required for this one (as array of plugin names) */ public static function info() { @@ -113,6 +122,17 @@ } /** + * Attempt to load the given plugin which is optional for the current plugin + * + * @param string Plugin name + * @return boolean True on success, false on failure + */ + public function include_plugin($plugin_name) + { + return $this->api->load_plugin($plugin_name, true, false); + } + + /** * Load local config file from plugins directory. * The loaded values are patched over the global configuration. * @@ -122,6 +142,12 @@ */ public function load_config($fname = 'config.inc.php') { + if (in_array($fname, $this->loaded_config)) { + return true; + } + + $this->loaded_config[] = $fname; + $fpath = $this->home.'/'.$fname; $rcube = rcube::get_instance(); @@ -394,7 +420,11 @@ public function local_skin_path() { $rcube = rcube::get_instance(); - foreach (array($rcube->config->get('skin'), 'larry') as $skin) { + $skins = array_keys((array)$rcube->output->skins); + if (empty($skins)) { + $skins = (array) $rcube->config->get('skin'); + } + foreach ($skins as $skin) { $skin_path = 'skins/' . $skin; if (is_dir(realpath(slashify($this->home) . $skin_path))) { break;
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_plugin_api.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_plugin_api.php
Changed
@@ -38,6 +38,7 @@ public $handlers = array(); public $allowed_prefs = array(); public $allowed_session_prefs = array(); + public $active_plugins = array(); protected $plugins = array(); protected $tasks = array(); @@ -45,7 +46,7 @@ protected $actionmap = array(); protected $objectsmap = array(); protected $template_contents = array(); - protected $active_hook = false; + protected $exec_stack = array(); // Deprecated names of hooks, will be removed after 0.5-stable release protected $deprecated_hooks = array( @@ -169,10 +170,11 @@ * * @param string Plugin name * @param boolean Force loading of the plugin even if it doesn't match the filter + * @param boolean Require loading of the plugin, error if it doesn't exist * * @return boolean True on success, false if not loaded or failure */ - public function load_plugin($plugin_name, $force = false) + public function load_plugin($plugin_name, $force = false, $require = true) { static $plugins_dir; @@ -186,10 +188,9 @@ return true; } - $fn = $plugins_dir . DIRECTORY_SEPARATOR . $plugin_name - . DIRECTORY_SEPARATOR . $plugin_name . '.php'; + $fn = "$plugins_dir/$plugin_name/$plugin_name.php"; - if (file_exists($fn)) { + if (is_readable($fn)) { if (!class_exists($plugin_name, false)) { include $fn; } @@ -197,6 +198,8 @@ // instantiate class if exists if (class_exists($plugin_name, false)) { $plugin = new $plugin_name($this); + $this->active_plugins[] = $plugin_name; + // check inheritance... if (is_subclass_of($plugin, 'rcube_plugin')) { // ... task, request type and framed mode @@ -222,7 +225,7 @@ true, false); } } - else { + elseif ($require) { rcube::raise_error(array('code' => 520, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__, 'message' => "Failed to load plugin file $fn"), true, false); @@ -233,7 +236,7 @@ /** * Get information about a specific plugin. - * This is either provided by a plugin's info() method or extracted from a package.xml or a composer.json file + * This is either provided my a plugin's info() method or extracted from a package.xml or a composer.json file * * @param string Plugin name * @return array Meta information about a plugin or False if plugin was not found @@ -252,6 +255,9 @@ 'GPL-3.0' => 'http://www.gnu.org/licenses/gpl-3.0.html', 'GPL-3.0+' => 'http://www.gnu.org/licenses/gpl.html', 'GPL-2.0+' => 'http://www.gnu.org/licenses/gpl.html', + 'AGPLv3' => 'http://www.gnu.org/licenses/agpl.html', + 'AGPLv3+' => 'http://www.gnu.org/licenses/agpl.html', + 'AGPL-3.0' => 'http://www.gnu.org/licenses/agpl.html', 'LGPL' => 'http://www.gnu.org/licenses/lgpl.html', 'LGPLv2' => 'http://www.gnu.org/licenses/lgpl-2.0.html', 'LGPLv2.1' => 'http://www.gnu.org/licenses/lgpl-2.1.html', @@ -272,24 +278,33 @@ ); $dir = dir($this->dir); - $fn = unslashify($dir->path) . DIRECTORY_SEPARATOR . $plugin_name . DIRECTORY_SEPARATOR . $plugin_name . '.php'; + $fn = unslashify($dir->path) . "/$plugin_name/$plugin_name.php"; $info = false; - if (!class_exists($plugin_name)) - include($fn); + if (!class_exists($plugin_name, false)) { + if (is_readable($fn)) + include($fn); + else + return false; + } if (class_exists($plugin_name)) - $info = call_user_func(array($plugin_name, 'info')); + $info = $plugin_name::info(); // fall back to composer.json file if (!$info) { $composer = INSTALL_PATH . "/plugins/$plugin_name/composer.json"; - if (file_exists($composer) && ($json = @json_decode(file_get_contents($composer), true))) { + if (is_readable($composer) && ($json = @json_decode(file_get_contents($composer), true))) { list($info['vendor'], $info['name']) = explode('/', $json['name']); $info['version'] = $json['version']; $info['license'] = $json['license']; - if ($license_uri = $license_uris[$info['license']]) - $info['license_uri'] = $license_uri; + $info['uri'] = $json['homepage']; + $info['require'] = array_filter(array_keys((array)$json['require']), function($pname) { + if (strpos($pname, '/') == false) + return false; + list($vendor, $name) = explode('/', $pname); + return !($name == 'plugin-installer' || $vendor == 'pear-pear'); + }); } // read local composer.lock file (once) @@ -313,7 +328,7 @@ // fall back to package.xml file if (!$info) { $package = INSTALL_PATH . "/plugins/$plugin_name/package.xml"; - if (file_exists($package) && ($file = file_get_contents($package))) { + if (is_readable($package) && ($file = file_get_contents($package))) { $doc = new DOMDocument(); $doc->loadXML($file); $xpath = new DOMXPath($doc); @@ -337,11 +352,19 @@ $deps = $xpath->evaluate('//rc:package/rc:dependencies/rc:required/rc:package/rc:name'); for ($i = 0; $i < $deps->length; $i++) { $dn = $deps->item($i)->nodeValue; - $info['requires'][] = $dn; + $info['require'][] = $dn; } } } + // At least provide the name + if (!$info && class_exists($plugin_name)) { + $info = array('name' => $plugin_name, 'version' => '--'); + } + else if ($info['license'] && empty($info['license_uri']) && ($license_uri = $license_uris[$info['license']])) { + $info['license_uri'] = $license_uri; + } + return $info; } @@ -399,8 +422,10 @@ $args = array('arg' => $args); } + // TODO: avoid recusion by checking in_array($hook, $this->exec_stack) ? + $args += array('abort' => false); - $this->active_hook = $hook; + array_push($this->exec_stack, $hook); foreach ((array)$this->handlers[$hook] as $callback) { $ret = call_user_func($callback, $args); @@ -413,7 +438,7 @@ } } - $this->active_hook = false; + array_pop($this->exec_stack); return $args; } @@ -549,7 +574,7 @@ */ public function is_processing($hook = null) { - return $this->active_hook && (!$hook || $this->active_hook == $hook); + return count($this->exec_stack) > 0 && (!$hook || in_array($hook, $this->exec_stack)); } /** @@ -601,6 +626,16 @@ } /** + * Returns loaded plugin + * + * @return rcube_plugin Plugin instance + */ + public function get_plugin($name) + { + return $this->plugins[$name]; + } + + /** * Callback for template_container hooks * * @param array $attrib
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_result_index.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_result_index.php
Changed
@@ -26,6 +26,8 @@ */ class rcube_result_index { + public $incomplete = false; + protected $raw_data; protected $mailbox; protected $meta = array();
View file
kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_result_multifolder.php
Added
@@ -0,0 +1,337 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | This file is part of the Roundcube Webmail client | + | Copyright (C) 2005-2011, The Roundcube Dev Team | + | Copyright (C) 2011, Kolab Systems AG | + | | + | 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: | + | SORT/SEARCH/ESEARCH response handler | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ +*/ + +/** + * Class holding a set of rcube_result_index instances that together form a + * result set of a multi-folder search + * + * @package Framework + * @subpackage Storage + */ +class rcube_result_multifolder +{ + public $multi = true; + public $sets = array(); + public $incomplete = false; + public $folder; + + protected $meta = array(); + protected $index = array(); + protected $folders = array(); + protected $order = 'ASC'; + protected $sorting; + + + /** + * Object constructor. + */ + public function __construct($folders = array()) + { + $this->folders = $folders; + $this->meta = array('count' => 0); + } + + + /** + * Initializes object with SORT command response + * + * @param string $data IMAP response string + */ + public function add($result) + { + $this->sets[] = $result; + + if ($result->count()) { + $this->append_result($result); + } + else if ($result->incomplete) { + $this->incomplete = true; + } + } + + /** + * Append message UIDs from the given result to our index + */ + protected function append_result($result) + { + $this->meta['count'] += $result->count(); + + // append UIDs to global index + $folder = $result->get_parameters('MAILBOX'); + $index = array_map(function($uid) use ($folder) { return $uid . '-' . $folder; }, $result->get()); + + $this->index = array_merge($this->index, $index); + } + + /** + * Store a global index of (sorted) message UIDs + */ + public function set_message_index($headers, $sort_field, $sort_order) + { + $this->index = array(); + foreach ($headers as $header) { + $this->index[] = $header->uid . '-' . $header->folder; + } + + $this->sorting = $sort_field; + $this->order = $sort_order; + } + + /** + * Checks the result from IMAP command + * + * @return bool True if the result is an error, False otherwise + */ + public function is_error() + { + return false; + } + + + /** + * Checks if the result is empty + * + * @return bool True if the result is empty, False otherwise + */ + public function is_empty() + { + return empty($this->sets) || $this->meta['count'] == 0; + } + + + /** + * Returns number of elements in the result + * + * @return int Number of elements + */ + public function count() + { + return $this->meta['count']; + } + + + /** + * Returns number of elements in the result. + * Alias for count() for compatibility with rcube_result_thread + * + * @return int Number of elements + */ + public function count_messages() + { + return $this->count(); + } + + + /** + * Reverts order of elements in the result + */ + public function revert() + { + $this->order = $this->order == 'ASC' ? 'DESC' : 'ASC'; + $this->index = array(); + + // revert order in all sub-sets + foreach ($this->sets as $set) { + if ($this->order != $set->get_parameters('ORDER')) { + $set->revert(); + } + + $folder = $set->get_parameters('MAILBOX'); + $index = array_map(function($uid) use ($folder) { return $uid . '-' . $folder; }, $set->get()); + + $this->index = array_merge($this->index, $index); + } + } + + + /** + * Check if the given message ID exists in the object + * + * @param int $msgid Message ID + * @param bool $get_index When enabled element's index will be returned. + * Elements are indexed starting with 0 + * @return mixed False if message ID doesn't exist, True if exists or + * index of the element if $get_index=true + */ + public function exists($msgid, $get_index = false) + { + if (!empty($this->folder)) { + $msgid .= '-' . $this->folder; + } + + return array_search($msgid, $this->index); + } + + + /** + * Filters data set. Removes elements listed in $ids list. + * + * @param array $ids List of IDs to remove. + * @param string $folder IMAP folder + */ + public function filter($ids = array(), $folder = null) + { + $this->meta['count'] = 0; + foreach ($this->sets as $set) { + if ($set->get_parameters('MAILBOX') == $folder) { + $set->filter($ids); + } + + $this->meta['count'] += $set->count(); + } + } +
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_result_thread.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_result_thread.php
Changed
@@ -26,6 +26,8 @@ */ class rcube_result_thread { + public $incomplete = false; + protected $raw_data; protected $mailbox; protected $meta = array();
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_session.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_session.php
Changed
@@ -3,7 +3,7 @@ /* +-----------------------------------------------------------------------+ | This file is part of the Roundcube Webmail client | - | Copyright (C) 2005-2012, The Roundcube Dev Team | + | Copyright (C) 2005-2014, The Roundcube Dev Team | | Copyright (C) 2011, Kolab Systems AG | | | | Licensed under the GNU General Public License version 3 or | @@ -47,6 +47,13 @@ private $storage; private $memcache; + /** + * Blocks session data from being written to database. + * Can be used if write-race conditions are to be expected + * @var boolean + */ + public $nowrite = false; + /** * Default constructor @@ -96,6 +103,8 @@ array($this, 'db_write'), array($this, 'db_destroy'), array($this, 'gc')); + + $this->table_name = $this->db->table_name('session', true); } } @@ -168,9 +177,8 @@ public function db_read($key) { $sql_result = $this->db->query( - "SELECT vars, ip, changed, " . $this->db->now() . " AS ts" - . " FROM " . $this->db->table_name('session') - . " WHERE sess_id = ?", $key); + "SELECT `vars`, `ip`, `changed`, " . $this->db->now() . " AS ts" + . " FROM {$this->table_name} WHERE `sess_id` = ?", $key); if ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) { $this->time_diff = time() - strtotime($sql_arr['ts']); @@ -197,9 +205,11 @@ */ public function db_write($key, $vars) { - $now = $this->db->now(); - $table = $this->db->table_name('session'); - $ts = microtime(true); + $now = $this->db->now(); + $ts = microtime(true); + + if ($this->nowrite) + return true; // no session row in DB (db_read() returns false) if (!$this->key) { @@ -217,17 +227,18 @@ $newvars = $this->_fixvars($vars, $oldvars); if ($newvars !== $oldvars) { - $this->db->query("UPDATE $table " - . "SET changed = $now, vars = ? WHERE sess_id = ?", + $this->db->query("UPDATE {$this->table_name} " + . "SET `changed` = $now, `vars` = ? WHERE `sess_id` = ?", base64_encode($newvars), $key); } else if ($ts - $this->changed + $this->time_diff > $this->lifetime / 2) { - $this->db->query("UPDATE $table SET changed = $now" - . " WHERE sess_id = ?", $key); + $this->db->query("UPDATE {$this->table_name} SET `changed` = $now" + . " WHERE `sess_id` = ?", $key); } } else { - $this->db->query("INSERT INTO $table (sess_id, vars, ip, created, changed)" + $this->db->query("INSERT INTO {$this->table_name}" + . " (`sess_id`, `vars`, `ip`, `created`, `changed`)" . " VALUES (?, ?, ?, $now, $now)", $key, base64_encode($vars), (string)$this->ip); } @@ -280,8 +291,7 @@ public function db_destroy($key) { if ($key) { - $this->db->query(sprintf("DELETE FROM %s WHERE sess_id = ?", - $this->db->table_name('session')), $key); + $this->db->query("DELETE FROM {$this->table_name} WHERE `sess_id` = ?", $key); } return true; @@ -397,8 +407,8 @@ if ($this->gc_enabled) { // just delete all expired sessions if ($this->storage == 'db') { - $this->db->query("DELETE FROM " . $this->db->table_name('session') - . " WHERE changed < " . $this->db->now(-$this->gc_enabled)); + $this->db->query("DELETE FROM {$this->table_name}" + . " WHERE `changed` < " . $this->db->now(-$this->gc_enabled)); } foreach ($this->gc_handlers as $fct) {
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_spellchecker.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_spellchecker.php
Changed
@@ -226,7 +226,18 @@ else { $word = mb_substr($this->content, $item[1], $item[2], RCUBE_CHARSET); } - $result[$word] = is_array($item[4]) ? implode("\t", $item[4]) : $item[4]; + + if (is_array($item[4])) { + $suggestions = $item[4]; + } + else if (empty($item[4])) { + $suggestions = array(); + } + else { + $suggestions = explode("\t", $item[4]); + } + + $result[$word] = $suggestions; } return $result; @@ -349,25 +360,25 @@ if ($this->have_dict) { if (!empty($this->dict)) { $this->rc->db->query( - "UPDATE ".$this->rc->db->table_name('dictionary') - ." SET data = ?" - ." WHERE user_id " . ($plugin['userid'] ? "= ".$this->rc->db->quote($plugin['userid']) : "IS NULL") - ." AND " . $this->rc->db->quote_identifier('language') . " = ?", + "UPDATE " . $this->rc->db->table_name('dictionary', true) + ." SET `data` = ?" + ." WHERE `user_id` " . ($plugin['userid'] ? "= ".$this->rc->db->quote($plugin['userid']) : "IS NULL") + ." AND `language` = ?", implode(' ', $plugin['dictionary']), $plugin['language']); } // don't store empty dict else { $this->rc->db->query( - "DELETE FROM " . $this->rc->db->table_name('dictionary') - ." WHERE user_id " . ($plugin['userid'] ? "= ".$this->rc->db->quote($plugin['userid']) : "IS NULL") - ." AND " . $this->rc->db->quote_identifier('language') . " = ?", + "DELETE FROM " . $this->rc->db->table_name('dictionary', true) + ." WHERE `user_id` " . ($plugin['userid'] ? "= ".$this->rc->db->quote($plugin['userid']) : "IS NULL") + ." AND `language` = ?", $plugin['language']); } } else if (!empty($this->dict)) { $this->rc->db->query( - "INSERT INTO " .$this->rc->db->table_name('dictionary') - ." (user_id, " . $this->rc->db->quote_identifier('language') . ", data) VALUES (?, ?, ?)", + "INSERT INTO " . $this->rc->db->table_name('dictionary', true) + ." (`user_id`, `language`, `data`) VALUES (?, ?, ?)", $plugin['userid'], $plugin['language'], implode(' ', $plugin['dictionary'])); } } @@ -392,9 +403,9 @@ if (empty($plugin['abort'])) { $dict = array(); $sql_result = $this->rc->db->query( - "SELECT data FROM ".$this->rc->db->table_name('dictionary') - ." WHERE user_id ". ($plugin['userid'] ? "= ".$this->rc->db->quote($plugin['userid']) : "IS NULL") - ." AND " . $this->rc->db->quote_identifier('language') . " = ?", + "SELECT `data` FROM " . $this->rc->db->table_name('dictionary', true) + ." WHERE `user_id` ". ($plugin['userid'] ? "= ".$this->rc->db->quote($plugin['userid']) : "IS NULL") + ." AND `language` = ?", $plugin['language']); if ($sql_arr = $this->rc->db->fetch_assoc($sql_result)) { @@ -416,5 +427,4 @@ return $this->dict; } - }
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_storage.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_storage.php
Changed
@@ -35,9 +35,15 @@ */ public $conn; + /** + * List of supported special folder types + * + * @var array + */ + public static $folder_types = array('drafts', 'sent', 'junk', 'trash'); + protected $folder = 'INBOX'; protected $default_charset = 'ISO-8859-1'; - protected $default_folders = array('INBOX'); protected $search_set; protected $options = array('auth_type' => 'check'); protected $page_size = 10; @@ -146,6 +152,19 @@ /** + * Get connection/class option + * + * @param string $name Option name + * + * @param mixed Option value + */ + public function get_option($name) + { + return $this->options[$name]; + } + + + /** * Activate/deactivate debug mode. * * @param boolean $dbg True if conversation with the server should be logged @@ -167,24 +186,6 @@ /** - * This list of folders will be listed above all other folders - * - * @param array $arr Indexed list of folder names - */ - public function set_default_folders($arr) - { - if (is_array($arr)) { - $this->default_folders = $arr; - - // add inbox if not included - if (!in_array('INBOX', $this->default_folders)) { - array_unshift($this->default_folders, 'INBOX'); - } - } - } - - - /** * Set internal folder reference. * All operations will be perfomed on this folder. * @@ -858,24 +859,70 @@ */ public function create_default_folders() { + $rcube = rcube::get_instance(); + // create default folders if they do not exist - foreach ($this->default_folders as $folder) { - if (!$this->folder_exists($folder)) { - $this->create_folder($folder, true); + foreach (self::$folder_types as $type) { + if ($folder = $rcube->config->get($type . '_mbox')) { + if (!$this->folder_exists($folder)) { + $this->create_folder($folder, true, $type); + } + else if (!$this->folder_exists($folder, true)) { + $this->subscribe($folder); + } } - else if (!$this->folder_exists($folder, true)) { - $this->subscribe($folder); + } + } + + + /** + * Check if specified folder is a special folder + */ + public function is_special_folder($name) + { + return $name == 'INBOX' || in_array($name, $this->get_special_folders()); + } + + + /** + * Return configured special folders + */ + public function get_special_folders($forced = false) + { + // getting config might be expensive, store special folders in memory + if (!isset($this->icache['special-folders'])) { + $rcube = rcube::get_instance(); + $this->icache['special-folders'] = array(); + + foreach (self::$folder_types as $type) { + if ($folder = $rcube->config->get($type . '_mbox')) { + $this->icache['special-folders'][$type] = $folder; + } } } + + return $this->icache['special-folders']; + } + + + /** + * Set special folder associations stored in backend + */ + public function set_special_folders($specials) + { + // should be overriden by storage class if backend supports special folders (SPECIAL-USE) + unset($this->icache['special-folders']); } /** * Get mailbox quota information. * + * @param string $folder Folder name + * * @return mixed Quota info or False if not supported */ - abstract function get_quota(); + abstract function get_quota($folder = null); /* -----------------------------------------
View file
kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_tnef_decoder.php
Added
@@ -0,0 +1,341 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | This file is part of the Roundcube Webmail client | + | Copyright (C) 2008-2014, The Roundcube Dev Team | + | Copyright (C) 2002-2010, The Horde Project (http://www.horde.org/) | + | | + | 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: | + | MS-TNEF format decoder | + +-----------------------------------------------------------------------+ + | Author: Jan Schneider <jan@horde.org> | + | Author: Michael Slusarz <slusarz@horde.org> | + +-----------------------------------------------------------------------+ +*/ + +/** + * MS-TNEF format decoder based on code by: + * Graham Norbury <gnorbury@bondcar.com> + * Original design by: + * Thomas Boll <tb@boll.ch>, Mark Simpson <damned@world.std.com> + * + * @package Framework + * @subpackage Storage + */ +class rcube_tnef_decoder +{ + const SIGNATURE = 0x223e9f78; + const LVL_MESSAGE = 0x01; + const LVL_ATTACHMENT = 0x02; + + const ASUBJECT = 0x88004; + const AMCLASS = 0x78008; + const ATTACHDATA = 0x6800f; + const AFILENAME = 0x18010; + const ARENDDATA = 0x69002; + const AMAPIATTRS = 0x69005; + const AVERSION = 0x89006; + + const MAPI_NULL = 0x0001; + const MAPI_SHORT = 0x0002; + const MAPI_INT = 0x0003; + const MAPI_FLOAT = 0x0004; + const MAPI_DOUBLE = 0x0005; + const MAPI_CURRENCY = 0x0006; + const MAPI_APPTIME = 0x0007; + const MAPI_ERROR = 0x000a; + const MAPI_BOOLEAN = 0x000b; + const MAPI_OBJECT = 0x000d; + const MAPI_INT8BYTE = 0x0014; + const MAPI_STRING = 0x001e; + const MAPI_UNICODE_STRING = 0x001f; + const MAPI_SYSTIME = 0x0040; + const MAPI_CLSID = 0x0048; + const MAPI_BINARY = 0x0102; + + const MAPI_ATTACH_LONG_FILENAME = 0x3707; + const MAPI_ATTACH_MIME_TAG = 0x370E; + + const MAPI_NAMED_TYPE_ID = 0x0000; + const MAPI_NAMED_TYPE_STRING = 0x0001; + const MAPI_MV_FLAG = 0x1000; + + /** + * Decompress the data. + * + * @param string $data The data to decompress. + * @param array $params An array of arguments needed to decompress the + * data. + * + * @return mixed The decompressed data. + */ + public function decompress($data, $params = array()) + { + $out = array(); + + if ($this->_geti($data, 32) == self::SIGNATURE) { + $this->_geti($data, 16); + + while (strlen($data) > 0) { + switch ($this->_geti($data, 8)) { + case self::LVL_MESSAGE: + $this->_decodeMessage($data); + break; + + case self::LVL_ATTACHMENT: + $this->_decodeAttachment($data, $out); + break; + } + } + } + + return array_reverse($out); + } + + /** + * TODO + * + * @param string &$data The data string. + * @param integer $bits How many bits to retrieve. + * + * @return TODO + */ + protected function _getx(&$data, $bits) + { + $value = null; + + if (strlen($data) >= $bits) { + $value = substr($data, 0, $bits); + $data = substr_replace($data, '', 0, $bits); + } + + return $value; + } + + /** + * TODO + * + * @param string &$data The data string. + * @param integer $bits How many bits to retrieve. + * + * @return TODO + */ + protected function _geti(&$data, $bits) + { + $bytes = $bits / 8; + $value = null; + + if (strlen($data) >= $bytes) { + $value = ord($data[0]); + if ($bytes >= 2) { + $value += (ord($data[1]) << 8); + } + if ($bytes >= 4) { + $value += (ord($data[2]) << 16) + (ord($data[3]) << 24); + } + $data = substr_replace($data, '', 0, $bytes); + } + + return $value; + } + + /** + * TODO + * + * @param string &$data The data string. + * @param string $attribute TODO + */ + protected function _decodeAttribute(&$data, $attribute) + { + /* Data. */ + $this->_getx($data, $this->_geti($data, 32)); + + /* Checksum. */ + $this->_geti($data, 16); + } + + /** + * TODO + * + * @param string $data The data string. + * @param array &$attachment_data TODO + */ + protected function _extractMapiAttributes($data, &$attachment_data) + { + /* Number of attributes. */ + $number = $this->_geti($data, 32); + + while ((strlen($data) > 0) && $number--) { + $have_mval = false; + $num_mval = 1; + $named_id = $value = null; + $attr_type = $this->_geti($data, 16); + $attr_name = $this->_geti($data, 16); + + if (($attr_type & self::MAPI_MV_FLAG) != 0) { + $have_mval = true; + $attr_type = $attr_type & ~self::MAPI_MV_FLAG; + } + + if (($attr_name >= 0x8000) && ($attr_name < 0xFFFE)) { + $this->_getx($data, 16); + $named_type = $this->_geti($data, 32); + + switch ($named_type) { + case self::MAPI_NAMED_TYPE_ID: + $named_id = $this->_geti($data, 32); + $attr_name = $named_id; + break; + + case self::MAPI_NAMED_TYPE_STRING: + $attr_name = 0x9999; + $idlen = $this->_geti($data, 32); + $datalen = $idlen + ((4 - ($idlen % 4)) % 4); + $named_id = substr($this->_getx($data, $datalen), 0, $idlen);
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_user.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_user.php
Changed
@@ -67,7 +67,8 @@ if ($id && !$sql_arr) { $sql_result = $this->db->query( - "SELECT * FROM ".$this->db->table_name('users')." WHERE user_id = ?", $id); + "SELECT * FROM " . $this->db->table_name('users', true) + . " WHERE `user_id` = ?", $id); $sql_arr = $this->db->fetch_assoc($sql_result); } @@ -189,10 +190,9 @@ $save_prefs = serialize($save_prefs); $this->db->query( - "UPDATE ".$this->db->table_name('users'). - " SET preferences = ?". - ", language = ?". - " WHERE user_id = ?", + "UPDATE ".$this->db->table_name('users', true). + " SET `preferences` = ?, `language` = ?". + " WHERE `user_id` = ?", $save_prefs, $_SESSION['language'], $this->ID); @@ -243,7 +243,7 @@ $id = (int)$id; // cache identities for better performance if (!array_key_exists($id, $this->identities)) { - $result = $this->list_identities($id ? 'AND identity_id = ' . $id : ''); + $result = $this->list_identities($id ? "AND `identity_id` = $id" : ''); $this->identities[$id] = $result[0]; } @@ -264,10 +264,10 @@ $result = array(); $sql_result = $this->db->query( - "SELECT * FROM ".$this->db->table_name('identities'). - " WHERE del <> 1 AND user_id = ?". + "SELECT * FROM ".$this->db->table_name('identities', true). + " WHERE `del` <> 1 AND `user_id` = ?". ($sql_add ? " ".$sql_add : ""). - " ORDER BY ".$this->db->quote_identifier('standard')." DESC, name ASC, identity_id ASC", + " ORDER BY `standard` DESC, `name` ASC, `email` ASC, `identity_id` ASC", $this->ID); while ($sql_arr = $this->db->fetch_assoc($sql_result)) { @@ -308,11 +308,11 @@ $query_params[] = $iid; $query_params[] = $this->ID; - $sql = "UPDATE ".$this->db->table_name('identities'). - " SET changed = ".$this->db->now().", ".join(', ', $query_cols). - " WHERE identity_id = ?". - " AND user_id = ?". - " AND del <> 1"; + $sql = "UPDATE ".$this->db->table_name('identities', true). + " SET `changed` = ".$this->db->now().", ".join(', ', $query_cols). + " WHERE `identity_id` = ?". + " AND `user_id` = ?". + " AND `del` <> 1"; call_user_func_array(array($this->db, 'query'), array_merge(array($sql), $query_params)); @@ -341,11 +341,11 @@ $insert_cols[] = $this->db->quote_identifier($col); $insert_values[] = $value; } - $insert_cols[] = 'user_id'; + $insert_cols[] = $this->db->quote_identifier('user_id'); $insert_values[] = $this->ID; - $sql = "INSERT INTO ".$this->db->table_name('identities'). - " (changed, ".join(', ', $insert_cols).")". + $sql = "INSERT INTO ".$this->db->table_name('identities', true). + " (`changed`, ".join(', ', $insert_cols).")". " VALUES (".$this->db->now().", ".join(', ', array_pad(array(), sizeof($insert_values), '?')).")"; call_user_func_array(array($this->db, 'query'), @@ -369,8 +369,8 @@ return false; $sql_result = $this->db->query( - "SELECT count(*) AS ident_count FROM ".$this->db->table_name('identities'). - " WHERE user_id = ? AND del <> 1", + "SELECT count(*) AS ident_count FROM ".$this->db->table_name('identities', true). + " WHERE `user_id` = ? AND `del` <> 1", $this->ID); $sql_arr = $this->db->fetch_assoc($sql_result); @@ -380,10 +380,10 @@ return -1; $this->db->query( - "UPDATE ".$this->db->table_name('identities'). - " SET del = 1, changed = ".$this->db->now(). - " WHERE user_id = ?". - " AND identity_id = ?", + "UPDATE ".$this->db->table_name('identities', true). + " SET `del` = 1, `changed` = ".$this->db->now(). + " WHERE `user_id` = ?". + " AND `identity_id` = ?", $this->ID, $iid); @@ -402,11 +402,9 @@ { if ($this->ID && $iid) { $this->db->query( - "UPDATE ".$this->db->table_name('identities'). - " SET ".$this->db->quote_identifier('standard')." = '0'". - " WHERE user_id = ?". - " AND identity_id <> ?". - " AND del <> 1", + "UPDATE ".$this->db->table_name('identities', true). + " SET `standard` = '0'". + " WHERE `user_id` = ? AND `identity_id` <> ?", $this->ID, $iid); @@ -422,9 +420,9 @@ { if ($this->ID) { $this->db->query( - "UPDATE ".$this->db->table_name('users'). - " SET last_login = ".$this->db->now(). - " WHERE user_id = ?", + "UPDATE ".$this->db->table_name('users', true). + " SET `last_login` = ".$this->db->now(). + " WHERE `user_id` = ?", $this->ID); } } @@ -453,17 +451,17 @@ $config = rcube::get_instance()->config; // query for matching user name - $sql_result = $dbh->query("SELECT * FROM " . $dbh->table_name('users') - ." WHERE mail_host = ? AND username = ?", $host, $user); + $sql_result = $dbh->query("SELECT * FROM " . $dbh->table_name('users', true) + ." WHERE `mail_host` = ? AND `username` = ?", $host, $user); $sql_arr = $dbh->fetch_assoc($sql_result); // username not found, try aliases from identities if (empty($sql_arr) && $config->get('user_aliases') && strpos($user, '@')) { $sql_result = $dbh->limitquery("SELECT u.*" - ." FROM " . $dbh->table_name('users') . " u" - ." JOIN " . $dbh->table_name('identities') . " i ON (i.user_id = u.user_id)" - ." WHERE email = ? AND del <> 1", 0, 1, $user); + ." FROM " . $dbh->table_name('users', true) . " u" + ." JOIN " . $dbh->table_name('identities', true) . " i ON (i.`user_id` = u.`user_id`)" + ." WHERE `email` = ? AND `del` <> 1", 0, 1, $user); $sql_arr = $dbh->fetch_assoc($sql_result); } @@ -510,8 +508,8 @@ } $dbh->query( - "INSERT INTO ".$dbh->table_name('users'). - " (created, last_login, username, mail_host, language)". + "INSERT INTO ".$dbh->table_name('users', true). + " (`created`, `last_login`, `username`, `mail_host`, `language`)". " VALUES (".$dbh->now().", ".$dbh->now().", ?, ?, ?)", $data['user'], $data['host'], @@ -643,11 +641,10 @@ $result = array(); $sql_result = $this->db->query( - "SELECT search_id AS id, ".$this->db->quote_identifier('name') - ." FROM ".$this->db->table_name('searches') - ." WHERE user_id = ?" - ." AND ".$this->db->quote_identifier('type')." = ?" - ." ORDER BY ".$this->db->quote_identifier('name'), + "SELECT `search_id` AS id, `name`" + ." FROM ".$this->db->table_name('searches', true) + ." WHERE `user_id` = ? AND `type` = ?" + ." ORDER BY `name`", (int) $this->ID, (int) $type); while ($sql_arr = $this->db->fetch_assoc($sql_result)) { @@ -675,12 +672,10 @@ } $sql_result = $this->db->query( - "SELECT ".$this->db->quote_identifier('name') - .", ".$this->db->quote_identifier('data') - .", ".$this->db->quote_identifier('type') - ." FROM ".$this->db->table_name('searches') - ." WHERE user_id = ?" - ." AND search_id = ?", + "SELECT `name`, `data`, `type`" + . " FROM ".$this->db->table_name('searches', true) + . " WHERE `user_id` = ?" + ." AND `search_id` = ?", (int) $this->ID, (int) $id); while ($sql_arr = $this->db->fetch_assoc($sql_result)) {
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_utils.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_utils.php
Changed
@@ -103,13 +103,14 @@ } foreach ($domain_array as $part) { - if (!preg_match('/^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]))$/', $part)) { + if (!preg_match('/^((xn--)?([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]))$/', $part)) { return false; } } // last domain part - if (preg_match('/[^a-zA-Z]/', array_pop($domain_array))) { + $last_part = array_pop($domain_array); + if (strpos($last_part, 'xn--') !== 0 && preg_match('/[^a-zA-Z]/', $last_part)) { return false; } @@ -119,17 +120,6 @@ return true; } - if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' && version_compare(PHP_VERSION, '5.3.0', '<')) { - $lookup = array(); - @exec("nslookup -type=MX " . escapeshellarg($domain_part) . " 2>&1", $lookup); - foreach ($lookup as $line) { - if (strpos($line, 'MX preference')) { - return true; - } - } - return false; - } - // find MX record(s) if (!function_exists('getmxrr') || getmxrr($domain_part, $mx_records)) { return true; @@ -795,7 +785,7 @@ * * @return object DateTime instance or false on failure */ - public static function anytodatetime($date) + public static function anytodatetime($date, $timezone = null) { if (is_object($date) && is_a($date, 'DateTime')) { return $date; @@ -807,7 +797,7 @@ // try to parse string with DateTime first if (!empty($date)) { try { - $dt = new DateTime($date); + $dt = new DateTime($date, $timezone); } catch (Exception $e) { // ignore @@ -1079,7 +1069,37 @@ return (bool) preg_match('!^[a-z]:[\\\\/]!i', $path); } else { - return $path[0] == DIRECTORY_SEPARATOR; + return $path[0] == '/'; + } + } + + /** + * Resolve relative URL + * + * @param string $url Relative URL + * + * @return string Absolute URL + */ + public static function resolve_url($url) + { + // prepend protocol://hostname:port + if (!preg_match('|^https?://|', $url)) { + $schema = 'http'; + $default_port = 80; + + if (self::https_check()) { + $schema = 'https'; + $default_port = 443; + } + + $prefix = $schema . '://' . preg_replace('/:\d+$/', '', $_SERVER['HTTP_HOST']); + if ($_SERVER['SERVER_PORT'] != $default_port) { + $prefix .= ':' . $_SERVER['SERVER_PORT']; + } + + $url = $prefix . ($url[0] == '/' ? '' : '/') . $url; } + + return $url; } }
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Roundcube/rcube_washtml.php -> kolab-syncroton-2.3.0.tar.gz/lib/ext/Roundcube/rcube_washtml.php
Changed
@@ -95,6 +95,7 @@ 'ins', 'label', 'legend', 'li', 'map', 'menu', 'nobr', 'ol', 'p', 'pre', 'q', 's', 'samp', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'u', 'ul', 'var', 'wbr', 'img', + 'video', 'source', // form elements 'button', 'input', 'textarea', 'select', 'option', 'optgroup' ); @@ -246,7 +247,10 @@ $quot = strpos($style, '"') !== false ? "'" : '"'; $t .= ' style=' . $quot . $style . $quot; } - else if ($key == 'background' || ($key == 'src' && strtolower($node->tagName) == 'img')) { //check tagName anyway + else if ($key == 'background' + || ($key == 'src' && preg_match('/^(img|source)$/i', $node->tagName)) + || ($key == 'poster' && strtolower($node->tagName) == 'video') + ) { if (($src = $this->config['cid_map'][$value]) || ($src = $this->config['cid_map'][$this->config['base_url'].$value]) ) { @@ -374,7 +378,7 @@ $this->max_nesting_level = (int) @ini_get('xdebug.max_nesting_level'); // Use optimizations if supported - if (version_compare(PHP_VERSION, '5.4.0', '>=')) { + if (PHP_VERSION_ID >= 50400) { @$node->loadHTML($html, LIBXML_PARSEHUGE | LIBXML_COMPACT); } else {
View file
kolab-syncroton-2.3.tar.gz/lib/kolab_sync.php -> kolab-syncroton-2.3.0.tar.gz/lib/kolab_sync.php
Changed
@@ -46,7 +46,7 @@ public $password; const CHARSET = 'UTF-8'; - const VERSION = "2.3"; + const VERSION = "2.3.0"; /** @@ -251,7 +251,7 @@ // take the first entry if $host is not found if (is_array($host)) { - list($key, $val) = each($default_host); + list($key, $val) = each($host); $host = is_numeric($key) ? $val : $key; } }
View file
kolab-syncroton-2.3.tar.gz/lib/kolab_sync_backend.php -> kolab-syncroton-2.3.0.tar.gz/lib/kolab_sync_backend.php
Changed
@@ -246,11 +246,10 @@ * @param string $old_name Old folder name (UTF7-IMAP) * @param string $new_name New folder name (UTF7-IMAP) * @param int $type Folder (ActiveSync) type - * @param string $deviceid Device identifier * * @return bool True on success, False on failure */ - public function folder_rename($old_name, $new_name, $type, $deviceid) + public function folder_rename($old_name, $new_name, $type) { $this->folder_meta = null;
View file
kolab-syncroton-2.3.tar.gz/lib/kolab_sync_backend_content.php -> kolab-syncroton-2.3.0.tar.gz/lib/kolab_sync_backend_content.php
Changed
@@ -122,7 +122,7 @@ $folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId; $cachekey = $deviceId . ':' . $folderId; - unset($this->cache['content_folderstate'][$cache_key]); + unset($this->cache['content_folderstate'][$cachekey]); $where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId); $where[] = $this->db->quote_identifier('folder_id') . ' = ' . $this->db->quote($folderId);
View file
kolab-syncroton-2.3.tar.gz/lib/kolab_sync_backend_device.php -> kolab-syncroton-2.3.0.tar.gz/lib/kolab_sync_backend_device.php
Changed
@@ -308,7 +308,7 @@ $plugin = $engine->plugins->get_plugin('managesieve'); $vacation = $plugin->get_engine('vacation'); - if ($error = $vacation->connect($engine->username, $engine->password)) { + if ($vacation->connect($engine->username, $engine->password)) { throw new Exception("Connection to managesieve server failed"); }
View file
kolab-syncroton-2.3.tar.gz/lib/kolab_sync_data.php -> kolab-syncroton-2.3.0.tar.gz/lib/kolab_sync_data.php
Changed
@@ -339,7 +339,7 @@ // @TODO: folder type change? } else { - $result = $this->backend->folder_rename($old_name, $name, $type, $this->device->deviceid); + $result = $this->backend->folder_rename($old_name, $name, $type); } if ($result) { @@ -665,7 +665,7 @@ $changed = false; // compare states, get members of changed relations - foreach ($relations as $idx => $relation) { + foreach ($relations as $relation) { $rel_id = $relation['uid']; if ($relation['changed']) { @@ -1551,7 +1551,7 @@ // Tasks do not support exceptions if ($type == 'Event') { - $result['exceptions'] = $this->exceptions_from_kolab($collection, $data, $result); + $result['exceptions'] = $this->exceptions_from_kolab($collection, $data); } } @@ -1629,7 +1629,7 @@ /** * Convert Kolab event recurrence exceptions into ActiveSync */ - protected function exceptions_from_kolab($collection, $data, $result) + protected function exceptions_from_kolab($collection, $data) { if (empty($data['recurrence']['EXCEPTIONS']) && empty($data['recurrence']['EXDATE'])) { return null; @@ -1732,10 +1732,8 @@ */ protected function setKolabTags($uid, $tags) { - if (isset($data->categories)) { - $config = kolab_storage_config::get_instance(); - $config->save_tags($uid, $tags); - } + $config = kolab_storage_config::get_instance(); + $config->save_tags($uid, $tags); } /**
View file
kolab-syncroton-2.3.tar.gz/lib/kolab_sync_data_calendar.php -> kolab-syncroton-2.3.0.tar.gz/lib/kolab_sync_data_calendar.php
Changed
@@ -270,7 +270,6 @@ if (!empty($event['attendees'])) { foreach ($event['attendees'] as $idx => $attendee) { if ($attendee['role'] == 'ORGANIZER') { - $organizer = $attendee; if ($name = $attendee['name']) { $result['organizerName'] = $name; } @@ -298,7 +297,7 @@ if ($this->asversion >= 12) { $type = isset($attendee['role']) ? $this->attendeeTypeMap[$attendee['role']] : null; - $status = isset($attendee['status']) ? $this->attendeeStatusMap[$attende['status']] : null; + $status = isset($attendee['status']) ? $this->attendeeStatusMap[$attendee['status']] : null; $att['attendeeType'] = $type ? $type : self::ATTENDEE_TYPE_REQUIRED; $att['attendeeStatus'] = $status ? $status : self::ATTENDEE_STATUS_UNKNOWN; @@ -418,7 +417,7 @@ // It doesn't set all-day flag but the period is a whole day if (!$event['allday'] && $event['end'] && $event['start']) { $interval = @date_diff($event['start'], $event['end']); - if ($interval && $interval->format('%y%m%d%h%i%s') == '001000') { + if ($interval && $interval->format('%y%m%d%h%i%s') === '001000') { $event['allday'] = 1; $event['end'] = clone $event['start']; } @@ -492,7 +491,7 @@ public function setAttendeeStatus(Syncroton_Model_MeetingResponse $request) { // @TODO: not implemented - throw new Syncroton_Exception_Status_MeetingResponse(Syncroton_Exception_Status_MeetingMeeting::MEETING_ERROR); + throw new Syncroton_Exception_Status_MeetingResponse(Syncroton_Exception_Status_MeetingResponse::MEETING_ERROR); } /** @@ -541,7 +540,7 @@ $value = intval($matches[1]); switch ($matches[2]) { - case 'S': $value = 1; break; + case 'S': $value = intval(round($value/60)); break; case 'H': $value *= 60; break; case 'D': $value *= 24 * 60; break; case 'W': $value *= 7 * 24 * 60; break;
View file
kolab-syncroton-2.3.tar.gz/lib/kolab_sync_data_email.php -> kolab-syncroton-2.3.0.tar.gz/lib/kolab_sync_data_email.php
Changed
@@ -124,12 +124,11 @@ { $message = $this->getObject($serverId); + // error (message doesn't exist?) if (empty($message)) { - // @TODO: exception - return; + throw new Syncroton_Exception_NotFound("Message $serverId not found"); } - $msg = $this->parseMessageId($serverId); $headers = $message->headers; // rcube_message_header // Calendar namespace fields @@ -150,7 +149,6 @@ foreach ($addresses as $idx => $part) { // @FIXME: set name + address or address only? $addresses[$idx] = format_email_recipient($part['mailto'], $part['name']); - $addresses[$idx] = rcube_charset::clean($addresses[$idx]); } $value = implode(',', $addresses); @@ -169,6 +167,10 @@ continue; } + if (is_string($value)) { + $value = rcube_charset::clean($value); + } + $result[$key] = $value; } @@ -183,7 +185,7 @@ // Use FollowUp flag which is used in Android when message is marked with a star $result['flag'] = new Syncroton_Model_EmailFlag(array( 'flagType' => 'FollowUp', - 'status' => Syncroton_Model_EmailFlag::STATUS_ACTIVE, + 'status' => Syncroton_Model_EmailFlag::STATUS_ACTIVE, )); } @@ -335,7 +337,7 @@ foreach ($attachments as $attachment) { $att = array(); - $filename = $attachment->filename; + $filename = rcube_charset::clean($attachment->filename); if (empty($filename) && $attachment->mimetype == 'text/html') { $filename = 'HTML Part'; } @@ -346,10 +348,10 @@ $att['estimatedDataSize'] = $attachment->size; if (!empty($attachment->content_id)) { - $att['contentId'] = $attachment->content_id; + $att['contentId'] = rcube_charset::clean($attachment->content_id); } if (!empty($attachment->content_location)) { - $att['contentLocation'] = $attachment->content_location; + $att['contentLocation'] = rcube_charset::clean($attachment->content_location); } if (in_array($attachment, $message->inline_parts)) { @@ -640,7 +642,7 @@ * @param mixed $message MIME message * @param boolean $saveInSent Enables saving the sent message in Sent folder * - * @param throws Syncroton_Exception_Status + * @throws Syncroton_Exception_Status */ public function sendEmail($message, $saveInSent) { @@ -673,7 +675,7 @@ * @param boolean $saveInSent Enables saving the sent message in Sent folder * @param boolean $replaceMime If enabled, original message would be appended * - * @param throws Syncroton_Exception_Status + * @throws Syncroton_Exception_Status */ public function forwardEmail($itemId, $body, $saveInSent, $replaceMime) { @@ -690,9 +692,10 @@ or a meeting, the behavior of the SmartForward command is the same as that of the SmartReply command (section 2.2.2.18). */ - $msg = $this->parseMessageId($itemId); + $msg = $this->parseMessageId($itemId); + $message = $this->getObject($itemId); - if (empty($msg)) { + if (empty($message)) { throw new Syncroton_Exception_Status(Syncroton_Exception_Status::ITEM_NOT_FOUND); } @@ -717,7 +720,7 @@ } // Send message - $sent = $this->sendEmail($sync_msg, $saveInSent); + $this->sendEmail($sync_msg, $saveInSent); // Set FORWARDED flag on the replied message if (empty($message->headers->flags['FORWARDED'])) { @@ -734,14 +737,14 @@ * @param boolean $saveInSent Enables saving the sent message in Sent folder * @param boolean $replaceMime If enabled, original message would be appended * - * @param throws Syncroton_Exception_Status + * @throws Syncroton_Exception_Status */ public function replyEmail($itemId, $body, $saveInSent, $replaceMime) { $msg = $this->parseMessageId($itemId); $message = $this->getObject($itemId); - if (!$message) { + if (empty($message)) { throw new Syncroton_Exception_Status(Syncroton_Exception_Status::ITEM_NOT_FOUND); } @@ -767,7 +770,7 @@ } // Send message - $sent = $this->sendEmail($sync_msg, $saveInSent); + $this->sendEmail($sync_msg, $saveInSent); // Set ANSWERED flag on the replied message if (empty($message->headers->flags['ANSWERED'])) { @@ -809,10 +812,8 @@ $changed_msgs = $this->getChangesByRelations($folderid, $filter); $result = $result_type == self::RESULT_COUNT ? 0 : array(); - // no sorting for best performance - $sort_by = null; - $found = 0; - $ts = time(); + $found = 0; + $ts = time(); foreach ($folders as $folder_id) { $foldername = $this->backend->folder_id2name($folder_id, $this->device->deviceid); @@ -833,29 +834,26 @@ } // We're in "get changes" mode - $modified = false; if (isset($modseq_data)) { $folder_data = $this->storage->folder_data($foldername); - $got_changes = true; + $modified = false; + // If previous HIGHESTMODSEQ doesn't exist we can't get changes + // We can only get folder's HIGHESTMODSEQ value and store it for the next try + // Skip search if HIGHESTMODSEQ didn't change if ($folder_data['HIGHESTMODSEQ']) { $modseq_data[$foldername] = $folder_data['HIGHESTMODSEQ']; if ($modseq_data[$foldername] != $modseq[$foldername]) { $modseq_update = true; } - else { - $got_changes = false; + else if ($modseq && $modseq[$foldername]) { + $modified = true; + $filter_str .= " MODSEQ " . ($modseq[$foldername] + 1); } } - - // If previous HIGHESTMODSEQ doesn't exist we can't get changes - // We can only get folder's HIGHESTMODSEQ value and store it for the next try - // Skip search if HIGHESTMODSEQ didn't change - if (!$got_changes || empty($modseq) || empty($modseq[$foldername])) { - $modified = true; - } - - $filter_str .= " MODSEQ " . ($modseq[$foldername] + 1); + } + else { + $modified = true; } // We could use messages cache by replacing search() with index() @@ -947,7 +945,7 @@ // convert filter into one IMAP search string $filter_str = 'ALL UNDELETED'; - foreach ($filter as $idx => $filter_item) { + foreach ($filter as $filter_item) { if (is_string($filter_item)) { $filter_str .= ' ' . $filter_item; } @@ -984,7 +982,7 @@ $search = ''; $search_count = 0; - foreach ($result as $folder => $data) { + foreach ($result as $data) { foreach ($data as $p) {
View file
kolab-syncroton-2.3.tar.gz/lib/kolab_sync_data_gal.php -> kolab-syncroton-2.3.0.tar.gz/lib/kolab_sync_data_gal.php
Changed
@@ -286,7 +286,6 @@ */ protected function get_address_book($id) { - $contacts = null; $config = rcube::get_instance()->config; $ldap_config = (array) $config->get('ldap_public'); @@ -311,7 +310,7 @@ /* // set configured sort order if ($sort_col = $this->config->get('addressbook_sort_col')) - $contacts->set_sort_order($sort_col); + $book->set_sort_order($sort_col); */ // add to the 'books' array for shutdown function $this->address_books[$id] = $book;
View file
kolab-syncroton-2.3.tar.gz/lib/kolab_sync_data_notes.php -> kolab-syncroton-2.3.0.tar.gz/lib/kolab_sync_data_notes.php
Changed
@@ -85,7 +85,7 @@ public function getEntry(Syncroton_Model_SyncCollection $collection, $serverId, $as_array = false) { $note = is_array($serverId) ? $serverId : $this->getObject($collection->collectionId, $serverId); - $config = $this->getFolderConfig($note['_mailbox']); +// $config = $this->getFolderConfig($note['_mailbox']); $result = array(); // Calendar namespace fields @@ -130,7 +130,7 @@ { $note = !empty($entry) ? $entry : array(); $foldername = isset($note['_mailbox']) ? $note['_mailbox'] : $this->getFolderName($folderid); - $config = $this->getFolderConfig($foldername); +// $config = $this->getFolderConfig($foldername); // Calendar namespace fields foreach ($this->mapping as $key => $name) {
View file
kolab-syncroton-2.3.tar.gz/lib/kolab_sync_data_tasks.php -> kolab-syncroton-2.3.0.tar.gz/lib/kolab_sync_data_tasks.php
Changed
@@ -113,7 +113,7 @@ public function getEntry(Syncroton_Model_SyncCollection $collection, $serverId, $as_array = false) { $task = is_array($serverId) ? $serverId : $this->getObject($collection->collectionId, $serverId); - $config = $this->getFolderConfig($task['_mailbox']); +// $config = $this->getFolderConfig($task['_mailbox']); $result = array(); // Completion status (required) @@ -177,7 +177,7 @@ { $task = !empty($entry) ? $entry : array(); $foldername = isset($task['_mailbox']) ? $task['_mailbox'] : $this->getFolderName($folderid); - $config = $this->getFolderConfig($foldername); +// $config = $this->getFolderConfig($foldername); $task['allday'] = 0;
View file
kolab-syncroton-2.3.tar.gz/lib/kolab_sync_message.php -> kolab-syncroton-2.3.0.tar.gz/lib/kolab_sync_message.php
Changed
@@ -258,6 +258,8 @@ $sent = mail($to, $subject, $msg_body, $header_str); } else { + $from = rcube_mime::decode_address_list($headers['From'], 1, false, null, true); + $from = $from[0]; $sent = mail($to, $subject, $msg_body, $header_str, "-f$from"); } }
View file
kolab-syncroton-2.3.tar.gz/lib/kolab_sync_transaction_manager.php -> kolab-syncroton-2.3.0.tar.gz/lib/kolab_sync_transaction_manager.php
Changed
@@ -140,7 +140,7 @@ $numOpenTransactions = count($this->_openTransactions); if ($numOpenTransactions === 0) { - foreach ($this->_openTransactionables as $transactionableIdx => $transactionable) { + foreach ($this->_openTransactionables as $transactionable) { if ($transactionable instanceof rcube_db) { $transactionable->endTransaction(); }
View file
kolab-syncroton-2.3.tar.gz/lib/ext/tnef_decoder.php
Deleted
@@ -1,331 +0,0 @@ -<?php -/** - * The Horde's class allows MS-TNEF data to be displayed. - * - * The TNEF rendering is based on code by: - * Graham Norbury <gnorbury@bondcar.com> - * Original design by: - * Thomas Boll <tb@boll.ch>, Mark Simpson <damned@world.std.com> - * - * Copyright 2002-2010 The Horde Project (http://www.horde.org/) - * - * See the enclosed file COPYING for license information (LGPL). If you - * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. - * - * @author Jan Schneider <jan@horde.org> - * @author Michael Slusarz <slusarz@horde.org> - * @package Horde_Compress - */ -class tnef_decoder -{ - const SIGNATURE = 0x223e9f78; - const LVL_MESSAGE = 0x01; - const LVL_ATTACHMENT = 0x02; - - const ASUBJECT = 0x88004; - const AMCLASS = 0x78008; - const ATTACHDATA = 0x6800f; - const AFILENAME = 0x18010; - const ARENDDATA = 0x69002; - const AMAPIATTRS = 0x69005; - const AVERSION = 0x89006; - - const MAPI_NULL = 0x0001; - const MAPI_SHORT = 0x0002; - const MAPI_INT = 0x0003; - const MAPI_FLOAT = 0x0004; - const MAPI_DOUBLE = 0x0005; - const MAPI_CURRENCY = 0x0006; - const MAPI_APPTIME = 0x0007; - const MAPI_ERROR = 0x000a; - const MAPI_BOOLEAN = 0x000b; - const MAPI_OBJECT = 0x000d; - const MAPI_INT8BYTE = 0x0014; - const MAPI_STRING = 0x001e; - const MAPI_UNICODE_STRING = 0x001f; - const MAPI_SYSTIME = 0x0040; - const MAPI_CLSID = 0x0048; - const MAPI_BINARY = 0x0102; - - const MAPI_ATTACH_LONG_FILENAME = 0x3707; - const MAPI_ATTACH_MIME_TAG = 0x370E; - - const MAPI_NAMED_TYPE_ID = 0x0000; - const MAPI_NAMED_TYPE_STRING = 0x0001; - const MAPI_MV_FLAG = 0x1000; - - /** - * Decompress the data. - * - * @param string $data The data to decompress. - * @param array $params An array of arguments needed to decompress the - * data. - * - * @return mixed The decompressed data. - */ - public function decompress($data, $params = array()) - { - $out = array(); - - if ($this->_geti($data, 32) == self::SIGNATURE) { - $this->_geti($data, 16); - - while (strlen($data) > 0) { - switch ($this->_geti($data, 8)) { - case self::LVL_MESSAGE: - $this->_decodeMessage($data); - break; - - case self::LVL_ATTACHMENT: - $this->_decodeAttachment($data, $out); - break; - } - } - } - - return array_reverse($out); - } - - /** - * TODO - * - * @param string &$data The data string. - * @param integer $bits How many bits to retrieve. - * - * @return TODO - */ - protected function _getx(&$data, $bits) - { - $value = null; - - if (strlen($data) >= $bits) { - $value = substr($data, 0, $bits); - $data = substr_replace($data, '', 0, $bits); - } - - return $value; - } - - /** - * TODO - * - * @param string &$data The data string. - * @param integer $bits How many bits to retrieve. - * - * @return TODO - */ - protected function _geti(&$data, $bits) - { - $bytes = $bits / 8; - $value = null; - - if (strlen($data) >= $bytes) { - $value = ord($data[0]); - if ($bytes >= 2) { - $value += (ord($data[1]) << 8); - } - if ($bytes >= 4) { - $value += (ord($data[2]) << 16) + (ord($data[3]) << 24); - } - $data = substr_replace($data, '', 0, $bytes); - } - - return $value; - } - - /** - * TODO - * - * @param string &$data The data string. - * @param string $attribute TODO - */ - protected function _decodeAttribute(&$data, $attribute) - { - /* Data. */ - $this->_getx($data, $this->_geti($data, 32)); - - /* Checksum. */ - $this->_geti($data, 16); - } - - /** - * TODO - * - * @param string $data The data string. - * @param array &$attachment_data TODO - */ - protected function _extractMapiAttributes($data, &$attachment_data) - { - /* Number of attributes. */ - $number = $this->_geti($data, 32); - - while ((strlen($data) > 0) && $number--) { - $have_mval = false; - $num_mval = 1; - $named_id = $value = null; - $attr_type = $this->_geti($data, 16); - $attr_name = $this->_geti($data, 16); - - if (($attr_type & self::MAPI_MV_FLAG) != 0) { - $have_mval = true; - $attr_type = $attr_type & ~self::MAPI_MV_FLAG; - } - - if (($attr_name >= 0x8000) && ($attr_name < 0xFFFE)) { - $this->_getx($data, 16); - $named_type = $this->_geti($data, 32); - - switch ($named_type) { - case self::MAPI_NAMED_TYPE_ID: - $named_id = $this->_geti($data, 32); - $attr_name = $named_id; - break; - - case self::MAPI_NAMED_TYPE_STRING: - $attr_name = 0x9999; - $idlen = $this->_geti($data, 32); - $datalen = $idlen + ((4 - ($idlen % 4)) % 4); - $named_id = substr($this->_getx($data, $datalen), 0, $idlen); - break; - } - } - - if ($have_mval) { - $num_mval = $this->_geti($data, 32); - } - - switch ($attr_type) { - case self::MAPI_SHORT: - $value = $this->_geti($data, 16);
View file
kolab-syncroton.dsc
Changed
@@ -2,7 +2,7 @@ Source: kolab-syncroton Binary: kolab-syncroton Architecture: all -Version: 2.3~dev20141017-0~kolab2 +Version: 2.3.0-0~kolab1 Maintainer: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> Uploaders: Paul Klos <kolab@klos2day.nl> Homepage: http://www.kolab.org/ @@ -12,5 +12,5 @@ Package-List: kolab-syncroton deb utils extra Files: - 00000000000000000000000000000000 0 kolab-syncroton-2.3.tar.gz + 00000000000000000000000000000000 0 kolab-syncroton-2.3.0.tar.gz 00000000000000000000000000000000 0 debian.tar.gz
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.