From 2965a981b7ec22866fbdf2d567d87e2d068d3617 Mon Sep 17 00:00:00 2001
From: Thomas Bruederli <thomas@roundcube.net>
Date: Fri, 31 Jul 2015 16:04:08 -0400
Subject: [PATCH] Allow to search and import missing PGP pubkeys from keyservers using Publickey.js
---
program/lib/Roundcube/rcube_ldap.php | 125 +++++++++++++++++++++++++----------------
1 files changed, 77 insertions(+), 48 deletions(-)
diff --git a/program/lib/Roundcube/rcube_ldap.php b/program/lib/Roundcube/rcube_ldap.php
index 274616a..dc7b3c0 100644
--- a/program/lib/Roundcube/rcube_ldap.php
+++ b/program/lib/Roundcube/rcube_ldap.php
@@ -64,7 +64,6 @@
private $base_dn = '';
private $groups_base_dn = '';
- private $group_url;
private $group_data;
private $group_search_cache;
private $cache;
@@ -118,13 +117,14 @@
// fieldmap property is given
if (is_array($p['fieldmap'])) {
+ $p['fieldmap'] = array_filter($p['fieldmap']);
foreach ($p['fieldmap'] as $rf => $lf)
$this->fieldmap[$rf] = $this->_attr_name(strtolower($lf));
}
else if (!empty($p)) {
// read deprecated *_field properties to remain backwards compatible
foreach ($p as $prop => $value)
- if (preg_match('/^(.+)_field$/', $prop, $matches))
+ if (!empty($value) && preg_match('/^(.+)_field$/', $prop, $matches))
$this->fieldmap[$matches[1]] = $this->_attr_name(strtolower($value));
}
@@ -283,12 +283,21 @@
}
// Get the pieces needed for variable replacement.
- if ($fu = $rcube->get_user_email())
+ if ($fu = $rcube->get_user_email()) {
list($u, $d) = explode('@', $fu);
- else
+ }
+ else {
$d = $this->mail_domain;
+ }
$dc = 'dc='.strtr($d, array('.' => ',dc=')); // hierarchal domain string
+
+ // resolve $dc through LDAP
+ if (!empty($this->prop['domain_filter']) && !empty($this->prop['search_bind_dn']) &&
+ method_exists($this->ldap, 'domain_root_dn')) {
+ $this->ldap->bind($this->prop['search_bind_dn'], $this->prop['search_bind_pw']);
+ $dc = $this->ldap->domain_root_dn($d);
+ }
$replaces = array('%dn' => '', '%dc' => $dc, '%d' => $d, '%fu' => $fu, '%u' => $u);
@@ -698,8 +707,9 @@
for ($i=0; $i < $entry['memberurl']['count']; $i++) {
// extract components from url
- if (!preg_match('!ldap:///([^\?]+)\?\?(\w+)\?(.*)$!', $entry['memberurl'][$i], $m))
+ if (!preg_match('!ldap://[^/]*/([^\?]+)\?\?(\w+)\?(.*)$!', $entry['memberurl'][$i], $m)) {
continue;
+ }
// add search filter if any
$filter = $this->filter ? '(&(' . $m[3] . ')(' . $this->filter . '))' : $m[3];
@@ -766,16 +776,16 @@
if ($this->prop['vlv_search'] && $this->ready && join(',', (array)$fields) == join(',', $list_fields)) {
$this->result = new rcube_result_set(0);
- $search_suffix = $this->prop['fuzzy_search'] && $mode != 1 ? '*' : '';
+ $this->ldap->config_set('fuzzy_search', intval($this->prop['fuzzy_search'] && $mode != 1));
$ldap_data = $this->ldap->search($this->base_dn, $this->prop['filter'], $this->prop['scope'], $this->prop['attributes'],
- array('search' => $value . $search_suffix /*, 'sort' => $this->prop['sort'] */));
+ array('search' => $value /*, 'sort' => $this->prop['sort'] */));
if ($ldap_data === false) {
return $this->result;
}
// get all entries of this page and post-filter those that really match the query
$search = mb_strtolower($value);
- foreach ($ldap_data as $i => $entry) {
+ foreach ($ldap_data as $entry) {
$rec = $this->_ldap2result($entry);
foreach ($fields as $f) {
foreach ((array)$rec[$f] as $val) {
@@ -791,33 +801,24 @@
return $this->result;
}
- // use AND operator for advanced searches
- $filter = is_array($value) ? '(&' : '(|';
- // set wildcards
- $wp = $ws = '';
- if (!empty($this->prop['fuzzy_search']) && $mode != 1) {
- $ws = '*';
- if (!$mode) {
- $wp = '*';
- }
- }
+ // advanced per-attribute search
+ if (is_array($value)) {
+ // use AND operator for advanced searches
+ $filter = '(&';
- if ($fields == '*') {
- // search_fields are required for fulltext search
- if (empty($this->prop['search_fields'])) {
- $this->set_error(self::ERROR_SEARCH, 'nofulltextsearch');
- $this->result = new rcube_result_set();
- return $this->result;
- }
- if (is_array($this->prop['search_fields'])) {
- foreach ($this->prop['search_fields'] as $field) {
- $filter .= "($field=$wp" . rcube_ldap_generic::quote_string($value) . "$ws)";
+ // set wildcards
+ $wp = $ws = '';
+ if (!empty($this->prop['fuzzy_search']) && $mode != 1) {
+ $ws = '*';
+ if (!$mode) {
+ $wp = '*';
}
}
- }
- else {
+
foreach ((array)$fields as $idx => $field) {
- $val = is_array($value) ? $value[$idx] : $value;
+ $val = $value[$idx];
+ if (!strlen($val))
+ continue;
if ($attrs = $this->_map_field($field)) {
if (count($attrs) > 1)
$filter .= '(|';
@@ -827,8 +828,33 @@
$filter .= ')';
}
}
+
+ $filter .= ')';
}
- $filter .= ')';
+ else {
+ if ($fields == '*') {
+ // search_fields are required for fulltext search
+ if (empty($this->prop['search_fields'])) {
+ $this->set_error(self::ERROR_SEARCH, 'nofulltextsearch');
+ $this->result = new rcube_result_set();
+ return $this->result;
+ }
+ $attributes = (array)$this->prop['search_fields'];
+ }
+ else {
+ // map address book fields into ldap attributes
+ $me = $this;
+ $attributes = array();
+ array_walk($fields, function($field) use ($me, &$attributes) {
+ if ($me->coltypes[$field] && ($attrs = (array)$me->coltypes[$field]['attributes'])) {
+ $attributes = array_merge($attributes, $attrs);
+ }
+ });
+ }
+
+ // compose a full-text-like search filter
+ $filter = rcube_ldap_generic::fulltext_search_filter($value, $attributes, $mode);
+ }
// add required (non empty) fields filter
$req_filter = '';
@@ -906,7 +932,6 @@
return $this->result;
}
-
/**
* Get a specific contact record
*
@@ -946,6 +971,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;
}
@@ -1515,7 +1557,6 @@
return $ldap_data;
}
-
/**
* Returns unified attribute name (resolving aliases)
*/
@@ -1547,17 +1588,6 @@
}
/**
- * Prints debug info to the log
- */
- private function _debug($str)
- {
- if ($this->debug) {
- rcube::write_log('ldap', $str);
- }
- }
-
-
- /**
* Activate/deactivate debug mode
*
* @param boolean $dbg True if LDAP commands should be logged
@@ -1570,7 +1600,6 @@
$this->ldap->config_set('debug', $dbg);
}
}
-
/**
* Setter for the current group
@@ -1609,7 +1638,7 @@
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;
}
}
@@ -1974,7 +2003,7 @@
$filter = strtr("(|(member=$contact_dn)(uniqueMember=$contact_dn)$add_filter)", array('\\' => '\\\\'));
$ldap_data = $this->ldap->search($base_dn, $filter, 'sub', array('dn', $name_attr));
- if ($res === false) {
+ if ($ldap_data === false) {
return array();
}
--
Gitblit v1.9.1