config/main.inc.php.dist | ●●●●● patch | view | raw | blame | history | |
program/include/rcube_imap.php | ●●●●● patch | view | raw | blame | history | |
program/include/rcube_ldap.php | ●●●●● patch | view | raw | blame | history | |
program/include/rcube_message.php | ●●●●● patch | view | raw | blame | history | |
program/include/rcube_session.php | ●●●●● patch | view | raw | blame | history | |
program/js/app.js | ●●●●● patch | view | raw | blame | history |
config/main.inc.php.dist
@@ -570,9 +570,11 @@ // if the groups base_dn is empty, the contact base_dn is used for the groups as well // -> in this case, assure that groups and contacts are separated due to the concernig filters! 'groups' => array( 'base_dn' => '', 'base_dn' => '', 'filter' => '(objectClass=groupOfNames)', 'object_classes' => array("top", "groupOfNames"), // name of the member attribute, e.g. uniqueMember 'member_attr' => 'member', ), ); */ program/include/rcube_imap.php
@@ -1505,7 +1505,10 @@ // use message index sort as default sorting if (!$this->sort_field) { if ($this->skip_deleted) { $a_index = $this->_search_index($mailbox, 'ALL'); $a_index = $this->conn->search($mailbox, 'ALL UNDELETED'); // I didn't found that SEARCH should return sorted IDs if (is_array($a_index)) sort($a_index); } else if ($max = $this->_messagecount($mailbox)) { $a_index = range(1, $max); } @@ -2491,17 +2494,17 @@ return true; } // Remove NULL characters (#1486189) $body = str_replace("\x00", '', $body); // convert charset (if text or message part) if ($body && !$skip_charset_conv && preg_match('/^(text|message)$/', $o_part->ctype_primary) ) { if (!$o_part->charset || strtoupper($o_part->charset) == 'US-ASCII') { $o_part->charset = $this->default_charset; if ($body && preg_match('/^(text|message)$/', $o_part->ctype_primary)) { // Remove NULL characters (#1486189) $body = str_replace("\x00", '', $body); if (!$skip_charset_conv) { if (!$o_part->charset || strtoupper($o_part->charset) == 'US-ASCII') { $o_part->charset = $this->default_charset; } $body = rcube_charset_convert($body, $o_part->charset); } $body = rcube_charset_convert($body, $o_part->charset); } return $body; program/include/rcube_ldap.php
@@ -73,8 +73,14 @@ $this->prop = $p; // check if groups are configured if (is_array($p['groups']) and count($p['groups'])) if (is_array($p['groups']) && count($p['groups'])) { $this->groups = true; // set member field if (!empty($p['groups']['member_attr'])) $this->prop['member_attr'] = strtolower($p['groups']['member_attr']); else if (empty($p['member_attr'])) $this->prop['member_attr'] = 'member'; } // fieldmap property is given if (is_array($p['fieldmap'])) { @@ -115,8 +121,8 @@ foreach ($this->prop['required_fields'] as $key => $val) $this->prop['required_fields'][$key] = $this->_attr_name(strtolower($val)); $this->sort_col = is_array($p['sort']) ? $p['sort'][0] : $p['sort']; $this->debug = $debug; $this->sort_col = is_array($p['sort']) ? $p['sort'][0] : $p['sort']; $this->debug = $debug; $this->mail_domain = $mail_domain; $this->_connect(); @@ -173,7 +179,10 @@ $bind_pass = $this->prop['bind_pass']; $bind_user = $this->prop['bind_user']; $bind_dn = $this->prop['bind_dn']; $this->base_dn = $this->prop['base_dn']; $this->base_dn = $this->prop['base_dn']; $this->groups_base_dn = ($this->prop['groups']['base_dn']) ? $this->prop['groups']['base_dn'] : $this->base_dn; // User specific access, generate the proper values to use. if ($this->prop['user_specific']) { @@ -199,7 +208,7 @@ $this->_debug("S: searching with base {$this->prop['search_base_dn']} for {$this->prop['search_filter']}"); $res = ldap_search($this->conn, $this->prop['search_base_dn'], $this->prop['search_filter'], array('uid')); $res = @ldap_search($this->conn, $this->prop['search_base_dn'], $this->prop['search_filter'], array('uid')); if ($res && ($entry = ldap_first_entry($this->conn, $res))) { $bind_dn = ldap_get_dn($this->conn, $entry); @@ -212,8 +221,9 @@ } } // Replace the bind_dn and base_dn variables. $bind_dn = strtr($bind_dn, $replaces); $this->base_dn = strtr($this->base_dn, $replaces); $bind_dn = strtr($bind_dn, $replaces); $this->base_dn = strtr($this->base_dn, $replaces); $this->groups_base_dn = strtr($this->groups_base_dn, $replaces); if (empty($bind_user)) { $bind_user = $u; @@ -1091,35 +1101,18 @@ */ function list_groups($search = null) { global $RCMAIL; if (!$this->groups) return array(); $this->groups_base_dn = ($this->prop['groups']['base_dn']) ? $this->prop['groups']['base_dn'] : $this->base_dn; // replace user specific dn if ($this->prop['user_specific']) { $fu = $RCMAIL->user->get_username(); list($u, $d) = explode('@', $fu); $dc = 'dc='.strtr($d, array('.' => ',dc=')); $replaces = array('%dc' => $dc, '%d' => $d, '%fu' => $fu, '%u' => $u); $this->groups_base_dn = strtr($this->groups_base_dn, $replaces); } $base_dn = $this->groups_base_dn; $filter = $this->prop['groups']['filter']; $this->_debug("C: Search [$filter][dn: $base_dn]"); $res = ldap_search($this->conn, $base_dn, $filter, array('cn','member')); $res = @ldap_search($this->conn, $base_dn, $filter, array('cn', $this->prop['member_attr'])); if ($res === false) { $this->_debug("S: ".ldap_error($this->conn)); $this->set_error(self::ERROR_SAVING, 'errorsaving'); return array(); } @@ -1136,7 +1129,7 @@ $group_id = self::dn_encode($group_name); $groups[$group_id]['ID'] = $group_id; $groups[$group_id]['name'] = $group_name; $groups[$group_id]['members'] = $ldap_data[$i]['member']; $groups[$group_id]['members'] = $ldap_data[$i][$this->prop['member_attr']]; $group_sortnames[] = strtolower($group_name); } } @@ -1164,7 +1157,7 @@ $new_entry = array( 'objectClass' => $this->prop['groups']['object_classes'], 'cn' => $group_name, 'member' => '', $this->prop['member_attr'] => '', ); $this->_debug("C: Add [dn: $new_dn]: ".print_r($new_entry, true)); @@ -1258,13 +1251,14 @@ if (!$this->group_cache) $this->list_groups(); $base_dn = $this->groups_base_dn; $group_name = $this->group_cache[$group_id]['name']; $group_dn = "cn=$group_name,$base_dn"; $base_dn = $this->groups_base_dn; $group_name = $this->group_cache[$group_id]['name']; $member_attr = $this->prop['member_attr']; $group_dn = "cn=$group_name,$base_dn"; $new_attrs = array(); foreach (explode(",", $contact_ids) as $id) $new_attrs['member'][] = self::dn_decode($id); $new_attrs[$member_attr][] = self::dn_decode($id); $this->_debug("C: Add [dn: $group_dn]: ".print_r($new_attrs, true)); @@ -1293,13 +1287,14 @@ if (!$this->group_cache) $this->list_groups(); $base_dn = $this->groups_base_dn; $group_name = $this->group_cache[$group_id]['name']; $group_dn = "cn=$group_name,$base_dn"; $base_dn = $this->groups_base_dn; $group_name = $this->group_cache[$group_id]['name']; $member_attr = $this->prop['member_attr']; $group_dn = "cn=$group_name,$base_dn"; $del_attrs = array(); foreach (explode(",", $contact_ids) as $id) $del_attrs['member'][] = self::dn_decode($id); $del_attrs[$member_attr][] = self::dn_decode($id); $this->_debug("C: Delete [dn: $group_dn]: ".print_r($del_attrs, true)); @@ -1329,17 +1324,17 @@ if (!$this->groups) return array(); $base_dn = $this->groups_base_dn; $contact_dn = self::dn_decode($contact_id); $filter = strtr("(member=$contact_dn)", array('\\' => '\\\\')); $base_dn = $this->groups_base_dn; $contact_dn = self::dn_decode($contact_id); $member_attr = $this->prop['member_attr']; $filter = strtr("($member_attr=$contact_dn)", array('\\' => '\\\\')); $this->_debug("C: Search [$filter][dn: $base_dn]"); $res = ldap_search($this->conn, $base_dn, $filter, array('cn')); $res = @ldap_search($this->conn, $base_dn, $filter, array('cn')); if ($res === false) { $this->_debug("S: ".ldap_error($this->conn)); $this->set_error(self::ERROR_SAVING, 'errorsaving'); return array(); } $ldap_data = ldap_get_entries($this->conn, $res); program/include/rcube_message.php
@@ -373,6 +373,8 @@ $p->ctype_secondary = 'plain'; $p->body = rcube_label('encryptedmessage'); $p->size = strlen($p->body); $this->parts[] = $p; } // message contains multiple parts else if (is_array($structure->parts) && !empty($structure->parts)) { program/include/rcube_session.php
@@ -51,9 +51,9 @@ */ public function __construct($db, $config) { $this->db = $db; $this->start = microtime(true); $this->ip = $_SERVER['REMOTE_ADDR']; $this->db = $db; $this->start = microtime(true); $this->ip = $_SERVER['REMOTE_ADDR']; $this->logging = $config->get('log_session', false); $this->mc_debug = $config->get('memcache_debug', false); @@ -126,10 +126,10 @@ public function db_read($key) { $sql_result = $this->db->query( "SELECT vars, ip, changed FROM ".get_table_name('session')." WHERE sess_id = ?", $key); "SELECT vars, ip, changed FROM ".get_table_name('session') ." WHERE sess_id = ?", $key); if ($sql_arr = $this->db->fetch_assoc($sql_result)) { if ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) { $this->changed = strtotime($sql_arr['changed']); $this->ip = $sql_arr['ip']; $this->vars = base64_decode($sql_arr['vars']); @@ -156,10 +156,15 @@ $ts = microtime(true); $now = $this->db->fromunixtime((int)$ts); // no session row in DB (db_read() returns false) if (!$this->key) { $oldvars = false; } // use internal data from read() for fast requests (up to 0.5 sec.) if ($key == $this->key && (!$this->vars || $ts - $this->start < 0.5)) { else if ($key == $this->key && (!$this->vars || $ts - $this->start < 0.5)) { $oldvars = $this->vars; } else { // else read data again from DB } else { // else read data again from DB $oldvars = $this->db_read($key); } @@ -281,8 +286,11 @@ { $ts = microtime(true); // no session data in cache (mc_read() returns false) if (!$this->key) $oldvars = false; // use internal data for fast requests (up to 0.5 sec.) if ($key == $this->key && (!$this->vars || $ts - $this->start < 0.5)) else if ($key == $this->key && (!$this->vars || $ts - $this->start < 0.5)) $oldvars = $this->vars; else // else read data again $oldvars = $this->mc_read($key); program/js/app.js
@@ -3489,13 +3489,15 @@ return rcube_event.cancel(e); case 9: // tab if (mod == SHIFT_KEY) break; case 9: // tab if (mod == SHIFT_KEY || !this.ksearch_visible()) { this.ksearch_hide(); return; } case 13: // enter if (this.ksearch_selected === null || !this.ksearch_value) break; if (!this.ksearch_visible()) return false; // insert selected address and hide ksearch pane this.insert_recipient(this.ksearch_selected); @@ -3520,6 +3522,11 @@ return true; }; this.ksearch_visible = function() { return (this.ksearch_selected !== null && this.ksearch_selected !== undefined && this.ksearch_value); }; this.ksearch_select = function(node) { var current = $('#rcmksearchSelected');