|
|
@ -554,30 +554,15 @@ class rcube_ldap extends rcube_addressbook
|
|
|
|
$this->result = new rcube_result_set($entries['count'], ($this->list_page-1) * $this->page_size);
|
|
|
|
$this->result = new rcube_result_set($entries['count'], ($this->list_page-1) * $this->page_size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
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
|
|
|
|
// exec LDAP search if no result resource is stored
|
|
|
|
if ($this->ready && !$this->ldap_result)
|
|
|
|
if ($this->ready && $this->ldap_result === null) {
|
|
|
|
$this->ldap_result = $this->ldap->search($base_dn, $prop['filter'], $prop['scope'], $this->prop['attributes'], $prop);
|
|
|
|
$this->ldap_result = $this->extended_search();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// count contacts for this user
|
|
|
|
// count contacts for this user
|
|
|
|
$this->result = $this->count();
|
|
|
|
$this->result = $this->count();
|
|
|
|
|
|
|
|
|
|
|
|
// we have a search result resource
|
|
|
|
$entries = $this->ldap_result;
|
|
|
|
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();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // end else
|
|
|
|
} // end else
|
|
|
|
|
|
|
|
|
|
|
|
// start and end of the page
|
|
|
|
// start and end of the page
|
|
|
@ -741,7 +726,7 @@ class rcube_ldap extends rcube_addressbook
|
|
|
|
* @param boolean $nocount (Not used)
|
|
|
|
* @param boolean $nocount (Not used)
|
|
|
|
* @param array $required List of fields that cannot be empty
|
|
|
|
* @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())
|
|
|
|
function search($fields, $value, $mode=0, $select=true, $nocount=false, $required=array())
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -867,12 +852,10 @@ class rcube_ldap extends rcube_addressbook
|
|
|
|
// avoid double-wildcard if $value is empty
|
|
|
|
// avoid double-wildcard if $value is empty
|
|
|
|
$filter = preg_replace('/\*+/', '*', $filter);
|
|
|
|
$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
|
|
|
|
// 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)
|
|
|
|
if ($select)
|
|
|
|
$this->list_records();
|
|
|
|
$this->list_records();
|
|
|
@ -891,24 +874,97 @@ class rcube_ldap extends rcube_addressbook
|
|
|
|
function count()
|
|
|
|
function count()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
$count = 0;
|
|
|
|
$count = 0;
|
|
|
|
if ($this->ldap_result) {
|
|
|
|
if (!empty($this->ldap_result)) {
|
|
|
|
$count = $this->ldap_result->count();
|
|
|
|
$count = $this->ldap_result['count'];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ($this->group_id && $this->group_data['dn']) {
|
|
|
|
else if ($this->group_id && $this->group_data['dn']) {
|
|
|
|
$count = count($this->list_group_members($this->group_data['dn'], true));
|
|
|
|
$count = count($this->list_group_members($this->group_data['dn'], true));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// We have a connection but no result set, attempt to get one.
|
|
|
|
// We have a connection but no result set, attempt to get one.
|
|
|
|
else if ($this->ready) {
|
|
|
|
else if ($this->ready) {
|
|
|
|
$prop = $this->group_id ? $this->group_data : $this->prop;
|
|
|
|
$count = $this->extended_search(true);
|
|
|
|
$base_dn = $this->group_id ? $this->group_base_dn : $this->base_dn;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!empty($this->filter)) { // Use global search filter
|
|
|
|
return new rcube_result_set($count, ($this->list_page-1) * $this->page_size);
|
|
|
|
$prop['filter'] = $this->filter;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|