diff options
Diffstat (limited to 'program/include')
-rw-r--r-- | program/include/rcmail.php | 88 | ||||
-rw-r--r-- | program/include/rcube.php | 20 | ||||
-rw-r--r-- | program/include/rcube_addressbook.php | 2 | ||||
-rw-r--r-- | program/include/rcube_browser.php | 4 | ||||
-rw-r--r-- | program/include/rcube_cache.php | 12 | ||||
-rw-r--r-- | program/include/rcube_config.php | 22 | ||||
-rw-r--r-- | program/include/rcube_imap.php | 19 | ||||
-rw-r--r-- | program/include/rcube_imap_cache.php | 123 | ||||
-rw-r--r-- | program/include/rcube_imap_generic.php | 69 | ||||
-rw-r--r-- | program/include/rcube_ldap.php | 4 | ||||
-rw-r--r-- | program/include/rcube_message.php | 26 | ||||
-rw-r--r-- | program/include/rcube_output_html.php | 25 | ||||
-rw-r--r-- | program/include/rcube_output_json.php | 12 | ||||
-rw-r--r-- | program/include/rcube_plugin.php | 9 | ||||
-rw-r--r-- | program/include/rcube_session.php | 14 | ||||
-rw-r--r-- | program/include/rcube_spellchecker.php | 22 | ||||
-rw-r--r-- | program/include/rcube_user.php | 34 | ||||
-rw-r--r-- | program/include/rcube_utils.php | 10 |
18 files changed, 333 insertions, 182 deletions
diff --git a/program/include/rcmail.php b/program/include/rcmail.php index 8ec8cfe47..a6b0bcd57 100644 --- a/program/include/rcmail.php +++ b/program/include/rcmail.php @@ -58,6 +58,12 @@ class rcmail extends rcube const JS_OBJECT_NAME = 'rcmail'; + const ERROR_STORAGE = -2; + const ERROR_INVALID_REQUEST = 1; + const ERROR_INVALID_HOST = 2; + const ERROR_COOKIES_DISABLED = 3; + + /** * This implements the 'singleton' design pattern * @@ -165,7 +171,7 @@ class rcmail extends rcube /** * Return instance of the internal address book class * - * @param string Address book identifier + * @param string Address book identifier (-1 for default addressbook) * @param boolean True if the address book needs to be writeable * * @return rcube_contacts Address book object @@ -174,17 +180,17 @@ class rcmail extends rcube { $contacts = null; $ldap_config = (array)$this->config->get('ldap_public'); - $abook_type = strtolower($this->config->get('address_book_type')); // 'sql' is the alias for '0' used by autocomplete if ($id == 'sql') - $id = '0'; + $id = '0'; + else if ($id == -1) { + $id = $this->config->get('default_addressbook'); + $default = true; + } // use existing instance - if (isset($this->address_books[$id]) && is_object($this->address_books[$id]) - && is_a($this->address_books[$id], 'rcube_addressbook') - && (!$writeable || !$this->address_books[$id]->readonly) - ) { + if (isset($this->address_books[$id]) && ($this->address_books[$id] instanceof rcube_addressbook)) { $contacts = $this->address_books[$id]; } else if ($id && $ldap_config[$id]) { @@ -200,14 +206,16 @@ class rcmail extends rcube if ($plugin['instance'] instanceof rcube_addressbook) { $contacts = $plugin['instance']; } - // get first source from the list - else if (!$id) { - $source = reset($this->get_address_sources($writeable)); - if (!empty($source)) { - $contacts = $this->get_address_book($source['id']); - if ($contacts) - $id = $source['id']; - } + } + + // Get first addressbook from the list if configured default doesn't exist + // This can happen when user deleted the addressbook (e.g. Kolab folder) + if (!$contacts && (!$id || $default)) { + $source = reset($this->get_address_sources($writeable)); + if (!empty($source)) { + $contacts = $this->get_address_book($source['id']); + if ($contacts) + $id = $source['id']; } } @@ -219,6 +227,10 @@ class rcmail extends rcube true, true); } + if ($writeable && $contacts->readonly) { + return null; + } + // set configured sort order if ($sort_col = $this->config->get('addressbook_sort_col')) $contacts->set_sort_order($sort_col); @@ -366,15 +378,23 @@ class rcmail extends rcube * @param string Mail storage (IMAP) user name * @param string Mail storage (IMAP) password * @param string Mail storage (IMAP) host + * @param bool Enables cookie check * * @return boolean True on success, False on failure */ - function login($username, $pass, $host=NULL) + function login($username, $pass, $host = null, $cookiecheck = false) { + $this->login_error = null; + if (empty($username)) { return false; } + if ($cookiecheck && empty($_COOKIE)) { + $this->login_error = self::ERROR_COOKIES_DISABLED; + return false; + } + $config = $this->config->all(); if (!$host) @@ -391,11 +411,18 @@ class rcmail extends rcube break; } } - if (!$allowed) - return false; + if (!$allowed) { + $host = null; } - else if (!empty($config['default_host']) && $host != rcube_utils::parse_host($config['default_host'])) + } + else if (!empty($config['default_host']) && $host != rcube_utils::parse_host($config['default_host'])) { + $host = null; + } + + if (!$host) { + $this->login_error = self::ERROR_INVALID_HOST; return false; + } // parse $host URL $a_host = parse_url($host); @@ -534,6 +561,23 @@ class rcmail extends rcube } + /** + * Returns error code of last login operation + * + * @return int Error code + */ + public function login_error() + { + if ($this->login_error) { + return $this->login_error; + } + + if ($this->storage && $this->storage->get_error_code() < -1) { + return self::ERROR_STORAGE; + } + } + + /** * Auto-select IMAP host based on the posted login information * @@ -682,8 +726,12 @@ class rcmail extends rcube */ public function url($p) { - if (!is_array($p)) + if (!is_array($p)) { + if (strpos($p, 'http') === 0) + return $p; + $p = array('_action' => @func_get_arg(0)); + } $task = $p['_task'] ? $p['_task'] : ($p['task'] ? $p['task'] : $this->task); $p['_task'] = $task; diff --git a/program/include/rcube.php b/program/include/rcube.php index 3e43ace96..494b5c3dd 100644 --- a/program/include/rcube.php +++ b/program/include/rcube.php @@ -106,12 +106,14 @@ class rcube /** * This implements the 'singleton' design pattern * + * @param integer Options to initialize with this instance. See rcube::INIT_WITH_* constants * @return rcube The one and only instance */ - static function get_instance() + static function get_instance($mode = 0) { if (!self::$instance) { self::$instance = new rcube(); + self::$instance->init($mode); } return self::$instance; @@ -189,11 +191,17 @@ class rcube $this->memcache = new Memcache; $this->mc_available = 0; - // add alll configured hosts to pool + // add all configured hosts to pool $pconnect = $this->config->get('memcache_pconnect', true); foreach ($this->config->get('memcache_hosts', array()) as $host) { - list($host, $port) = explode(':', $host); - if (!$port) $port = 11211; + if (substr($host, 0, 7) != 'unix://') { + list($host, $port) = explode(':', $host); + if (!$port) $port = 11211; + } + else { + $port = 0; + } + $this->mc_available += intval($this->memcache->addServer($host, $port, $pconnect, 1, 1, 15, false, array($this, 'memcache_failure'))); } @@ -238,8 +246,7 @@ class rcube */ public function get_cache($name, $type='db', $ttl=0, $packed=true) { - if (!isset($this->caches[$name])) { - $userid = $this->get_user_id(); + if (!isset($this->caches[$name]) && ($userid = $this->get_user_id())) { $this->caches[$name] = new rcube_cache($type, $userid, $name, $ttl, $packed); } @@ -406,6 +413,7 @@ class rcube ini_set('session.use_cookies', 1); ini_set('session.use_only_cookies', 1); ini_set('session.serialize_handler', 'php'); + ini_set('session.cookie_httponly', 1); // use database for storing session data $this->session = new rcube_session($this->get_dbh(), $this->config); diff --git a/program/include/rcube_addressbook.php b/program/include/rcube_addressbook.php index f5b32cd52..069ea5715 100644 --- a/program/include/rcube_addressbook.php +++ b/program/include/rcube_addressbook.php @@ -422,7 +422,7 @@ abstract class rcube_addressbook function get_col_values($col, $data, $flat = false) { $out = array(); - foreach ($data as $c => $values) { + foreach ((array)$data as $c => $values) { if ($c === $col || strpos($c, $col.':') === 0) { if ($flat) { $out = array_merge($out, (array)$values); diff --git a/program/include/rcube_browser.php b/program/include/rcube_browser.php index 609ddb842..06033e036 100644 --- a/program/include/rcube_browser.php +++ b/program/include/rcube_browser.php @@ -42,9 +42,9 @@ class rcube_browser $this->ns4 = strpos($HTTP_USER_AGENT, 'mozilla/4') !== false && strpos($HTTP_USER_AGENT, 'msie') === false; $this->ns = ($this->ns4 || strpos($HTTP_USER_AGENT, 'netscape') !== false); $this->ie = !$this->opera && strpos($HTTP_USER_AGENT, 'compatible; msie') !== false; - $this->mz = !$this->ie && strpos($HTTP_USER_AGENT, 'mozilla/5') !== false; - $this->chrome = strpos($HTTP_USER_AGENT, 'chrome') !== false; $this->khtml = strpos($HTTP_USER_AGENT, 'khtml') !== false; + $this->mz = !$this->ie && !$this->khtml && strpos($HTTP_USER_AGENT, 'mozilla/5') !== false; + $this->chrome = strpos($HTTP_USER_AGENT, 'chrome') !== false; $this->safari = !$this->chrome && ($this->khtml || strpos($HTTP_USER_AGENT, 'safari') !== false); if ($this->ns || $this->chrome) { diff --git a/program/include/rcube_cache.php b/program/include/rcube_cache.php index 73c5eacea..17a8859d8 100644 --- a/program/include/rcube_cache.php +++ b/program/include/rcube_cache.php @@ -45,7 +45,6 @@ class rcube_cache private $packed; private $index; private $cache = array(); - private $cache_keys = array(); private $cache_changes = array(); private $cache_sums = array(); @@ -167,7 +166,7 @@ class rcube_cache $this->cache = array(); $this->cache_changed = false; $this->cache_changes = array(); - $this->cache_keys = array(); + $this->cache_sums = array(); } // Remove keys by name prefix else if ($prefix_mode) { @@ -175,7 +174,7 @@ class rcube_cache if (strpos($k, $key) === 0) { $this->cache[$k] = null; $this->cache_changes[$k] = false; - unset($this->cache_keys[$k]); + unset($this->cache_sums[$k]); } } } @@ -183,7 +182,7 @@ class rcube_cache else { $this->cache[$key] = null; $this->cache_changes[$key] = false; - unset($this->cache_keys[$key]); + unset($this->cache_sums[$key]); } // Remove record(s) from the backend @@ -274,7 +273,7 @@ class rcube_cache } else { $sql_result = $this->db->limitquery( - "SELECT cache_id, data, cache_key". + "SELECT data, cache_key". " FROM ".$this->db->table_name('cache'). " WHERE user_id = ?". " AND cache_key = ?". @@ -296,7 +295,6 @@ class rcube_cache $this->cache[$key] = $data; $this->cache_sums[$key] = $md5sum; - $this->cache_keys[$key] = $sql_arr['cache_id']; } else { $this->cache[$key] = null; @@ -325,7 +323,7 @@ class rcube_cache return $this->add_record($this->ckey($key), $data); } - $key_exists = $this->cache_keys[$key]; + $key_exists = array_key_exists($key, $this->cache_sums); $key = $this->prefix . '.' . $key; // Remove NULL rows (here we don't need to check if the record exist) diff --git a/program/include/rcube_config.php b/program/include/rcube_config.php index 1b621e0fc..aae3656a1 100644 --- a/program/include/rcube_config.php +++ b/program/include/rcube_config.php @@ -49,6 +49,11 @@ class rcube_config public function __construct() { $this->load(); + + // Defaults, that we do not require you to configure, + // but contain information that is used in various + // locations in the code: + $this->set('contactlist_fields', array('name', 'firstname', 'surname', 'email')); } @@ -76,10 +81,14 @@ class rcube_config $this->prop['skin'] = str_replace('skins/', '', unslashify($this->prop['skin_path'])); } else { - $this->prop['skin'] = 'default'; + $this->prop['skin'] = 'larry'; } } + // larry is the new default skin :-) + if ($this->prop['skin'] == 'default') + $this->prop['skin'] = 'larry'; + // fix paths $this->prop['log_dir'] = $this->prop['log_dir'] ? realpath(unslashify($this->prop['log_dir'])) : INSTALL_PATH . 'logs'; $this->prop['temp_dir'] = $this->prop['temp_dir'] ? realpath(unslashify($this->prop['temp_dir'])) : INSTALL_PATH . 'temp'; @@ -233,10 +242,8 @@ class rcube_config // Honor the dont_override setting for any existing user preferences $dont_override = $this->get('dont_override'); if (is_array($dont_override) && !empty($dont_override)) { - foreach ($prefs as $key => $pref) { - if (in_array($key, $dont_override)) { - unset($prefs[$key]); - } + foreach ($dont_override as $key) { + unset($prefs[$key]); } } @@ -245,6 +252,11 @@ class rcube_config $prefs['timezone'] = timezone_name_from_abbr('', $prefs['timezone'] * 3600, 0); } + // larry is the new default skin :-) + if ($prefs['skin'] == 'default') { + $prefs['skin'] = 'larry'; + } + $this->userprefs = $prefs; $this->prop = array_merge($this->prop, $prefs); diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php index 00a4158fe..94200b7da 100644 --- a/program/include/rcube_imap.php +++ b/program/include/rcube_imap.php @@ -3229,8 +3229,9 @@ class rcube_imap extends rcube_storage $cache_key = 'mailboxes.folder-info.' . $folder; $cached = $this->get_cache($cache_key); - if (is_array($cached)) + if (is_array($cached)) { return $cached; + } $acl = $this->get_capability('ACL'); $namespace = $this->get_namespace(); @@ -3267,10 +3268,9 @@ class rcube_imap extends rcube_storage $options['name'] = $folder; $options['attributes'] = $this->folder_attributes($folder, true); $options['namespace'] = $this->folder_namespace($folder); - $options['rights'] = $acl && !$options['is_root'] ? (array)$this->my_rights($folder) : array(); $options['special'] = in_array($folder, $this->default_folders); - // Set 'noselect' and 'norename' flags + // Set 'noselect' flag if (is_array($options['attributes'])) { foreach ($options['attributes'] as $attrib) { $attrib = strtolower($attrib); @@ -3283,6 +3283,15 @@ class rcube_imap extends rcube_storage $options['noselect'] = true; } + // Get folder rights (MYRIGHTS) + if ($acl && !$options['noselect']) { + // skip shared roots + if (!$options['is_root'] || $options['namespace'] == 'personal') { + $options['rights'] = (array)$this->my_rights($folder); + } + } + + // Set 'norename' flag if (!empty($options['rights'])) { $options['norename'] = !in_array('x', $options['rights']) && !in_array('d', $options['rights']); @@ -3742,9 +3751,9 @@ class rcube_imap extends rcube_storage { if ($this->messages_caching && !$this->mcache) { $rcube = rcube::get_instance(); - if ($dbh = $rcube->get_dbh()) { + if (($dbh = $rcube->get_dbh()) && ($userid = $rcube->get_user_id())) { $this->mcache = new rcube_imap_cache( - $dbh, $this, $rcube->get_user_id(), $this->options['skip_deleted']); + $dbh, $this, $userid, $this->options['skip_deleted']); } } diff --git a/program/include/rcube_imap_cache.php b/program/include/rcube_imap_cache.php index f6f53127d..a061a1f6e 100644 --- a/program/include/rcube_imap_cache.php +++ b/program/include/rcube_imap_cache.php @@ -516,7 +516,6 @@ class rcube_imap_cache .($uids !== null ? " AND uid IN (".$this->db->array2list((array)$uids, 'integer').")" : ""), $this->userid, $mailbox); } - } @@ -917,18 +916,17 @@ class rcube_imap_cache return; } - // NOTE: make sure the mailbox isn't selected, before - // enabling QRESYNC and invoking SELECT - if ($this->imap->conn->selected !== null) { - $this->imap->conn->close(); - } - // Enable QRESYNC $res = $this->imap->conn->enable($qresync ? 'QRESYNC' : 'CONDSTORE'); - if (!is_array($res)) { + if ($res === false) { return; } + // Close mailbox if already selected to get most recent data + if ($this->imap->conn->selected == $mailbox) { + $this->imap->conn->close(); + } + // Get mailbox data (UIDVALIDITY, HIGHESTMODSEQ, counters, etc.) $mbox_data = $this->imap->folder_data($mailbox); @@ -952,8 +950,10 @@ class rcube_imap_cache return; } - // Get known uids - $uids = array(); + $uids = array(); + $removed = array(); + + // Get known UIDs $sql_result = $this->db->query( "SELECT uid" ." FROM ".$this->db->table_name('cache_messages') @@ -962,74 +962,69 @@ class rcube_imap_cache $this->userid, $mailbox); while ($sql_arr = $this->db->fetch_assoc($sql_result)) { - $uids[] = $sql_arr['uid']; - } - - // No messages in database, nothing to sync - if (empty($uids)) { - return; - } - - // Get modified flags and vanished messages - // UID FETCH 1:* (FLAGS) (CHANGEDSINCE 0123456789 VANISHED) - $result = $this->imap->conn->fetch($mailbox, - !empty($uids) ? $uids : '1:*', true, array('FLAGS'), - $index['modseq'], $qresync); - - $invalidated = false; - - if (!empty($result)) { - foreach ($result as $id => $msg) { - $uid = $msg->uid; - // Remove deleted message - if ($this->skip_deleted && !empty($msg->flags['DELETED'])) { - $this->remove_message($mailbox, $uid); - - if (!$invalidated) { - $invalidated = true; - // Invalidate thread indexes (?) - $this->remove_thread($mailbox); + $uids[] = $sql_arr['uid']; + } + + // Synchronize messages data + if (!empty($uids)) { + // Get modified flags and vanished messages + // UID FETCH 1:* (FLAGS) (CHANGEDSINCE 0123456789 VANISHED) + $result = $this->imap->conn->fetch($mailbox, + $uids, true, array('FLAGS'), $index['modseq'], $qresync); + + if (!empty($result)) { + foreach ($result as $id => $msg) { + $uid = $msg->uid; + // Remove deleted message + if ($this->skip_deleted && !empty($msg->flags['DELETED'])) { + $removed[] = $uid; // Invalidate index $index['valid'] = false; + continue; } - continue; - } - $flags = 0; - if (!empty($msg->flags)) { - foreach ($this->flags as $idx => $flag) - if (!empty($msg->flags[$flag])) - $flags += $idx; - } + $flags = 0; + if (!empty($msg->flags)) { + foreach ($this->flags as $idx => $flag) { + if (!empty($msg->flags[$flag])) { + $flags += $idx; + } + } + } - $this->db->query( - "UPDATE ".$this->db->table_name('cache_messages') - ." SET flags = ?, changed = ".$this->db->now() - ." WHERE user_id = ?" - ." AND mailbox = ?" - ." AND uid = ?" - ." AND flags <> ?", - $flags, $this->userid, $mailbox, $uid, $flags); + $this->db->query( + "UPDATE ".$this->db->table_name('cache_messages') + ." SET flags = ?, changed = ".$this->db->now() + ." WHERE user_id = ?" + ." AND mailbox = ?" + ." AND uid = ?" + ." AND flags <> ?", + $flags, $this->userid, $mailbox, $uid, $flags); + } } - } - // Get VANISHED - if ($qresync) { - $mbox_data = $this->imap->folder_data($mailbox); + // VANISHED found? + if ($qresync) { + $mbox_data = $this->imap->folder_data($mailbox); - // Removed messages - if (!empty($mbox_data['VANISHED'])) { + // Removed messages found $uids = rcube_imap_generic::uncompressMessageSet($mbox_data['VANISHED']); if (!empty($uids)) { - // remove messages from database - $this->remove_message($mailbox, $uids); - - // Invalidate thread indexes (?) - $this->remove_thread($mailbox); + $removed = array_merge($removed, $uids); // Invalidate index $index['valid'] = false; } } + + // remove messages from database + if (!empty($removed)) { + $this->remove_message($mailbox, $removed); + } + } + + // Invalidate thread index (?) + if (!$index['valid']) { + $this->remove_thread($mailbox); } $sort_field = $index['sort_field']; diff --git a/program/include/rcube_imap_generic.php b/program/include/rcube_imap_generic.php index 959dd9fd0..8d956f2b9 100644 --- a/program/include/rcube_imap_generic.php +++ b/program/include/rcube_imap_generic.php @@ -313,9 +313,13 @@ class rcube_imap_generic else { $this->resultcode = null; // parse response for [APPENDUID 1204196876 3456] - if (preg_match("/^\[APPENDUID [0-9]+ ([0-9,:*]+)\]/i", $str, $m)) { + if (preg_match("/^\[APPENDUID [0-9]+ ([0-9]+)\]/i", $str, $m)) { $this->data['APPENDUID'] = $m[1]; } + // parse response for [COPYUID 1204196876 3456:3457 123:124] + else if (preg_match("/^\[COPYUID [0-9]+ ([0-9,:]+) ([0-9,:]+)\]/i", $str, $m)) { + $this->data['COPYUID'] = array($m[1], $m[2]); + } } $this->result = $str; @@ -1472,14 +1476,31 @@ class rcube_imap_generic */ function enable($extension) { - if (empty($extension)) + if (empty($extension)) { return false; + } - if (!$this->hasCapability('ENABLE')) + if (!$this->hasCapability('ENABLE')) { return false; + } - if (!is_array($extension)) + if (!is_array($extension)) { $extension = array($extension); + } + + if (!empty($this->extensions_enabled)) { + // check if all extensions are already enabled + $diff = array_diff($extension, $this->extensions_enabled); + + if (empty($diff)) { + return $extension; + } + + // Make sure the mailbox isn't selected, before enabling extension(s) + if ($this->selected !== null) { + $this->close(); + } + } list($code, $response) = $this->execute('ENABLE', $extension); @@ -1487,7 +1508,9 @@ class rcube_imap_generic $response = substr($response, 10); // remove prefix "* ENABLED " $result = (array) $this->tokenizeResponse($response); - return $result; + $this->extensions_enabled = array_unique(array_merge((array)$this->extensions_enabled, $result)); + + return $this->extensions_enabled; } return false; @@ -1931,6 +1954,9 @@ class rcube_imap_generic */ function copy($messages, $from, $to) { + // Clear last COPYUID data + unset($this->data['COPYUID']); + if (!$this->select($from)) { return false; } @@ -3176,10 +3202,10 @@ class rcube_imap_generic */ static function getStructurePartData($structure, $part) { - $part_a = self::getStructurePartArray($structure, $part); - $data = array(); + $part_a = self::getStructurePartArray($structure, $part); + $data = array(); - if (empty($part_a)) { + if (empty($part_a)) { return $data; } @@ -3212,13 +3238,13 @@ class rcube_imap_generic static function getStructurePartArray($a, $part) { - if (!is_array($a)) { + if (!is_array($a)) { return false; } if (empty($part)) { - return $a; - } + return $a; + } $ctype = is_string($a[0]) && is_string($a[1]) ? $a[0] . '/' . $a[1] : ''; @@ -3226,20 +3252,17 @@ class rcube_imap_generic $a = $a[8]; } - if (strpos($part, '.') > 0) { - $orig_part = $part; - $pos = strpos($part, '.'); - $rest = substr($orig_part, $pos+1); - $part = substr($orig_part, 0, $pos); + if (strpos($part, '.') > 0) { + $orig_part = $part; + $pos = strpos($part, '.'); + $rest = substr($orig_part, $pos+1); + $part = substr($orig_part, 0, $pos); - return self::getStructurePartArray($a[$part-1], $rest); - } + return self::getStructurePartArray($a[$part-1], $rest); + } else if ($part > 0) { - if (is_array($a[$part-1])) - return $a[$part-1]; - else - return $a; - } + return (is_array($a[$part-1])) ? $a[$part-1] : $a; + } } /** diff --git a/program/include/rcube_ldap.php b/program/include/rcube_ldap.php index 8f23a406b..3a7fc1805 100644 --- a/program/include/rcube_ldap.php +++ b/program/include/rcube_ldap.php @@ -767,7 +767,9 @@ class rcube_ldap extends rcube_addressbook } // use VLV pseudo-search for autocompletion - if ($this->prop['vlv_search'] && $this->conn && join(',', (array)$fields) == 'email,name') + $rcmail = rcmail::get_instance(); + + if ($this->prop['vlv_search'] && $this->conn && join(',', (array)$fields) == join(',', $rcmail->config->get('contactlist_fields'))) { // add general filter to query if (!empty($this->prop['filter']) && empty($this->filter)) diff --git a/program/include/rcube_message.php b/program/include/rcube_message.php index a140b86c6..9d36acf38 100644 --- a/program/include/rcube_message.php +++ b/program/include/rcube_message.php @@ -277,6 +277,32 @@ class rcube_message /** + * Checks if part of the message is an attachment (or part of it) + * + * @param rcube_message_part $part Message part + * + * @return bool True if the part is an attachment part + */ + public function is_attachment($part) + { + foreach ($this->attachments as $att_part) { + if ($att_part->mime_id == $part->mime_id) { + return true; + } + + // check if the part is a subpart of another attachment part (message/rfc822) + if ($att_part->mimetype == 'message/rfc822') { + if (in_array($part, (array)$att_part->parts)) { + return true; + } + } + } + + return false; + } + + + /** * Read the message structure returend by the IMAP server * and build flat lists of content parts and attachments * diff --git a/program/include/rcube_output_html.php b/program/include/rcube_output_html.php index 7ceea1839..3bc93db53 100644 --- a/program/include/rcube_output_html.php +++ b/program/include/rcube_output_html.php @@ -696,10 +696,31 @@ class rcube_output_html extends rcube_output // show a label case 'label': if ($attrib['name'] || $attrib['command']) { + // @FIXME: 'noshow' is useless, remove? + if ($attrib['noshow']) { + return ''; + } + $vars = $attrib + array('product' => $this->config->get('product_name')); unset($vars['name'], $vars['command']); - $label = $this->app->gettext($attrib + array('vars' => $vars)); - return !$attrib['noshow'] ? (get_boolean((string)$attrib['html']) ? $label : html::quote($label)) : ''; + + $label = $this->app->gettext($attrib + array('vars' => $vars)); + $quoting = !empty($attrib['quoting']) ? strtolower($attrib['quoting']) : (get_boolean((string)$attrib['html']) ? 'no' : ''); + + switch ($quoting) { + case 'no': + case 'raw': + break; + case 'javascript': + case 'js': + $label = rcmail::JQ($label); + break; + default: + $label = html::quote($label); + break; + } + + return $label; } break; diff --git a/program/include/rcube_output_json.php b/program/include/rcube_output_json.php index 7b5510dfe..eb1a9380d 100644 --- a/program/include/rcube_output_json.php +++ b/program/include/rcube_output_json.php @@ -37,18 +37,6 @@ class rcube_output_json extends rcube_output /** - * Set environment variable - * - * @param string $name Property name - * @param mixed $value Property value - */ - public function set_env($name, $value) - { - $this->env[$name] = $value; - } - - - /** * Issue command to set page title * * @param string $title New page title diff --git a/program/include/rcube_plugin.php b/program/include/rcube_plugin.php index b91355c98..b1ec32a8a 100644 --- a/program/include/rcube_plugin.php +++ b/program/include/rcube_plugin.php @@ -336,9 +336,12 @@ abstract class rcube_plugin public function local_skin_path() { $rcmail = rcube::get_instance(); - $skin_path = 'skins/' . $rcmail->config->get('skin'); - if (!is_dir(realpath(slashify($this->home) . $skin_path))) - $skin_path = 'skins/default'; + foreach (array($rcmail->config->get('skin'),'default') as $skin) { + $skin_path = 'skins/' . $skin; + if (is_dir(realpath(slashify($this->home) . $skin_path))) + break; + } + return $skin_path; } diff --git a/program/include/rcube_session.php b/program/include/rcube_session.php index 09a07d644..e3b5600ca 100644 --- a/program/include/rcube_session.php +++ b/program/include/rcube_session.php @@ -218,13 +218,14 @@ class rcube_session * Handler for session_destroy() * * @param string Session ID + * * @return boolean True on success */ public function db_destroy($key) { - $this->db->query( - sprintf("DELETE FROM %s WHERE sess_id = ?", $this->db->table_name('session')), - $key); + if ($key) { + $this->db->query(sprintf("DELETE FROM %s WHERE sess_id = ?", $this->db->table_name('session')), $key); + } return true; } @@ -305,11 +306,16 @@ class rcube_session * Handler for session_destroy() with memcache backend * * @param string Session ID + * * @return boolean True on success */ public function mc_destroy($key) { - return $this->memcache->delete($key); + if ($key) { + $this->memcache->delete($key); + } + + return true; } diff --git a/program/include/rcube_spellchecker.php b/program/include/rcube_spellchecker.php index f38720bc8..a2d1f7c61 100644 --- a/program/include/rcube_spellchecker.php +++ b/program/include/rcube_spellchecker.php @@ -57,13 +57,6 @@ class rcube_spellchecker $this->engine = $this->rc->config->get('spellcheck_engine', 'googie'); $this->lang = $lang ? $lang : 'en'; - if ($this->engine == 'pspell' && !extension_loaded('pspell')) { - rcube::raise_error(array( - 'code' => 500, 'type' => 'php', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Pspell extension not available"), true, true); - } - $this->options = array( 'ignore_syms' => $this->rc->config->get('spellcheck_ignore_syms'), 'ignore_nums' => $this->rc->config->get('spellcheck_ignore_nums'), @@ -235,8 +228,9 @@ class rcube_spellchecker else if (!pspell_check($this->plink, $word)) { $suggestions = pspell_suggest($this->plink, $word); - if (sizeof($suggestions) > self::MAX_SUGGESTIONS) - $suggestions = array_slice($suggestions, 0, self::MAX_SUGGESTIONS); + if (sizeof($suggestions) > self::MAX_SUGGESTIONS) { + $suggestions = array_slice($suggestions, 0, self::MAX_SUGGESTIONS); + } $matches[] = array($word, $pos, $len, null, $suggestions); } @@ -321,6 +315,16 @@ class rcube_spellchecker private function _pspell_init() { if (!$this->plink) { + if (!extension_loaded('pspell')) { + $this->error = "Pspell extension not available"; + rcube::raise_error(array( + 'code' => 500, 'type' => 'php', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => $this->error), true, false); + + return; + } + $this->plink = pspell_new($this->lang, null, null, RCMAIL_CHARSET, PSPELL_FAST); } diff --git a/program/include/rcube_user.php b/program/include/rcube_user.php index 1a54b91a2..644d24bd9 100644 --- a/program/include/rcube_user.php +++ b/program/include/rcube_user.php @@ -397,15 +397,22 @@ class rcube_user */ static function query($user, $host) { - $dbh = rcube::get_instance()->get_dbh(); + $dbh = rcube::get_instance()->get_dbh(); + $config = rcube::get_instance()->config; // query for matching user name - $query = "SELECT * FROM ".$dbh->table_name('users')." WHERE mail_host = ? AND %s = ?"; - $sql_result = $dbh->query(sprintf($query, 'username'), $host, $user); + $sql_result = $dbh->query("SELECT * FROM " . $dbh->table_name('users') + ." 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); - // query for matching alias - if (!($sql_arr = $dbh->fetch_assoc($sql_result))) { - $sql_result = $dbh->query(sprintf($query, 'alias'), $host, $user); $sql_arr = $dbh->fetch_assoc($sql_result); } @@ -449,11 +456,10 @@ class rcube_user $dbh->query( "INSERT INTO ".$dbh->table_name('users'). - " (created, last_login, username, mail_host, alias, language)". - " VALUES (".$dbh->now().", ".$dbh->now().", ?, ?, ?, ?)", + " (created, last_login, username, mail_host, language)". + " VALUES (".$dbh->now().", ".$dbh->now().", ?, ?, ?)", strip_newlines($user), strip_newlines($host), - strip_newlines($data['alias'] ? $data['alias'] : $user_email), strip_newlines($data['language'] ? $data['language'] : $_SESSION['language'])); if ($user_id = $dbh->insert_id('users')) { @@ -479,23 +485,23 @@ class rcube_user // create new identities records $standard = 1; foreach ($email_list as $row) { - $record = array(); + $record = array(); if (is_array($row)) { - $record = $row; + $record = $row; } else { $record['email'] = $row; } - if (empty($record['name'])) - $record['name'] = $user_name; + if (empty($record['name'])) + $record['name'] = $user_name; $record['name'] = strip_newlines($record['name']); $record['user_id'] = $user_id; $record['standard'] = $standard; $plugin = $rcube->plugins->exec_hook('identity_create', - array('login' => true, 'record' => $record)); + array('login' => true, 'record' => $record)); if (!$plugin['abort'] && $plugin['record']['email']) { $rcube->user->insert_identity($plugin['record']); diff --git a/program/include/rcube_utils.php b/program/include/rcube_utils.php index 7f20dbb1a..9344a929b 100644 --- a/program/include/rcube_utils.php +++ b/program/include/rcube_utils.php @@ -47,7 +47,7 @@ class rcube_utils } $cookie = session_get_cookie_params(); - $secure = self::https_check(); + $secure = $cookie['secure'] || self::https_check(); setcookie($name, $value, $exp, $cookie['path'], $cookie['domain'], $secure, true); } @@ -616,8 +616,10 @@ class rcube_utils { // %n - host $n = preg_replace('/:\d+$/', '', $_SERVER['SERVER_NAME']); - // %d - domain name without first part, e.g. %n=mail.domain.tld, %d=domain.tld - $d = preg_replace('/^[^\.]+\./', '', $n); + // %t - host name without first part, e.g. %n=mail.domain.tld, %t=domain.tld + $t = preg_replace('/^[^\.]+\./', '', $n); + // %d - domain name without first part + $d = preg_replace('/^[^\.]+\./', '', $_SERVER['HTTP_HOST']); // %h - IMAP host $h = $_SESSION['storage_host'] ? $_SESSION['storage_host'] : $host; // %z - IMAP domain without first part, e.g. %h=imap.domain.tld, %z=domain.tld @@ -632,7 +634,7 @@ class rcube_utils } } - $name = str_replace(array('%n', '%d', '%h', '%z', '%s'), array($n, $d, $h, $z, $s[2]), $name); + $name = str_replace(array('%n', '%t', '%d', '%h', '%z', '%s'), array($n, $t, $d, $h, $z, $s[2]), $name); return $name; } |