|
|
@ -567,30 +567,15 @@ class rcube_ldap extends rcube_addressbook |
|
|
|
$this->result = new rcube_result_set($entries['count'], ($this->list_page-1) * $this->page_size); |
|
|
|
} |
|
|
|
else { |
|
|
|
$prop = $this->group_id ? $this->group_data : $this->prop; |
|
|
|
$base_dn = $this->group_id ? $prop['base_dn'] : $this->base_dn; |
|
|
|
|
|
|
|
// use global search filter
|
|
|
|
if (!empty($this->filter)) |
|
|
|
$prop['filter'] = $this->filter; |
|
|
|
|
|
|
|
// exec LDAP search if no result resource is stored
|
|
|
|
if ($this->ready && !$this->ldap_result) |
|
|
|
$this->ldap_result = $this->ldap->search($base_dn, $prop['filter'], $prop['scope'], $this->prop['attributes'], $prop); |
|
|
|
if ($this->ready && $this->ldap_result === null) { |
|
|
|
$this->ldap_result = $this->extended_search(); |
|
|
|
} |
|
|
|
|
|
|
|
// count contacts for this user
|
|
|
|
$this->result = $this->count(); |
|
|
|
|
|
|
|
// we have a search result resource
|
|
|
|
if ($this->ldap_result && $this->result->count > 0) { |
|
|
|
// sorting still on the ldap server
|
|
|
|
if ($this->sort_col && $prop['scope'] !== 'base' && !$this->ldap->vlv_active) |
|
|
|
$this->ldap_result->sort($this->sort_col); |
|
|
|
|
|
|
|
// get all entries from the ldap server
|
|
|
|
$entries = $this->ldap_result->entries(); |
|
|
|
} |
|
|
|
|
|
|
|
$entries = $this->ldap_result; |
|
|
|
} // end else
|
|
|
|
|
|
|
|
// start and end of the page
|
|
|
@ -753,7 +738,7 @@ class rcube_ldap extends rcube_addressbook |
|
|
|
* @param boolean $nocount (Not used) |
|
|
|
* @param array $required List of fields that cannot be empty |
|
|
|
* |
|
|
|
* @return array Indexed list of contact records and 'count' value |
|
|
|
* @return rcube_result_set List of contact records |
|
|
|
*/ |
|
|
|
function search($fields, $value, $mode=0, $select=true, $nocount=false, $required=array()) |
|
|
|
{ |
|
|
@ -879,12 +864,10 @@ class rcube_ldap extends rcube_addressbook |
|
|
|
// avoid double-wildcard if $value is empty
|
|
|
|
$filter = preg_replace('/\*+/', '*', $filter); |
|
|
|
|
|
|
|
// add general filter to query
|
|
|
|
if (!empty($this->prop['filter'])) |
|
|
|
$filter = '(&(' . preg_replace('/^\(|\)$/', '', $this->prop['filter']) . ')' . $filter . ')'; |
|
|
|
|
|
|
|
// set filter string and execute search
|
|
|
|
$this->set_search_set($filter); |
|
|
|
// @FIXME: we need a better way to detect/define when groups are allowed in the result
|
|
|
|
$prefix = empty($required) ? 'e:' : ''; |
|
|
|
$this->set_search_set($prefix . $filter); |
|
|
|
|
|
|
|
if ($select) |
|
|
|
$this->list_records(); |
|
|
@ -902,24 +885,97 @@ class rcube_ldap extends rcube_addressbook |
|
|
|
function count() |
|
|
|
{ |
|
|
|
$count = 0; |
|
|
|
if ($this->ldap_result) { |
|
|
|
$count = $this->ldap_result->count(); |
|
|
|
if (!empty($this->ldap_result)) { |
|
|
|
$count = $this->ldap_result['count']; |
|
|
|
} |
|
|
|
else if ($this->group_id && $this->group_data['dn']) { |
|
|
|
$count = count($this->list_group_members($this->group_data['dn'], true)); |
|
|
|
} |
|
|
|
// We have a connection but no result set, attempt to get one.
|
|
|
|
else if ($this->ready) { |
|
|
|
$prop = $this->group_id ? $this->group_data : $this->prop; |
|
|
|
$base_dn = $this->group_id ? $this->group_base_dn : $this->base_dn; |
|
|
|
$count = $this->extended_search(true); |
|
|
|
} |
|
|
|
|
|
|
|
if (!empty($this->filter)) { // Use global search filter
|
|
|
|
$prop['filter'] = $this->filter; |
|
|
|
return new rcube_result_set($count, ($this->list_page-1) * $this->page_size); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Wrapper on LDAP searches with group_filters support, which |
|
|
|
* allows searching for contacts AND groups. |
|
|
|
* |
|
|
|
* @param bool $count Return count instead of the records |
|
|
|
* |
|
|
|
* @return int|array Count of records or the result array (with 'count' item) |
|
|
|
*/ |
|
|
|
protected function extended_search($count = false) |
|
|
|
{ |
|
|
|
$prop = $this->group_id ? $this->group_data : $this->prop; |
|
|
|
$base_dn = $this->group_id ? $this->groups_base_dn : $this->base_dn; |
|
|
|
$attrs = $count ? array('dn') : $this->prop['attributes']; |
|
|
|
$entries = array(); |
|
|
|
|
|
|
|
// Use global search filter
|
|
|
|
if ($filter = $this->filter) { |
|
|
|
if ($filter[0] == 'e' && $filter[1] == ':') { |
|
|
|
$filter = substr($filter, 2); |
|
|
|
$is_extended_search = !$this->group_id; |
|
|
|
} |
|
|
|
|
|
|
|
$prop['filter'] = $filter; |
|
|
|
|
|
|
|
// add general filter to query
|
|
|
|
if (!empty($this->prop['filter'])) { |
|
|
|
$prop['filter'] = '(&(' . preg_replace('/^\(|\)$/', '', $this->prop['filter']) . ')' . $prop['filter'] . ')'; |
|
|
|
} |
|
|
|
$count = $this->ldap->search($base_dn, $prop['filter'], $prop['scope'], array('dn'), $prop, true); |
|
|
|
} |
|
|
|
|
|
|
|
return new rcube_result_set($count, ($this->list_page-1) * $this->page_size); |
|
|
|
$result = $this->ldap->search($base_dn, $prop['filter'], $prop['scope'], $attrs, $prop, $count); |
|
|
|
|
|
|
|
// we have a search result resource, get all entries
|
|
|
|
if (!$count && $result && $result->count() > 0) { |
|
|
|
$result = $result->entries(); |
|
|
|
unset($result['count']); |
|
|
|
} |
|
|
|
|
|
|
|
// search for groups
|
|
|
|
if ($is_extended_search |
|
|
|
&& is_array($this->prop['group_filters']) |
|
|
|
&& !empty($this->prop['groups']['filter']) |
|
|
|
) { |
|
|
|
$filter = '(&(' . preg_replace('/^\(|\)$/', '', $this->prop['groups']['filter']) . ')' . $filter . ')'; |
|
|
|
|
|
|
|
// for groups we may use cn instead of displayname...
|
|
|
|
if ($this->prop['fieldmap']['name'] != $this->prop['groups']['name_attr']) { |
|
|
|
$filter = str_replace(strtolower($this->prop['fieldmap']['name']) . '=', $this->prop['groups']['name_attr'] . '=', $filter); |
|
|
|
} |
|
|
|
|
|
|
|
$name_attr = $this->prop['groups']['name_attr']; |
|
|
|
$email_attr = $this->prop['groups']['email_attr'] ?: 'mail'; |
|
|
|
$attrs = array_unique(array('dn', 'objectClass', $name_attr, $email_attr)); |
|
|
|
|
|
|
|
$res = $this->ldap->search($this->groups_base_dn, $filter, $this->prop['groups']['scope'], $attrs, $prop, $count); |
|
|
|
|
|
|
|
if ($count && $res) { |
|
|
|
$result += $res; |
|
|
|
} |
|
|
|
else if (!$count && $res && $res->count()) { |
|
|
|
$res = $res->entries(); |
|
|
|
unset($res['count']); |
|
|
|
$result = array_merge($result, $res); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (!$count && $result) { |
|
|
|
// sorting
|
|
|
|
if ($this->sort_col && $prop['scope'] !== 'base' && !$this->ldap->vlv_active) { |
|
|
|
usort($result, array($this, '_entry_sort_cmp')); |
|
|
|
} |
|
|
|
|
|
|
|
$result['count'] = count($result); |
|
|
|
$this->result_entries = $result; |
|
|
|
} |
|
|
|
|
|
|
|
return $result; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|