@ -52,7 +52,7 @@ class rcube_ldap extends rcube_addressbook
*
*
* @var array
* @var array
*/
*/
private static $group_types = array(
private $group_types = array(
'group' => 'member',
'group' => 'member',
'groupofnames' => 'member',
'groupofnames' => 'member',
'kolabgroupofnames' => 'member',
'kolabgroupofnames' => 'member',
@ -94,6 +94,9 @@ class rcube_ldap extends rcube_addressbook
$this->prop['groups']['name_attr'] = 'cn';
$this->prop['groups']['name_attr'] = 'cn';
if (empty($this->prop['groups']['scope']))
if (empty($this->prop['groups']['scope']))
$this->prop['groups']['scope'] = 'sub';
$this->prop['groups']['scope'] = 'sub';
// extend group objectclass => member attribute mapping
if (!empty($this->prop['groups']['class_member_attr']))
$this->group_types = array_merge($this->group_types, $this->prop['groups']['class_member_attr']);
// add group name attrib to the list of attributes to be fetched
// add group name attrib to the list of attributes to be fetched
$fetch_attributes[] = $this->prop['groups']['name_attr'];
$fetch_attributes[] = $this->prop['groups']['name_attr'];
@ -292,6 +295,14 @@ class rcube_ldap extends rcube_addressbook
if ($this->prop['search_base_dn'] & & $this->prop['search_filter']
if ($this->prop['search_base_dn'] & & $this->prop['search_filter']
& & (strstr($bind_dn, '%dn') || strstr($this->base_dn, '%dn') || strstr($this->groups_base_dn, '%dn'))
& & (strstr($bind_dn, '%dn') || strstr($this->base_dn, '%dn') || strstr($this->groups_base_dn, '%dn'))
) {
) {
$search_attribs = array('uid');
if ($search_bind_attrib = (array)$this->prop['search_bind_attrib']) {
foreach ($search_bind_attrib as $r => $attr) {
$search_attribs[] = $attr;
$replaces[$r] = '';
}
}
$search_bind_dn = strtr($this->prop['search_bind_dn'], $replaces);
$search_bind_dn = strtr($this->prop['search_bind_dn'], $replaces);
$search_base_dn = strtr($this->prop['search_base_dn'], $replaces);
$search_base_dn = strtr($this->prop['search_base_dn'], $replaces);
$search_filter = strtr($this->prop['search_filter'], $replaces);
$search_filter = strtr($this->prop['search_filter'], $replaces);
@ -321,10 +332,18 @@ class rcube_ldap extends rcube_addressbook
}
}
}
}
$res = $ldap->search($search_base_dn, $search_filter, 'sub', array('uid') );
$res = $ldap->search($search_base_dn, $search_filter, 'sub', $search_attribs );
if ($res) {
if ($res) {
$res->rewind();
$res->rewind();
$replaces['%dn'] = $res->get_dn();
$replaces['%dn'] = $res->get_dn();
// add more replacements from 'search_bind_attrib' config
if ($search_bind_attrib) {
$res = $res->current();
foreach ($search_bind_attrib as $r => $attr) {
$replaces[$r] = $res[$attr][0];
}
}
}
}
if ($ldap != $this->ldap) {
if ($ldap != $this->ldap) {
@ -355,6 +374,23 @@ class rcube_ldap extends rcube_addressbook
$this->base_dn = strtr($this->base_dn, $replaces);
$this->base_dn = strtr($this->base_dn, $replaces);
$this->groups_base_dn = strtr($this->groups_base_dn, $replaces);
$this->groups_base_dn = strtr($this->groups_base_dn, $replaces);
// replace placeholders in filter settings
if (!empty($this->prop['filter']))
$this->prop['filter'] = strtr($this->prop['filter'], $replaces);
if (!empty($this->prop['groups']['filter']))
$this->prop['groups']['filter'] = strtr($this->prop['groups']['filter'], $replaces);
if (!empty($this->prop['groups']['member_filter']))
$this->prop['groups']['member_filter'] = strtr($this->prop['groups']['member_filter'], $replaces);
if (!empty($this->prop['group_filters'])) {
foreach ($this->prop['group_filters'] as $i => $gf) {
if (!empty($gf['base_dn']))
$this->prop['group_filters'][$i]['base_dn'] = strtr($gf['base_dn'], $replaces);
if (!empty($gf['filter']))
$this->prop['group_filters'][$i]['filter'] = strtr($gf['filter'], $replaces);
}
}
if (empty($bind_user)) {
if (empty($bind_user)) {
$bind_user = $u;
$bind_user = $u;
}
}
@ -559,9 +595,10 @@ class rcube_ldap extends rcube_addressbook
/**
/**
* Get all members of the given group
* Get all members of the given group
*
*
* @param string Group DN
* @param string Group DN
* @param array Group entries (if called recursively)
* @param boolean Count only
* @return array Accumulated group members
* @param array Group entries (if called recursively)
* @return array Accumulated group members
*/
*/
function list_group_members($dn, $count = false, $entries = null)
function list_group_members($dn, $count = false, $entries = null)
{
{
@ -569,7 +606,7 @@ class rcube_ldap extends rcube_addressbook
// fetch group object
// fetch group object
if (empty($entries)) {
if (empty($entries)) {
$attribs = array('dn','objectClass','member','uniqueMember','memberURL' );
$attribs = array_merge(array('dn','objectClass','memberURL'), array_values($this->group_types) );
$entries = $this->ldap->read_entries($dn, '(objectClass=*)', $attribs);
$entries = $this->ldap->read_entries($dn, '(objectClass=*)', $attribs);
if ($entries === false) {
if ($entries === false) {
return $group_members;
return $group_members;
@ -581,17 +618,17 @@ class rcube_ldap extends rcube_addressbook
$attrs = array();
$attrs = array();
foreach ((array)$entry['objectclass'] as $objectclass) {
foreach ((array)$entry['objectclass'] as $objectclass) {
if (strtolower($objectclass) == 'groupofurls') {
if (($member_attr = $this->get_group_member_attr(array($objectclass), ''))
$members = $this->_list_group_memberurl($dn, $entry, $count);
$group_members = array_merge($group_members, $members);
}
else if (($member_attr = $this->get_group_member_attr(array($objectclass), ''))
& & ($member_attr = strtolower($member_attr)) & & !in_array($member_attr, $attrs)
& & ($member_attr = strtolower($member_attr)) & & !in_array($member_attr, $attrs)
) {
) {
$members = $this->_list_group_members($dn, $entry, $member_attr, $count);
$members = $this->_list_group_members($dn, $entry, $member_attr, $count);
$group_members = array_merge($group_members, $members);
$group_members = array_merge($group_members, $members);
$attrs[] = $member_attr;
$attrs[] = $member_attr;
}
}
else if (!empty($entry['memberurl'])) {
$members = $this->_list_group_memberurl($dn, $entry, $count);
$group_members = array_merge($group_members, $members);
}
if ($this->prop['sizelimit'] & & count($group_members) > $this->prop['sizelimit']) {
if ($this->prop['sizelimit'] & & count($group_members) > $this->prop['sizelimit']) {
break 2;
break 2;
@ -608,6 +645,7 @@ class rcube_ldap extends rcube_addressbook
* @param string Group DN
* @param string Group DN
* @param array Group entry
* @param array Group entry
* @param string Member attribute to use
* @param string Member attribute to use
* @param boolean Count only
* @return array Accumulated group members
* @return array Accumulated group members
*/
*/
private function _list_group_members($dn, $entry, $attr, $count)
private function _list_group_members($dn, $entry, $attr, $count)
@ -621,8 +659,7 @@ class rcube_ldap extends rcube_addressbook
// read these attributes for all members
// read these attributes for all members
$attrib = $count ? array('dn','objectClass') : $this->prop['list_attributes'];
$attrib = $count ? array('dn','objectClass') : $this->prop['list_attributes'];
$attrib[] = 'member';
$attrib = array_merge($attrib, array_values($this->group_types));
$attrib[] = 'uniqueMember';
$attrib[] = 'memberURL';
$attrib[] = 'memberURL';
$filter = $this->prop['groups']['member_filter'] ? $this->prop['groups']['member_filter'] : '(objectclass=*)';
$filter = $this->prop['groups']['member_filter'] ? $this->prop['groups']['member_filter'] : '(objectclass=*)';
@ -1483,7 +1520,7 @@ class rcube_ldap extends rcube_addressbook
{
{
$classes = array_map('strtolower', (array)$entry['objectclass']);
$classes = array_map('strtolower', (array)$entry['objectclass']);
return count(array_intersect(array_keys(self:: $group_types), $classes)) > 0;
return count(array_intersect(array_keys($this-> group_types), $classes)) > 0;
}
}
/**
/**
@ -1914,7 +1951,7 @@ class rcube_ldap extends rcube_addressbook
if (!empty($object_classes)) {
if (!empty($object_classes)) {
foreach ((array)$object_classes as $oc) {
foreach ((array)$object_classes as $oc) {
if ($attr = self:: $group_types[strtolower($oc)]) {
if ($attr = $this-> group_types[strtolower($oc)]) {
return $attr;
return $attr;
}
}
}
}