Use Horde_Ldap.
authorJan Schneider <jan@horde.org>
Fri, 17 Sep 2010 23:16:37 +0000 (01:16 +0200)
committerJan Schneider <jan@horde.org>
Fri, 17 Sep 2010 23:17:56 +0000 (01:17 +0200)
framework/Group/lib/Horde/Group/Ldap.php
framework/Group/lib/Horde/Group/LdapObject.php

index 5c55c30..25cf3a1 100644 (file)
@@ -8,6 +8,7 @@
  * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  *
  * @author   Ben Chavet <ben@horde.org>
+ * @author   Jan Schneider <jan@horde.org>
  * @category Horde
  * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
  * @package  Group
 class Horde_Group_Ldap extends Horde_Group
 {
     /**
-     * LDAP connection handle
+     * LDAP object.
+     *
+     * @var Horde_Ldap
      */
-    protected $_ds;
+    protected $_ldap;
 
     /**
      * Local copy of the global $conf['group']['params'] array. Simply
      * for coding convenience.
+     *
+     * @var array
      */
     protected $_params;
 
     /**
-     * Generated LDAP filter based on the config parameters
+     * LDAP filter based on the config parameters.
+     *
+     * @var Horde_Ldap_Filter
      */
     protected $_filter;
 
     /**
+     * Local cache for already retrieved group objects, indexed by DN.
+     *
+     * @var array
+     */
+    protected $_dnCache = array();
+
+    /**
+     * Local cache for already retrieved group objects, indexed by group name.
+     *
+     * @var array
+     */
+    protected $_nameCache = array();
+
+    /**
+     * Local cache for already retrieved group names, indexed by DN.
+     *
+     * @var array|boolean
+     */
+    protected $_listCache = false;
+
+    /**
+     * Local cache for already retrieved group memberships, indexed by user
+     * name.
+     *
+     * @var array
+     */
+    protected $_userCache = array();
+
+    /**
+     * Local cache for already retrieved group users, indexed by group name.
+     *
+     * @var array
+     */
+    protected $_groupCache = array();
+
+    /**
      * Constructor.
      */
     public function __construct($params)
@@ -38,100 +81,34 @@ class Horde_Group_Ldap extends Horde_Group
         $this->_params = $params;
         $this->_params['gid'] = Horde_String::lower($this->_params['gid']);
         $this->_params['memberuid'] = Horde_String::lower($this->_params['memberuid']);
-        foreach ($this->_params['newgroup_objectclass'] as $key => $val) {
-            $this->_params['newgroup_objectclass'][$key] = Horde_String::lower($val);
+        foreach ($this->_params['newgroup_objectclass'] as &$val) {
+            $val = Horde_String::lower($val);
         }
 
         /* Generate LDAP search filter. */
         if (!empty($this->_params['filter'])) {
-            $this->_filter = $this->_params['filter'];
+            $this->_filter = Horde_Ldap_Filter::parse($this->_params['filter']);
         } elseif (!is_array($this->_params['objectclass'])) {
-            $this->_filter = 'objectclass=' . $this->_params['objectclass'];
+            $this->_filter = Horde_Ldap_Filter::create('objectclass', 'equals', $this->_params['objectclass']);
         } else {
-            $this->_filter = '';
+            $filters = array();
             foreach ($this->_params['objectclass'] as $objectclass) {
-                $this->_filter = '(&' . $this->_filter;
-                $this->_filter .= '(objectclass=' . $objectclass . '))';
+                $filters[] = Horde_Ldap_Filter::create('objectclass', 'equals', $objectclass);
             }
-        }
-
-        $this->_filter = Horde_String::lower($this->_filter);
-    }
-
-    /**
-     * Connects to the LDAP server.
-     *
-     * @throws Horde_Group_Exception
-     */
-    protected function _connect()
-    {
-        /* Connect to the LDAP server. */
-        $this->_ds = @ldap_connect($this->_params['hostspec']);
-        if (!$this->_ds) {
-            throw new Horde_Group_Exception('Could not reach the LDAP server');
-        }
-
-        if (!@ldap_set_option($this->_ds, LDAP_OPT_PROTOCOL_VERSION,
-                              $this->_params['version'])) {
-            Horde::logMessage(
-                sprintf('Set LDAP protocol version to %d failed: [%d] %s',
-                        $this->_params['version'],
-                        @ldap_errno($this->_ds),
-                        @ldap_error($this->_ds)),
-                'ERR');
-        }
-
-        /* Start TLS if we're using it. */
-        if (!empty($this->_params['tls'])) {
-            if (!@ldap_start_tls($this->_ds)) {
-                Horde::logMessage(
-                    sprintf('STARTTLS failed: [%d] %s',
-                            @ldap_errno($this->_ds),
-                            @ldap_error($this->_ds)),
-                    'ERR');
+            if (count($filters) == 1) {
+                $this->_filter = $filters[0];
+            } else {
+                $this->_filter = Horde_Ldap_Filter::combine('and', $filters);
             }
         }
 
-        if (isset($this->_params['binddn'])) {
-            $bind = @ldap_bind($this->_ds, $this->_params['binddn'],
-                               $this->_params['bindpw']);
-        } else {
-            $bind = @ldap_bind($this->_ds);
-        }
-
-        if (!$bind) {
-            throw new Horde_Group_Exception('Could not bind to LDAP server');
-        }
+        /* Connect to server. */
+        $this->_ldap = new Horde_Ldap($this->_params);
     }
 
     /**
-     * Recursively deletes $dn. $this->_ds MUST already be connected.
-     *
-     * @throws Horde_Group_Exception
-     */
-    protected function _recursive_delete($dn)
-    {
-        $search = @ldap_list($this->_ds, $dn, 'objectclass=*', array(''));
-        if (!$search) {
-            throw new Horde_Group_Exception('Could not reach the LDAP server');
-        }
-
-        $children = @ldap_get_entries($this->_ds, $search);
-        for ($i = 0; $i < $children['count']; $i++) {
-            $result = $this->_recursive_delete($children[$i]['dn']);
-            if (!$result) {
-                throw new Horde_Group_Exception(sprintf(__CLASS__ . ': Unable to delete group "%s". This is what the server said: %s', $this->getName($children[$i]['dn']), @ldap_error($this->_ds)));
-            }
-        }
-
-        if (!@ldap_delete($this->_ds, $dn)) {
-            throw new Horde_Group_Exception(sprintf(__CLASS__ . ': Unable to delete group "%s". This is what the server said: %s', $dn, @ldap_error($this->_ds)));
-        }
-    }
-
-    /**
-     * Searches existing groups for the highest gidnumber, and returns
-     * one higher.
+     * Searches existing groups for the highest gidnumber, and returns one
+     * higher.
      *
      * @return integer
      *
@@ -139,33 +116,26 @@ class Horde_Group_Ldap extends Horde_Group
      */
     protected function _nextGid()
     {
-        /* Connect to the LDAP server. */
-        $this->_connect();
-
-        $search = @ldap_search($this->_ds, $this->_params['basedn'], $this->_filter);
-        if (!$search) {
-            throw new Horde_Group_Exception('Could not reach the LDAP server');
+        try {
+            $search = $this->_ldap->search($this->_params['basedn'], $this->_filter, array('attributes' => array('gidnumber')));
+        } catch (Horde_Ldap_Exception $e) {
+            throw new Horde_Group_Exception($e);
         }
 
-        $result = @ldap_get_entries($this->_ds, $search);
-        @ldap_close($this->_ds);
-
-        if (!is_array($result) || (count($result) <= 1)) {
+        if (!$search->count()) {
             return 1;
         }
 
         $nextgid = 0;
-        for ($i = 0; $i < $result['count']; $i++) {
-            if ($result[$i]['gidnumber'][0] > $nextgid) {
-                $nextgid = $result[$i]['gidnumber'][0];
-            }
+        foreach ($search as $entry) {
+            $nextgid = max($nextgid, $entry->getValue('gidnumber', 'single'));
         }
 
         return $nextgid + 1;
     }
 
     /**
-     * Return a new group object.
+     * Returns a new group object.
      *
      * @param string $name    The group's name.
      * @param string $parent  The group's parent's ID (DN).
@@ -192,8 +162,8 @@ class Horde_Group_Ldap extends Horde_Group
     }
 
     /**
-     * Return a group object corresponding to the named group, with the
-     * users and other data retrieved appropriately.
+     * Returns a group object corresponding to the named group, with the users
+     * and other data retrieved appropriately.
      *
      * @param string $name  The name of the group to retrieve.
      *
@@ -206,58 +176,40 @@ class Horde_Group_Ldap extends Horde_Group
     }
 
     /**
-     * Return a group object corresponding to the given dn, with the
-     * users and other data retrieved appropriately.
+     * Returns a group object corresponding to the given DN, with the users and
+     * other data retrieved appropriately.
      *
-     * @param string $dn  The dn of the group to retrieve.
+     * @param string $dn  The DN of the group to retrieve.
      *
      * @return Horde_Group_LdapObject  The requested group.
      * @throws Horde_Group_Exception
+     * @throws Horde_Exception_NotFound
      */
     public function getGroupById($dn)
     {
-        static $cache = array();
-
-        if (!isset($cache[$dn])) {
-            /* Connect to the LDAP server. */
-            $this->_connect();
-
-            $search = @ldap_search($this->_ds, $dn, $this->_filter);
-            if (!$search) {
-                throw new Horde_Group_Exception('Could not reach the LDAP server');
-            }
-
-            $result = @ldap_get_entries($this->_ds, $search);
-            @ldap_close($this->_ds);
-            if (!is_array($result) || (count($result) <= 1)) {
-                throw new Horde_Group_Exception('Empty result');
-            }
-
-            $attributes = array();
-            for ($i = 0; $i < $result[0]['count']; $i++) {
-                if ($result[0][$result[0][$i]]['count'] > 1) {
-                    $attributes[$result[0][$i]] = array();
-                    for ($j = 0; $j < $result[0][$result[0][$i]]['count']; $j++) {
-                        $attributes[$result[0][$i]][] = $result[0][$result[0][$i]][$j];
-                    }
-                } else {
-                    $attributes[$result[0][$i]] = $result[0][$result[0][$i]][0];
-                }
-            }
-            $attributes['dn'] = $result[0]['dn'];
+        if (isset($this->_dnCache[$dn])) {
+            return $this->_dnCache[$dn];
+        }
 
-            $group = new Horde_Group_LdapObject($this->getGroupName($dn));
-            $group->fromAttributes($attributes);
-            $group->setGroupOb($this);
-            $cache[$dn] = $group;
+        try {
+            $entry = $this->_ldap->getEntry($dn);
+        } catch (Horde_Ldap_Exception $e) {
+            throw new Horde_Group_Exception($e);
         }
 
-        return $cache[$dn];
+        $group = new Horde_Group_LdapObject($this->getGroupName($dn));
+        $group->setEntry($entry);
+        $group->setGroupOb($this);
+        $this->_dnCache[$dn] = $group;
+
+        return $group;
     }
 
     /**
-     * Get a globally unique ID for a group.  This really just returns the dn
-     * for the group, but is included for compatibility with the Group class.
+     * Returns a globally unique ID for a group.
+     *
+     * This really just returns the DN for the group, but is included for
+     * compatibility with the Group class.
      *
      * @param Horde_Group_LdapObject $group  The group.
      *
@@ -269,35 +221,30 @@ class Horde_Group_Ldap extends Horde_Group
     }
 
     /**
-     * Add a group to the groups system.  The group must first be created with
-     * Group_ldap::newGroup(), and have any initial users added to it, before
-     * this function is called.
+     * Adds a group to the groups system.
+     *
+     * The group must first be created with Horde_Group_Ldap::newGroup(), and
+     * have any initial users added to it, before this function is called.
      *
      * @param Horde_Group_LdapObject $group  The new group object.
      *
      * @throws Horde_Group_Exception
      */
-    public function addGroup(Horde_Group_DataTreeObject $group)
+    public function addGroup(Horde_Group_LdapObject $group)
     {
-        /* Connect to the LDAP server. */
-        $this->_connect();
-
         $dn = $group->get('dn');
-
-        $entry = $group->toAttributes();
-        $success = @ldap_add($this->_ds, $dn, $entry);
-
-        if (!$success) {
-            throw new Horde_Group_Exception(sprintf(__CLASS__ . ': Unable to add group "%s". This is what the server said: ', $group->getName()) . @ldap_error($this->_ds));
+        $entry = Horde_Ldap_Entry::createFresh($dn, $group->toAttributes());
+        try {
+            $this->_ldap->add($entry);
+        } catch (Horde_Ldap_Exception $e) {
+            throw new Horde_Group_Exception($e);
         }
-
-        @ldap_close($this->_ds);
     }
 
     /**
-     * Store updated data - users, etc. - of a group to the backend system.
+     * Stores updated data - users, etc. - of a group to the backend system.
      *
-     * @param Horde_Group_LdapObject $group  The group to update
+     * @param Horde_Group_LdapObject $group  The group to update.
      *
      * @throws Horde_Group_Exception
      * @throws Horde_History_Exception
@@ -305,21 +252,18 @@ class Horde_Group_Ldap extends Horde_Group
      */
     public function updateGroup(Horde_Group_LdapObject $group)
     {
-        $entry = $group->toAttributes();
-
-        /* Connect to the LDAP server. */
-        $this->_connect();
-
+        $entry = $group->getEntry();
+        $attributes = $group->toAttributes();
         // Do not attempt to change an LDAP object's objectClasses
-        unset($entry['objectclass']);
+        unset($attributes['objectclass']);
 
-        $result = @ldap_modify($this->_ds, $group->getId(), $entry);
-        if (!$result) {
-            throw new Horde_Group_Exception(sprintf(__CLASS__ . ': Unable to update group "%s". This is what the server said: %s', $group->getName(), @ldap_error($this->_ds)));
+        try {
+            $entry->replace($attributes);
+            $entry->update();
+        } catch (Horde_Ldap_Exception $e) {
+            throw new Horde_Group_Exception($e);
         }
 
-        @ldap_close($this->_ds);
-
         /* Log the update of the group users on the history log. */
         $history = $GLOBALS['injector']->getInstance('Horde_History');
         $guid = $this->getGUID($group);
@@ -330,12 +274,10 @@ class Horde_Group_Ldap extends Horde_Group
 
         /* Log the group modification. */
         $history->log($guid, array('action' => 'modify'), true);
-
-        return $result;
     }
 
     /**
-     * Remove a group from the groups system permanently.
+     * Removes a group from the groups system permanently.
      *
      * @param Horde_Group_LdapObject $group  The group to remove.
      * @param boolean $force     Recursively delete children groups if true.
@@ -345,22 +287,15 @@ class Horde_Group_Ldap extends Horde_Group
     public function removeGroup(Horde_Group_DataTreeObject $group,
                                 $force = false)
     {
-        $dn = $group->getId();
-
-        /* Connect to the LDAP server. */
-        $this->_connect();
-
-        if ($force) {
-            return $this->_recursive_delete($dn);
-        }
-
-        if (!@ldap_delete($this->_ds, $dn)) {
-            throw new Horde_Group_Exception(sprintf(__CLASS__ . ': Unable to delete group "%s". This is what the server said: %s', $dn, @ldap_error($this->_ds)));
+        try {
+            $this->_ldap->delete($group->getId(), $force);
+        } catch (Horde_Ldap_Exception $e) {
+            throw new Horde_Group_Exception($e);
         }
     }
 
     /**
-     * Retrieve the name of a group.
+     * Retrieves the name of a group.
      *
      * @param string $dn  The dn of the group to retrieve the name for.
      *
@@ -393,46 +328,48 @@ class Horde_Group_Ldap extends Horde_Group
     }
 
     /**
-     * Retrieve the ID of the given group.
+     * Returns the ID of the given group.
      *
      * NOTE: If given a group name, this function can be unreliable if more
      * than one group exists with the same name.
      *
-     * @param mixed $group  Group object, or a group name (string).
+     * @param Horde_Group_LdapObject|string $group  Group object, or a group name.
      *
      * @return string  The group's ID.
      * @throws Horde_Group_Exception
      */
     public function getGroupId($group)
     {
-        static $cache = array();
-
         if ($group instanceof Horde_Group_LdapObject) {
             return $group->get('dn');
         }
 
-        if (!isset($cache[$group])) {
-            $this->_connect();
-            $search = @ldap_search($this->_ds, $this->_params['basedn'],
-                                   $this->_params['gid'] . '=' . $group,
-                                   array($this->_params['gid']));
-            if (!$search) {
-                throw new Horde_Group_Exception('Could not reach the LDAP server');
-            }
+        if (isset($this->_nameCache[$group])) {
+            return $this->_nameCache[$group];
+        }
 
-            $result = @ldap_get_entries($this->_ds, $search);
-            @ldap_close($this->_ds);
-            if (!is_array($result) || (count($result) <= 1)) {
-                throw new Horde_Group_Exception('Empty result');
-            }
-            $cache[$group] = $result[0]['dn'];
+        try {
+            $search = $this->_ldap->search(
+                $this->_params['basedn'],
+                Horde_Ldap_Filter::create($this->_params['gid'], 'equals', $group),
+                array('attributes' => array($this->_params['gid'])));
+        } catch (Horde_Ldap_Exception $e) {
+            throw new Horde_Group_Exception($e);
+        }
+        if (!$search->count()) {
+            throw new Horde_Group_Exception('Empty result');
+        }
+        try {
+            $this->_nameCache[$group] = $search->shiftEntry()->dn();
+        } catch (Horde_Ldap_Exception $e) {
+            throw new Horde_Group_Exception($e);
         }
 
-        return $cache[$group];
+        return $this->_nameCache[$group];
     }
 
     /**
-     * Check if a group exists in the system.
+     * Returns whether a group exists in the system.
      *
      * @param string $group  The group name to check for.
      *
@@ -441,32 +378,21 @@ class Horde_Group_Ldap extends Horde_Group
      */
     public function exists($group)
     {
-        static $cache = array();
-
-        if (!isset($cache[$group])) {
-            /* Connect to the LDAP server. */
-            $this->_connect();
-
-            $groupDN = $this->getGroupId($group);
-            $group = $this->getGroupShortName($group);
-
-            $res = @ldap_compare($this->_ds, $groupDN, $this->_params['gid'], $group);
-            // $res is True if the group exists, false if not, -1 on error.
-            if ($res === -1) {
-                throw new Horde_Group_Exception(sprintf('Internal Error: An attribute must ALWAYS match itself: %s', @ldap_error($this->_ds)));
-            }
-            $cache[$group] = $res;
+        try {
+            $ldapGroup = $this->getGroup($group);
+        } catch (Horde_Exception_NotFound $e) {
+            return false;
         }
 
-        return $cache[$group];
+        return $ldapGroup->getName() == $group->getName();
     }
 
     /**
-     * Get a list of the parents of a child group.
+     * Returns a list of the parents of a child group.
      *
-     * @param string $dn  The fully qualified group dn
+     * @param string $dn  The fully qualified group DN.
      *
-     * @return array  Nested array of parents
+     * @return array  Nested array of parents.
      */
     public function getGroupParents($dn)
     {
@@ -480,11 +406,11 @@ class Horde_Group_Ldap extends Horde_Group
     }
 
     /**
-     * Get the parent of the given group.
+     * Returns the parent of the given group.
      *
-     * @param string $dn  The dn of the child group.
+     * @param string $dn  The DN of the child group.
      *
-     * @return string  The dn of the parent group.
+     * @return string  The DN of the parent group.
      * @throws Horde_Group_Exception
      */
     public function getGroupParent($dn)
@@ -503,10 +429,10 @@ class Horde_Group_Ldap extends Horde_Group
     }
 
     /**
-     * Get a list of parents all the way up to the root object for the given
-     * group.
+     * Returns a list of parents all the way up to the root object for the
+     * given group.
      *
-     * @param string $dn  The dn of the group.
+     * @param string $dn  The DN of the group.
      *
      * @return array  A flat list of all of the parents of the given group,
      *                hashed in $dn => $name format.
@@ -536,7 +462,7 @@ class Horde_Group_Ldap extends Horde_Group
     }
 
     /**
-     * Get a list of every group, in the format dn => groupname.
+     * Returns a list of every group, in the format dn => groupname.
      *
      * @param boolean $refresh  If true, the cached value is ignored and the
      *                          group list is refreshed from the group backend.
@@ -546,75 +472,55 @@ class Horde_Group_Ldap extends Horde_Group
      */
     public function listGroups($refresh = false)
     {
-        static $groups;
-
-        if ($refresh || is_null($groups)) {
-            /* Connect to the LDAP server. */
-            $this->_connect();
-
-            $search = @ldap_search($this->_ds, $this->_params['basedn'], $this->_filter, array($this->_params['gid']));
-            if (!$search) {
-                throw new Horde_Group_Exception('Could not search the LDAP server');
-            }
-
-            @ldap_sort($this->_ds, $search, $this->_params['gid']);
+        if ($this->_listCache !== false) {
+            return $this->_listCache;
+        }
 
-            $result = @ldap_get_entries($this->_ds, $search);
-            @ldap_close($this->_ds);
-            if (!is_array($result) || (count($result) <= 1)) {
-                return array();
-            }
+        $this->_listCache = array();
+        try {
+            $search = $this->_ldap->search($this->_params['basedn'], $this->_filter, array($this->_params['gid']));
+        } catch (Horde_Ldap_Exception $e) {
+            throw new Horde_Group_Exception($e);
+        }
 
-            $groups = array();
-            for ($i = 0; $i < $result['count']; $i++) {
-                $groups[$result[$i]['dn']] = $this->getGroupName($result[$i]['dn']);
-            }
+        foreach ($search->sorted_as_struct(array($this->_params['gid'])) as $entry) {
+            $this->_listCache[$entry['dn']] = $this->getGroupName($entry['dn']);
         }
 
-        return $groups;
+        return $this->_listCache;
     }
 
     /**
-     * Get a list of every user that is part of the specified group and any
+     * Returns a list of every user that is part of the specified group and any
      * of its subgroups.
      *
-     * @param string $dn  The dn of the parent group.
+     * @param string $dn  The DN of the parent group.
      *
      * @return array  The complete user list.
      * @throws Horde_Group_Exception
      */
     public function listAllUsers($dn)
     {
-        static $cache = array();
-
-        if (!isset($cache[$dn])) {
-            $this->_connect();
-
-            $search = @ldap_search($this->_ds, $dn, $this->_filter);
-            if (!$search) {
-                throw new Horde_Group_Exception(sprintf('Could not reach the LDAP server: %s', @ldap_error($this->_ds)));
-            }
-
-            $result = @ldap_get_entries($this->_ds, $search);
-            @ldap_close($this->_ds);
-            if (!is_array($result) || (count($result) <= 1)) {
-                // Not an error, we just don't have any users in this group.
-                return array();
-            }
+        if (isset($this->_groupCache[$dn])) {
+            return $this->_groupCache[$dn];
+        }
 
-            $users = array();
-            for ($i = 0; $i < $result['count']; $i++) {
-                $users = array_merge($users, $this->listUsers($result[$i]['dn']));
-            }
+        try {
+            $search = $this->_ldap->search($dn, $this->_filter);
+        } catch (Horde_Ldap_Exception $e) {
+            throw new Horde_Group_Exception($e);
+        }
 
-            $cache[$dn] = array_keys(array_flip($users));
+        $users = array();
+        foreach ($search as $dn => $entry) {
+            $users = array_merge($users, $this->listUsers($dn));
         }
 
-        return $cache[$dn];
+        return $this->_groupCache[$dn] = array_keys(array_flip($users));
     }
 
     /**
-     * Get a list of every group that the given user is a member of.
+     * Returns a list of every group that the given user is a member of.
      *
      * @param string  $user          The user to get groups for.
      * @param boolean $parentGroups  Also return the parents of any groups?
@@ -624,46 +530,37 @@ class Horde_Group_Ldap extends Horde_Group
      */
     public function getGroupMemberships($user, $parentGroups = false)
     {
-        static $cache = array();
-
-        if (empty($cache[$user])) {
-            /* Connect to the LDAP server. */
-            $this->_connect();
-
-            // Set up search filter
-            $filter = '(' . $this->_params['memberuid'] . '=';
-            if ($GLOBALS['conf']['group']['params']['attrisdn']) {
-                $filter .= $GLOBALS['conf']['auth']['params']['uid'] . '=';
-            }
-            $filter .= $user;
-            if ($GLOBALS['conf']['group']['params']['attrisdn']) {
-                $filter .= ',' . $GLOBALS['conf']['auth']['params']['basedn'];
-            }
-            $filter .= ')';
-
-            // Perform search
-            $search = @ldap_search($this->_ds, $this->_params['basedn'], $filter);
-            if (!$search) {
-                throw new Horde_Group_Exception('Could not reach the LDAP server');
-            }
+        if (isset($this->_userCache[$user])) {
+            return $this->_userCache[$user];
+        }
 
-            $result = @ldap_get_entries($this->_ds, $search);
-            @ldap_close($this->_ds);
-            if (!is_array($result) || (count($result) <= 1)) {
-                return array();
-            }
+        // Set up search filter.
+        // TODO/FIXME/WTH?
+        $filter = '(' . $this->_params['memberuid'] . '=';
+        if ($GLOBALS['conf']['group']['params']['attrisdn']) {
+            $filter .= $GLOBALS['conf']['auth']['params']['uid'] . '=';
+        }
+        $filter .= $user;
+        if ($GLOBALS['conf']['group']['params']['attrisdn']) {
+            $filter .= ',' . $GLOBALS['conf']['auth']['params']['basedn'];
+        }
+        $filter .= ')';
 
-            $groups = array();
-            $current_charset = $GLOBALS['registry']->getCharset();
-            for ($i = 0; $i < $result['count']; $i++) {
-                $utf8_dn = Horde_String::convertCharset($result[$i]['dn'], 'UTF-8', $current_charset);
-                $groups[$utf8_dn] = $this->getGroupName($utf8_dn);
-            }
+        // Perform search
+        try {
+            $search = $this->_ldap->search($this->_params['basedn'], $filter);
+        } catch (Horde_Ldap_Exception $e) {
+            throw new Horde_Group_Exception($e);
+        }
 
-            $cache[$user] = $groups;
+        $this->_userCache[$user] = array();
+        $current_charset = $GLOBALS['registry']->getCharset();
+        foreach ($search as $dn => $entry) {
+            $utf8_dn = Horde_String::convertCharset($dn, 'UTF-8', $current_charset);
+            $this->_userCache[$user][$utf8_dn] = $this->getGroupName($utf8_dn);
         }
 
-        return $cache[$user];
+        return $this->_userCache[$user];
     }
 
     /**
index 0feddd0..e07d223 100644 (file)
  */
 class Horde_Group_LdapObject extends Horde_Group_DataTreeObject
 {
-    /**
-     * Constructor.
-     *
-     * @param string $name    The name of this group.
-     * @param string $parent  The dn of the parent of this group.
-     */
-    public function __construct($name, $parent = null)
+    protected $_entry;
+
+    public function getEntry()
     {
-        // FIXME!!!!
-        $conf = Horde::getDriverConfig('group', 'ldap');
-        parent::__construct($name);
-        if ($parent) {
-            $this->data['dn'] = Horde_String::lower($conf['gid']) . '=' . $name . ',' . $parent;
-        } else {
-            $this->data['dn'] = Horde_String::lower($conf['gid']) . '=' . $name .
-                ',' . Horde_String::lower($conf['basedn']);
-        }
+        return $this->_entry;
+    }
+
+    public function setEntry(Horde_Ldap_Entry $entry)
+    {
+        $this->_entry = $entry;
+        $this->fromAttributes(array('dn' => $entry->dn()) + $entry->getValues());
     }
 
     /**