Upcase server class names.
authorGunnar Wrobel <p@rdus.de>
Mon, 30 Mar 2009 04:38:34 +0000 (04:38 +0000)
committerGunnar Wrobel <p@rdus.de>
Wed, 1 Apr 2009 07:23:09 +0000 (07:23 +0000)
13 files changed:
framework/Kolab_Server/lib/Horde/Kolab/Server.php
framework/Kolab_Server/lib/Horde/Kolab/Server/File.php [new file with mode: 0644]
framework/Kolab_Server/lib/Horde/Kolab/Server/Ldap.php [new file with mode: 0644]
framework/Kolab_Server/lib/Horde/Kolab/Server/Test.php [new file with mode: 0644]
framework/Kolab_Server/lib/Horde/Kolab/Server/file.php [deleted file]
framework/Kolab_Server/lib/Horde/Kolab/Server/ldap.php [deleted file]
framework/Kolab_Server/lib/Horde/Kolab/Server/test.php [deleted file]
framework/Kolab_Server/package.xml
framework/Kolab_Server/test/Horde/Kolab/Server/LdapTest.php [new file with mode: 0644]
framework/Kolab_Server/test/Horde/Kolab/Server/ServerTest.php
framework/Kolab_Server/test/Horde/Kolab/Server/TestTest.php [new file with mode: 0644]
framework/Kolab_Server/test/Horde/Kolab/Server/ldapTest.php [deleted file]
framework/Kolab_Server/test/Horde/Kolab/Server/testTest.php [deleted file]

index 5cbb1eb..a8091ad 100644 (file)
@@ -90,7 +90,7 @@ abstract class Horde_Kolab_Server
      */
     static public function &factory($driver, $params = array())
     {
-        $class = 'Horde_Kolab_Server_' . basename($driver);
+        $class = 'Horde_Kolab_Server_' . ucfirst(basename($driver));
         if (class_exists($class)) {
             $db = new $class($params);
             return $db;
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/File.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/File.php
new file mode 100644 (file)
index 0000000..6a32d5a
--- /dev/null
@@ -0,0 +1,115 @@
+<?php
+/**
+ * A persistent file-based driver for simulating a Kolab user database stored in
+ * LDAP.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package  Kolab_Server
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * This class provides a persistant class for testing the Kolab Server DB.
+ *
+ * Copyright 2008-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Kolab
+ * @package  Kolab_Server
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_File extends Horde_Kolab_Server_Test
+{
+
+    /**
+     * The file for storing the database data.
+     *
+     * @var string
+     */
+    private $_file;
+
+    /**
+     * Construct a new Horde_Kolab_Server object.
+     *
+     * @param array $params Parameter array.
+     */
+    public function __construct($params = array())
+    {
+        if (isset($params['file'])) {
+            $this->_file = $params['file'];
+        } else {
+            $this->_file = Horde::getTempFile('Horde_Kolab_Server', false);
+        }
+        parent::__construct($params);
+    }
+
+    
+    /**
+     * Load the current state of the database.
+     *
+     * @return NULL
+     */
+    protected function load()
+    {
+        $raw_data = file_get_contents($this->_file);
+        if (!$raw_data === false) {
+            $data = @unserialize($raw_data);
+            if ($data !== false) {
+                $this->data = $data;
+            } else {
+                $error = error_get_last();
+                Horde::logMessage(sprintf('Horde_Kolab_Server_file failed to read the database from %s. Error was: %s',
+                                          $this->_file, $error['message']), __FILE__,
+                                  __LINE__, PEAR_LOG_WARNING);
+                $this->data = array();
+            }
+        }
+    }
+
+    /**
+     * Store the current state of the database.
+     *
+     * @return NULL
+     */
+    protected function store()
+    {
+        $raw_data = serialize($this->data);
+        $result = @file_put_contents($this->_file, $raw_data);
+        if ($result === false) {
+            $error = error_get_last();
+            Horde::logMessage(sprintf('Horde_Kolab_Server_file failed to store the database in %s. Error was: %s',
+                                      $this->_file,  $error['message']), __FILE__,
+                              __LINE__, PEAR_LOG_WARNING);
+        }
+    }
+
+    /**
+     * Cleans the current state of the database.
+     *
+     * @return NULL
+     */
+    public function clean()
+    {
+        unlink($this->_file);
+        $this->data = array();
+        $this->store();
+    }
+
+    /**
+     * Returns the path to the storage location of the database.
+     *
+     * @return string The path to the database.
+     */
+    public function getStoragePAth()
+    {
+        return $this->_file;
+    }
+}
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Ldap.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Ldap.php
new file mode 100644 (file)
index 0000000..becf7c3
--- /dev/null
@@ -0,0 +1,937 @@
+<?php
+/**
+ * The driver for accessing the Kolab user database stored in LDAP.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package  Kolab_Server
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * This class provides methods to deal with Kolab objects stored in
+ * the standard Kolab LDAP db.
+ *
+ * Copyright 2008-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Kolab
+ * @package  Kolab_Server
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Ldap extends Horde_Kolab_Server
+{
+
+    /**
+     * The object types supported by this server type.
+     */
+    const USER  = 'kolabInetOrgPerson';
+    const GROUP = 'kolabGroupOfNames';
+
+    /**
+     * LDAP connection handle.
+     *
+     * @var Net_LDAP2
+     */
+    private $_ldap;
+
+    /**
+     * Base DN of the LDAP server.
+     *
+     * @var string
+     */
+    private $_base_dn;
+
+    /**
+     * Construct a new Horde_Kolab_Server_ldap object.
+     *
+     * @param array $params Parameter array.
+     */
+    public function __construct($params = array())
+    {
+        if (!isset($params['charset'])) {
+            $params['charset'] = 'UTF-8';
+        }
+
+        $base_config = array('host'           => 'localhost',
+                             'port'           => 389,
+                             'version'        => 3,
+                             'starttls'       => false,
+                             'uid'            => '',
+                             'pass'           => '',
+                             'basedn'         => '',
+                             'charset'        => '',
+                             'options'        => array(),
+                             'auto_reconnect' => true);
+
+
+        $config = array_merge($base_config, $params);
+
+        $this->_base_dn = $config['basedn'];
+
+        $config['binddn'] = $config['uid'];
+        $config['bindpw'] = $config['pass'];
+
+       $this->connect();
+
+        parent::__construct($params);
+    }
+
+    
+    /**
+     * Connect to the LDAP server.
+     *
+     * @return NULL.
+     *
+     * @throws Horde_Kolab_Server_Exception If the connection failed.
+     */
+    protected function connect()
+    {
+        $this->_ldap = Net_LDAP2::connect($config);
+        if (is_a($this->_ldap, 'PEAR_Error')) {
+            throw new Horde_Kolab_Server_Exception($this->_ldap);
+        }
+    }
+
+    /**
+     * Read object data.
+     *
+     * @param string $dn    The object to retrieve.
+     * @param string $attrs Restrict to these attributes.
+     *
+     * @return array|boolean An array of attributes or false if the specified
+     *                       object was not found.
+     *
+     * @throws Horde_Kolab_Server_Exception If the search operation retrieved a
+     *                                      problematic result.
+     */
+    public function read($dn, $attrs = null)
+    {
+        $params = array('scope' => 'base');
+        if (!empty($attrs)) {
+            $params['attributes'] = $attrs;
+        }
+
+        $data = $this->search(null, $params, $dn);
+        if (empty($data)) {
+            throw new Horde_Kolab_Server_Exception(_("Empty result!"));
+        }            
+
+        if (!isset($data[$dn])) {
+            throw new Horde_Kolab_Server_Exception(sprintf(_("No result found for %s"),
+                                                           $dn));
+        }
+        if (is_a($data[$dn], 'PEAR_Error')) {
+            throw new Horde_Kolab_Server_Exception($data[$dn]);
+        }
+        return $data[$dn];
+    }
+
+    /**
+     * Determine the type of a Kolab object.
+     *
+     * @param string $dn The DN of the object to examine.
+     *
+     * @return int The corresponding Kolab object type.
+     *
+     * @throws Horde_Kolab_Server_Exception If the object type is unknown.
+     */
+    public function determineType($dn)
+    {
+        $oc = $this->getObjectClasses($dn);
+        // Not a user type?
+        if (!in_array('kolabinetorgperson', $oc)) {
+            // Is it a group?
+            if (in_array('kolabgroupofnames', $oc)) {
+                return 'Horde_Kolab_Server_Object_group';
+            }
+            // Is it a shared Folder?
+            if (in_array('kolabsharedfolder', $oc)) {
+                return 'Horde_Kolab_Server_Object_sharedfolder';
+            }
+            throw new Horde_Kolab_Server_Exception(sprintf(_("Unkown Kolab object type for DN %s."),
+                                                           $dn));
+        }
+
+        $groups = $this->getGroups($dn);
+        if (!empty($groups)) {
+            if (in_array('cn=admin,cn=internal,' . $this->_base_dn, $groups)) {
+                return 'Horde_Kolab_Server_Object_administrator';
+            }
+            if (in_array('cn=maintainer,cn=internal,' . $this->_base_dn,
+                         $groups)) {
+                return 'Horde_Kolab_Server_Object_maintainer';
+            }
+            if (in_array('cn=domain-maintainer,cn=internal,' . $this->_base_dn,
+                         $groups)) {
+                return 'Horde_Kolab_Server_Object_domainmaintainer';
+            }
+        }
+
+        if (strpos($dn, 'cn=external') !== false) {
+            return 'Horde_Kolab_Server_Object_address';
+        }
+
+        return 'Horde_Kolab_Server_Object_user';
+    }
+
+    /**
+     * List all objects of a specific type
+     *
+     * @param string $type   The type of the objects to be listed
+     * @param array  $params Additional parameters.
+     *
+     * @return array An array of Kolab objects.
+     *
+     * @throws Horde_Kolab_Server_Exception
+     *
+     * @todo Sorting
+     */
+    public function listObjects($type, $params = null)
+    {
+        if (empty($params['base_dn'])) {
+            $base = $this->_base_dn;
+        } else {
+            $base = $params['base_dn'];
+        }
+
+        $result = Horde_Kolab_Server_Object::loadClass($type);
+        $vars   = get_class_vars($type);
+        $filter = call_user_func(array($type, 'getFilter'));
+        $sort   = $vars['sort_by'];
+
+        if (isset($params['sort'])) {
+            $sort = $params['sort'];
+        }
+
+        $options = array('scope' => 'sub');
+        if (isset($params['attributes'])) {
+            $options['attributes'] = $params['attributes'];
+        } else {
+            $options['attributes'] = $vars['_supported_attributes'];
+        }
+
+        $result = $this->search($filter, $options, $base);
+        if (empty($result)) {
+            return array();
+        }
+
+        if ($sort) {
+            /* FIXME */
+            /*$this->sort($result, $sort); */
+        }
+
+        if (isset($params['from'])) {
+            $from = $params['from'];
+        } else {
+            $from = -1;
+        }
+
+        if (isset($params['to'])) {
+            $sort = $params['to'];
+        } else {
+            $to = -1;
+        }
+
+        $entries = array();
+        foreach ($result as $entry) {
+            $entries[] = $entry['dn'];
+        }
+
+        if (!empty($vars['required_group'])) {
+            $required_group = $this->fetch($vars['required_group'],
+                                           'Horde_Kolab_Server_Object_group');
+        }
+
+        $objects = array();
+        foreach ($entries as $dn) {
+            if (!empty($vars['required_group']) && $required_group->isMember($dn)) {
+                continue;
+            }
+            $result    = $this->fetch($dn, $type);
+            $objects[$dn] = $result;
+        }
+        return $objects;
+    }
+
+    /**
+     * Generates a UID for the given information.
+     *
+     * @param string $type The type of the object to create.
+     * @param string $id   The id of the object.
+     * @param array  $info Any additional information about the object to create.
+     *
+     * @return string The DN.
+     *
+     * @throws Horde_Kolab_Server_Exception If the given type is unknown.
+     */
+    public function generateServerUid($type, $id, $info)
+    {
+        switch ($type) {
+        case 'Horde_Kolab_Server_Object_user':
+            if (!isset($info['user_type']) || $info['user_type'] == 0) {
+                return sprintf('cn=%s,%s', $id, $this->_base_dn);
+            } else if ($info['user_type'] == Horde_Kolab_Server_Object_user::USERTYPE_INTERNAL) {
+                return sprintf('cn=%s,cn=internal,%s', $id, $this->_base_dn);
+            } else if ($info['user_type'] == Horde_Kolab_Server_Object_user::USERTYPE_GROUP) {
+                return sprintf('cn=%s,cn=groups,%s', $id, $this->_base_dn);
+            } else if ($info['user_type'] == Horde_Kolab_Server_Object_user::USERTYPE_RESOURCE) {
+                return sprintf('cn=%s,cn=resources,%s', $id, $this->_base_dn);
+            } else {
+                return sprintf('cn=%s,%s', $id, $this->_base_dn);
+            }
+        case 'Horde_Kolab_Server_Object_address':
+            return sprintf('cn=%s,cn=external,%s', $id, $this->_base_dn);
+        case 'Horde_Kolab_Server_Object_sharedfolder':
+        case 'Horde_Kolab_Server_Object_administrator':
+        case 'Horde_Kolab_Server_Object_maintainer':
+        case 'Horde_Kolab_Server_Object_domainmaintainer':
+            return sprintf('cn=%s,%s', $id, $this->_base_dn);
+        case 'Horde_Kolab_Server_Object_group':
+        case 'Horde_Kolab_Server_Object_distlist':
+            if (!isset($info['visible']) || !empty($info['visible'])) {
+                return sprintf('cn=%s,%s', $id, $this->_base_dn);
+            } else {
+                return sprintf('cn=%s,cn=internal,%s', $id, $this->_base_dn);
+            }
+        default:
+            throw new Horde_Kolab_Server_Exception(_("Not implemented!"));
+        }
+    }
+
+    /**
+     * Return the root of the UID values on this server.
+     *
+     * @return string The base UID on this server (base DN on ldap).
+     */
+    public function getBaseUid()
+    {
+        return $this->_base_dn;
+    }
+
+    /**
+     * Save an object.
+     *
+     * @param string $dn   The DN of the object.
+     * @param array  $data The data for the object.
+     *
+     * @return boolean True if successfull.
+     *
+     * @throws Horde_Kolab_Server_Exception If the given type is unknown.
+     */
+    function save($dn, $data)
+    {
+        $result = $this->_add($dn, $data);
+        if (!$result  && $this->_errno()) {
+            throw new Horde_Kolab_Server_Exception(sprintf(_("Failed saving object. Error was: %s"),
+                                                           $this->_error()));
+        }
+    }
+
+    /**
+     * Identify the UID for the first object found using the specified
+     * search criteria.
+     *
+     * @param array $criteria The search parameters as array.
+     * @param int   $restrict A Horde_Kolab_Server::RESULT_* result restriction.
+     *
+     * @return boolean|string|array The UID(s) or false if there was no result.
+     *
+     * @throws Horde_Kolab_Server_Exception
+     */
+    public function uidForSearch($criteria,
+                                 $restrict = Horde_Kolab_Server::RESULT_SINGLE)
+    {
+        $users = array('field' => 'objectClass',
+                       'op'    => '=',
+                       'test'  => self::USER);
+        if (!empty($criteria)) {
+            $criteria = array('AND' => array($users, $criteria));
+        } else {
+            $criteria = array('AND' => array($users));
+        }
+
+        $filter = $this->searchQuery($criteria);
+        return $this->dnForFilter($filter, $restrict);
+    }
+
+    /**
+     * Identify the GID for the first group found using the specified
+     * search criteria
+     *
+     * @param array $criteria The search parameters as array.
+     * @param int   $restrict A Horde_Kolab_Server::RESULT_* result restriction.
+     *
+     * @return boolean|string|array The GID(s) or false if there was no result.
+     *
+     * @throws Horde_Kolab_Server_Exception
+     */
+    public function gidForSearch($criteria,
+                                 $restrict = Horde_Kolab_Server::RESULT_SINGLE)
+    {
+        $groups = array('field' => 'objectClass',
+                        'op'    => '=',
+                        'test'  => self::GROUP);
+        if (!empty($criteria)) {
+            $criteria = array('AND' => array($groups, $criteria));
+        } else {
+            $criteria = array('AND' => array($groups));
+        }
+
+        $filter = $this->searchQuery($criteria);
+        return $this->dnForFilter($filter, $restrict);
+    }
+
+    /**
+     * Identify attributes for the objects found using a filter.
+     *
+     * @param array $criteria The search parameters as array.
+     * @param array $attrs    The attributes to retrieve.
+     * @param int   $restrict A Horde_Kolab_Server::RESULT_* result restriction.
+     *
+     * @return array The results.
+     *
+     * @throws Horde_Kolab_Server_Exception
+     */
+    public function attrsForSearch($criteria, $attrs,
+                                   $restrict = Horde_Kolab_Server::RESULT_SINGLE)
+    {
+        $params = array('attributes' => $attrs);
+        $filter = $this->searchQuery($criteria);
+        $result = $this->search($filter, $params, $this->_base_dn);
+        return $this->attrsFromResult($result, $attrs, $restrict);
+    }
+
+    /**
+     * Search for object data.
+     *
+     * @param string $filter The LDAP search filter.
+     * @param string $params Additional search parameters.
+     * @param string $base   The search base
+     *
+     * @return array The result array.
+     *
+     * @throws Horde_Kolab_Server_Exception If the search operation encountered
+     *                                      a problem.
+     */
+    public function search($filter = null, $params = array(), $base = null)
+    {
+        if (!isset($base)) {
+            $base = $this->_base_dn;
+        }
+        $result = $this->_ldap->search($base, $filter, $params);
+        if (is_a($result, 'PEAR_Error')) {
+            throw new Horde_Kolab_Server_Exception($result->getMessage());
+        }
+        return $result->as_struct();
+    }
+
+    /**
+     * Get the LDAP object classes for the given DN.
+     *
+     * @param string $dn DN of the object.
+     *
+     * @return array An array of object classes.
+     *
+     * @throws Horde_Kolab_Server_Exception If the object has no
+     *                                      object classes.
+     */
+    public function getObjectClasses($dn)
+    {
+        $object = $this->read($dn, array('objectClass'));
+        if (!isset($object['objectClass'])) {
+            throw new Horde_Kolab_Server_Exception(sprintf(_("The object %s has no object classes!"),
+                                                           $dn));
+        }
+        $result = array_map('strtolower', $object['objectClass']);
+        return $result;
+    }
+
+    /**
+     * Build a search query.
+     *
+     * Taken from the Turba LDAP driver.
+     *
+     * @param array $criteria The array of criteria.
+     *
+     * @return string  An LDAP query filter.
+     */
+    protected function searchQuery($criteria)
+    {
+        /* Build the LDAP filter. */
+        $filter = '';
+        if (count($criteria)) {
+            foreach ($criteria as $key => $vals) {
+                if ($key == 'OR') {
+                    $filter .= '(|' . $this->buildSearchQuery($vals) . ')';
+                } elseif ($key == 'AND') {
+                    $filter .= '(&' . $this->buildSearchQuery($vals) . ')';
+                }
+            }
+        } else {
+            /* Accept everything. */
+            $filter = '(objectclass=*)';
+        }
+
+        /* Add source-wide filters, which are _always_ AND-ed. */
+        if (!empty($this->params['filter'])) {
+            $filter = '(&' . '(' . $this->params['filter'] . ')' . $filter . ')';
+        }
+        return $filter;
+    }
+
+    /**
+     * Build a piece of a search query.
+     *
+     * Taken from the Turba LDAP driver.
+     *
+     * @param array $criteria The array of criteria.
+     *
+     * @return string  An LDAP query fragment.
+     */
+    protected function buildSearchQuery($criteria)
+    {
+        $clause = '';
+        foreach ($criteria as $key => $vals) {
+            if (!empty($vals['OR'])) {
+                $clause .= '(|' . $this->buildSearchQuery($vals) . ')';
+            } elseif (!empty($vals['AND'])) {
+                $clause .= '(&' . $this->buildSearchQuery($vals) . ')';
+            } else {
+                if (isset($vals['field'])) {
+                    require_once 'Horde/String.php';
+                    require_once 'Horde/NLS.php';
+                    $rhs     = String::convertCharset($vals['test'], NLS::getCharset(), $this->params['charset']);
+                    $clause .= Horde_LDAP::buildClause($vals['field'], $vals['op'], $rhs, array('begin' => !empty($vals['begin'])));
+                } else {
+                    foreach ($vals as $test) {
+                        if (!empty($test['OR'])) {
+                            $clause .= '(|' . $this->buildSearchQuery($test) . ')';
+                        } elseif (!empty($test['AND'])) {
+                            $clause .= '(&' . $this->buildSearchQuery($test) . ')';
+                        } else {
+                            $rhs     = String::convertCharset($test['test'], NLS::getCharset(), $this->params['charset']);
+                            $clause .= Horde_LDAP::buildClause($test['field'], $test['op'], $rhs, array('begin' => !empty($vals['begin'])));
+                        }
+                    }
+                }
+            }
+        }
+
+        return $clause;
+    }
+
+    /**
+     * Identify the DN of the first result entry.
+     *
+     * @param array $result   The LDAP search result.
+     * @param int   $restrict A Horde_Kolab_Server::RESULT_* result restriction.
+     *
+     * @return boolean|string|array The DN(s) or false if there was no result.
+     *
+     * @throws Horde_Kolab_Server_Exception If the number of results did not
+     *                                      meet the expectations.
+     */
+    protected function dnFromResult($result,
+                                    $restrict = Horde_Kolab_Server::RESULT_SINGLE)
+    {
+        if (empty($result)) {
+            return false;
+        }
+        $dns = array_keys($result);
+
+        switch ($restrict) {
+        case self::RESULT_STRICT:
+            if (count($dns) > 1) {
+                throw new Horde_Kolab_Server_Exception(sprintf(_("Found %s results when expecting only one!"),
+                                                               $count));
+            }
+        case self::RESULT_SINGLE:
+            return $dns[0];
+        case self::RESULT_MANY:
+            return $dns;
+        }
+    }
+
+    /**
+     * Get the attributes of the first result entry.
+     *
+     * @param array $result   The LDAP search result.
+     * @param array $attrs    The attributes to retrieve.
+     * @param int   $restrict A Horde_Kolab_Server::RESULT_* result restriction.
+     *
+     * @return array The DN.
+     *
+     * @throws Horde_Kolab_Server_Exception If the number of results did not
+     *                                      meet the expectations.
+     */
+    protected function attrsFromResult($result, $attrs,
+                                       $restrict = Horde_Kolab_Server::RESULT_SINGLE)
+    {
+        switch ($restrict) {
+        case self::RESULT_STRICT:
+            if (count($result) > 1) {
+                throw new Horde_Kolab_Server_Exception(sprintf(_("Found %s results when expecting only one!"),
+                                                               $count));
+            }
+        case self::RESULT_SINGLE:
+            if (count($result) > 0) {
+                return $result[0];
+            }
+            return array();
+        case self::RESULT_MANY:
+            return $result;
+        }
+        return array();
+    }
+
+
+    /**
+     * Identify the DN for the first object found using a filter.
+     *
+     * @param string $filter   The LDAP filter to use.
+     * @param int    $restrict A Horde_Kolab_Server::RESULT_* result restriction.
+     *
+     * @return boolean|string|array The DN(s) or false if there was no result.
+     *
+     * @throws Horde_Kolab_Server_Exception
+     */
+    protected function dnForFilter($filter,
+                                   $restrict = Horde_Kolab_Server::RESULT_SINGLE)
+    {
+        $params = array('attributes' => 'dn');
+        $result = $this->search($filter, $params, $this->_base_dn);
+        return $this->dnFromResult($result, $restrict);
+    }
+
+    /**
+     * Identify the UID for the first object found with the given ID.
+     *
+     * @param string $id       Search for objects with this ID.
+     * @param int    $restrict A Horde_Kolab_Server::RESULT_* result restriction.
+     *
+     * @return mixed The UID or false if there was no result.
+     *
+     * @throws Horde_Kolab_Server_Exception
+     */
+    public function uidForId($id,
+                             $restrict = Horde_Kolab_Server::RESULT_SINGLE)
+    {
+        $criteria = array('AND' => array(array('field' => 'uid',
+                                               'op'    => '=',
+                                               'test'  => $id),
+                          ),
+        );
+        return $this->uidForSearch($criteria, $restrict);
+    }
+
+    /**
+     * Identify the UID for the first user found with the given mail.
+     *
+     * @param string $mail     Search for users with this mail address.
+     * @param int    $restrict A Horde_Kolab_Server::RESULT_* result restriction.
+     *
+     * @return mixed The UID or false if there was no result.
+     *
+     * @throws Horde_Kolab_Server_Exception
+     */
+    public function uidForMail($mail,
+                               $restrict = Horde_Kolab_Server::RESULT_SINGLE)
+    {
+        $criteria = array('AND' => array(array('field' => 'mail',
+                                              'op'    => '=',
+                                              'test'  => $mail),
+                         ),
+        );
+        return $this->uidForSearch($criteria, $restrict);
+    }
+
+    /**
+     * Identify the UID for the first object found with the given alias.
+     *
+     * @param string $mail     Search for objects with this mail alias.
+     * @param int    $restrict A Horde_Kolab_Server::RESULT_* result restriction.
+     *
+     * @return mixed The UID or false if there was no result.
+     *
+     * @throws Horde_Kolab_Server_Exception
+     */
+    public function uidForAlias($mail,
+                                $restrict = Horde_Kolab_Server::RESULT_SINGLE)
+    {
+        $criteria = array('AND' => array(array('field' => 'alias',
+                                              'op'    => '=',
+                                              'test'  => $mail),
+                         ),
+        );
+        return $this->uidForSearch($criteria, $restrict);
+    }
+
+    /**
+     * Identify the UID for the first object found with the given ID or mail.
+     *
+     * @param string $id Search for objects with this uid/mail.
+     *
+     * @return string|boolean The UID or false if there was no result.
+     *
+     * @throws Horde_Kolab_Server_Exception
+     */
+    public function uidForIdOrMail($id)
+    {
+        $criteria = array('OR' =>
+                         array(
+                             array('field' => 'uid',
+                                   'op'    => '=',
+                                   'test'  => $id),
+                             array('field' => 'mail',
+                                   'op'    => '=',
+                                   'test'  => $id),
+                         ),
+        );
+        return $this->uidForSearch($criteria);
+    }
+
+    /**
+     * Identify the UID for the first object found with the given mail
+     * address or alias.
+     *
+     * @param string $mail Search for objects with this mail address
+     * or alias.
+     *
+     * @return string|boolean The UID or false if there was no result.
+     *
+     * @throws Horde_Kolab_Server_Exception
+     */
+    public function uidForMailOrAlias($mail)
+    {
+        $criteria = array('OR' =>
+                         array(
+                             array('field' => 'alias',
+                                   'op'    => '=',
+                                   'test'  => $mail),
+                             array('field' => 'mail',
+                                   'op'    => '=',
+                                   'test'  => $mail),
+                         )
+        );
+        return $this->uidForSearch($criteria);
+    }
+
+    /**
+     * Identify the UID for the first object found with the given ID,
+     * mail or alias.
+     *
+     * @param string $id Search for objects with this ID/mail/alias.
+     *
+     * @return string|boolean The UID or false if there was no result.
+     *
+     * @throws Horde_Kolab_Server_Exception
+     */
+    public function uidForIdOrMailOrAlias($id)
+    {
+        $criteria = array('OR' =>
+                         array(
+                             array('field' => 'alias',
+                                   'op'    => '=',
+                                   'test'  => $id),
+                             array('field' => 'mail',
+                                   'op'    => '=',
+                                   'test'  => $id),
+                             array('field' => 'uid',
+                                   'op'    => '=',
+                                   'test'  => $id),
+                         ),
+        );
+        return $this->uidForSearch($criteria);
+    }
+
+    /**
+     * Identify the primary mail attribute for the first object found
+     * with the given ID or mail.
+     *
+     * @param string $id Search for objects with this ID/mail.
+     *
+     * @return mixed The mail address or false if there was no result.
+     *
+     * @throws Horde_Kolab_Server_Exception
+     */
+    public function mailForIdOrMail($id)
+    {
+        $criteria = array('AND' =>
+                         array(
+                             array('field' => 'objectClass',
+                                   'op'    => '=',
+                                   'test'  => self::USER),
+                             array('OR' =>
+                                   array(
+                                       array('field' => 'uid',
+                                             'op'    => '=',
+                                             'test'  => $id),
+                                       array('field' => 'mail',
+                                             'op'    => '=',
+                                             'test'  => $id),
+                                   ),
+                             ),
+                         ),
+        );
+
+        $data = $this->attrsForSearch($criteria, array('mail'),
+                                      self::RESULT_STRICT);
+        if (!empty($data)) {
+            return $data['mail'][0];
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Returns a list of allowed email addresses for the given user.
+     *
+     * @param string $id Search for objects with this ID/mail.
+     *
+     * @return array An array of allowed mail addresses.
+     *
+     * @throws Horde_Kolab_Server_Exception
+     */
+    public function addrsForIdOrMail($id)
+    {
+        $criteria = array('AND' =>
+                         array(
+                             array('field' => 'objectClass',
+                                   'op'    => '=',
+                                   'test'  => self::USER),
+                             array('OR' =>
+                                   array(
+                                       array('field' => 'uid',
+                                             'op'    => '=',
+                                             'test'  => $id),
+                                       array('field' => 'mail',
+                                             'op'    => '=',
+                                             'test'  => $id),
+                                   ),
+                             ),
+                         ),
+        );
+
+        $result = $this->attrsForSearch($criteria, array('mail', 'alias'),
+                                        self::RESULT_STRICT);
+        if (isset($result['alias'])) {
+            $addrs = array_merge((array) $result['mail'], (array) $result['alias']);
+        } else {
+            $addrs = $result['mail'];
+        }
+
+        if (empty($result)) {
+            return array();
+        }
+        $criteria = array('AND' =>
+                         array(
+                             array('field' => 'objectClass',
+                                   'op'    => '=',
+                                   'test'  => self::USER),
+                             array('field' => 'kolabDelegate',
+                                   'op'    => '=',
+                                   'test'  => $result['mail'][0]),
+                         ),
+        );
+
+        $result = $this->attrsForSearch($criteria, array('mail', 'alias'),
+                                      self::RESULT_MANY);
+        if (!empty($result)) {
+            foreach ($result as $adr) {
+                if (isset($adr['mail'])) {
+                    $addrs = array_merge((array) $addrs, (array) $adr['mail']);
+                }
+                if (isset($adr['alias'])) {
+                    $addrs = array_merge((array) $addrs, (array) $adr['alias']);
+                }
+            }
+        }
+
+        $addrs = array_map('strtolower', $addrs);
+
+        return $addrs;
+    }
+
+    /**
+     * Identify the GID for the first group found with the given mail.
+     *
+     * @param string $mail     Search for groups with this mail address.
+     * @param int    $restrict A Horde_Kolab_Server::RESULT_* result restriction.
+     *
+     * @return mixed The GID or false if there was no result.
+     *
+     * @throws Horde_Kolab_Server_Exception
+     */
+    public function gidForMail($mail,
+                               $restrict = Horde_Kolab_Server::RESULT_SINGLE)
+    {
+        $criteria = array('AND' => array(array('field' => 'mail',
+                                              'op'    => '=',
+                                              'test'  => $mail),
+                         ),
+        );
+        return $this->gidForSearch($criteria, $restrict);
+    }
+
+    /**
+     * Is the given UID member of the group with the given mail address?
+     *
+     * @param string $uid  UID of the user.
+     * @param string $mail Search the group with this mail address.
+     *
+     * @return boolean True in case the user is in the group, false otherwise.
+     *
+     * @throws Horde_Kolab_Server_Exception
+     */
+    public function memberOfGroupAddress($uid, $mail)
+    {
+        $criteria = array('AND' =>
+                          array(
+                              array('field' => 'mail',
+                                    'op'    => '=',
+                                    'test'  => $mail),
+                              array('field' => 'member',
+                                    'op'    => '=',
+                                    'test'  => $uid),
+                          ),
+        );
+
+        $result = $this->gidForSearch($criteria,
+                                      self::RESULT_SINGLE);
+        return !empty($result);
+    }
+
+    /**
+     * Get the groups for this object.
+     *
+     * @param string $uid The UID of the object to fetch.
+     *
+     * @return array An array of group ids.
+     *
+     * @throws Horde_Kolab_Server_Exception
+     */
+    public function getGroups($uid)
+    {
+        $criteria = array('AND' =>
+                          array(
+                              array('field' => 'member',
+                                    'op'    => '=',
+                                    'test'  => $uid),
+                          ),
+        );
+
+        $result = $this->gidForSearch($criteria, self::RESULT_MANY);
+        if (empty($result)) {
+            return array();
+        }
+        return $result;
+    }
+}
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Test.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Test.php
new file mode 100644 (file)
index 0000000..8f907b8
--- /dev/null
@@ -0,0 +1,715 @@
+<?php
+/**
+ * A driver for simulating a Kolab user database stored in LDAP.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package  Kolab_Server
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * This class provides a class for testing the Kolab Server DB.
+ *
+ * Copyright 2008-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Kolab
+ * @package  Kolab_Server
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Test extends Horde_Kolab_Server_Ldap
+{
+
+    /**
+     * The current database data.
+     *
+     * @var array
+     */
+    protected $data;
+
+    /**
+     * Indicates if we are bound.
+     *
+     * @var array
+     */
+    protected $bound;
+
+    /**
+     * Array holding the current result set.
+     *
+     * @var array
+     */
+    private $_result;
+
+    /**
+     * Buffer for error numbers.
+     *
+     * @var int
+     */
+    private $_errno = 0;
+
+    /**
+     * Buffer for error descriptions.
+     *
+     * @var int
+     */
+    private $_error = '';
+
+    /**
+     * Attribute used for sorting.
+     *
+     * @var string
+     */
+    private $_sort_by;
+
+    /**
+     * A result cache for iterating over the result.
+     *
+     * @var array
+     */
+    private $_current_result;
+
+    /**
+     * An index into the current result for iterating.
+     *
+     * @var int
+     */
+    private $_current_index;
+
+    /**
+     * Construct a new Horde_Kolab_Server object.
+     *
+     * @param array $params Parameter array.
+     */
+    public function __construct($params = array())
+    {
+        $this->load();
+        if (isset($params['data'])) {
+            $this->data = $params['data'];
+        } else {
+            if (!isset($this->data)) {
+               $this->data  = array();
+            }
+        }
+
+        parent::__construct($params);
+
+        if (isset($this->params['adminuser'])
+            && isset($this->params['adminpass'])) {
+            $base_dn = isset($this->params['basedn']) ? ',' . $this->params['basedn'] : '';
+            $dn = 'cn=' . $this->params['adminuser'] . ',cn=internal' . $base_dn;
+            if (!isset($this->data[$dn])) {
+                $ldap_data = array(
+                    'cn' => array('manager'),
+                    'sn' => array('n/a'),
+                    'uid' => array('manager'),
+                    'userPassword' => array($this->params['adminpass']),
+                    'objectClass' => array('top','inetOrgPerson','kolabInetOrgPerson')
+                );
+                $this->data[$dn] = array(
+                    'dn' => $dn,
+                    'data' => $ldap_data
+                );
+            }
+        }
+
+        $this->store();
+    }
+
+    /**
+     * Connect to the server.
+     *
+     * @return NULL.
+     *
+     * @throws Horde_Kolab_Server_Exception If the connection failed.
+     */
+    protected function connect()
+    {
+    }
+
+    /**
+     * Load the current state of the database.
+     *
+     * @return NULL
+     */
+    protected function load()
+    {
+        if (isset($GLOBALS['KOLAB_SERVER_TEST_DATA'])) {
+            $this->data = $GLOBALS['KOLAB_SERVER_TEST_DATA'];
+        } else {
+            $this->data = array();
+        }
+    }
+
+    /**
+     * Store the current state of the database.
+     *
+     * @return NULL
+     */
+    protected function store()
+    {
+        $GLOBALS['KOLAB_SERVER_TEST_DATA'] = $this->data;
+    }
+
+    /**
+     * Cleans the current state of the database.
+     *
+     * @return NULL
+     */
+    public function clean()
+    {
+        $this->unbind();
+
+        $GLOBALS['KOLAB_SERVER_TEST_DATA'] = array();
+
+        $this->data = array();
+    }
+
+    /**
+     * Binds the LDAP connection with a specific user and pass.
+     *
+     * @param string $dn DN to bind with
+     * @param string $pw Password associated to this DN.
+     *
+     * @return boolean Whether or not the binding succeeded.
+     *
+     * @throws Horde_Kolab_Server_Exception If the user does not exit, he has no
+     *                                      password, provided an incorrect
+     *                                      password or anonymous binding is not
+     *                                      allowed.
+     */
+    protected function bind($dn = false, $pw = '')
+    {
+        if (!$dn) {
+            if (isset($this->params['uid'])) {
+                $dn = $this->params['uid'];
+            } else {
+                $dn = '';
+            }
+        }
+        if (!$pw) {
+            if (isset($this->params['pass'])) {
+                $pw = $this->params['pass'];
+            }
+        }
+
+        if (!empty($dn)) {
+            if (!isset($this->data[$dn])) {
+                throw new Horde_Kolab_Server_Exception('User does not exist!');
+            }
+
+            $this->bound = true;
+
+            try {
+                $data = $this->read($dn, array('userPassword'));
+            } catch (Horde_Kolab_Server_Exception $e) {
+                $this->bound = false;
+                throw $e;
+            }
+            if (!isset($data['userPassword'])) {
+                $this->bound = false;
+                throw new Horde_Kolab_Server_Exception('User has no password entry!');
+            }
+            $this->bound = $data['userPassword'][0] == $pw;
+            if (!$this->bound) {
+                throw new Horde_Kolab_Server_Exception('Incorrect password!');
+            }
+        } else if (!empty($this->params['no_anonymous_bind'])) {
+            $this->bound = false;
+            throw new Horde_Kolab_Server_Exception('Anonymous bind is not allowed!');
+        } else {
+            $this->bound = true;
+        }
+        return $this->bound;
+    }
+
+    /**
+     * Disconnect from LDAP.
+     *
+     * @return NULL
+     */
+    public function unbind()
+    {
+        $this->bound = false;
+    }
+
+    /**
+     * Parse LDAP filter.
+     * Partially derived from Net_LDAP_Filter.
+     *
+     * @param string $filter The filter string.
+     *
+     * @return array An array of the parsed filter.
+     *
+     * @throws Horde_Kolab_Server_Exception If parsing the filter expression
+     *                                      fails.
+     */
+    public function parse($filter)
+    {
+        $result = array();
+        if (preg_match('/^\((.+?)\)$/', $filter, $matches)) {
+            if (in_array(substr($matches[1], 0, 1), array('!', '|', '&'))) {
+                $result['op']  = substr($matches[1], 0, 1);
+                $result['sub'] = $this->parseSub(substr($matches[1], 1));
+                return $result;
+            } else {
+                if (stristr($matches[1], ')(')) {
+                    throw new Horde_Kolab_Server_Exception('Filter parsing error: invalid filter syntax - multiple leaf components detected!');
+                } else {
+                    $filter_parts = preg_split('/(?<!\\\\)(=|=~|>|<|>=|<=)/',
+                                               $matches[1], 2,
+                                               PREG_SPLIT_DELIM_CAPTURE);
+                    if (count($filter_parts) != 3) {
+                        throw new Horde_Kolab_Server_Exception('Filter parsing error: invalid filter syntax - unknown matching rule used');
+                    } else {
+                        $result['att'] = $filter_parts[0];
+                        $result['log'] = $filter_parts[1];
+                        $result['val'] = $filter_parts[2];
+                        return $result;
+                    }
+                }
+            }
+        } else {
+            throw new Horde_Kolab_Server_Exception(sprintf("Filter parsing error: %s - filter components must be enclosed in round brackets",
+                                                           $filter));
+        }
+    }
+
+    /**
+     * Parse a LDAP subfilter.
+     *
+     * @param string $filter The subfilter string.
+     *
+     * @return array An array of the parsed subfilter.
+     *
+     * @throws Horde_Kolab_Server_Exception
+     */
+    public function parseSub($filter)
+    {
+        $result  = array();
+        $level   = 0;
+        $collect = '';
+        while (preg_match('/^(\(.+?\))(.*)/', $filter, $matches)) {
+            if (in_array(substr($matches[1], 0, 2), array('(!', '(|', '(&'))) {
+                $level++;
+            }
+            if ($level) {
+                $collect .= $matches[1];
+                if (substr($matches[2], 0, 1) == ')') {
+                    $collect   .= ')';
+                    $matches[2] = substr($matches[2], 1);
+                    $level--;
+                    if (!$level) {
+                        $result[] = $this->parse($collect);
+                    }
+                }
+            } else {
+                $result[] = $this->parse($matches[1]);
+            }
+            $filter = $matches[2];
+        }
+        return $result;
+    }
+
+    /**
+     * Search for object data.
+     *
+     * @param string $filter The LDAP search filter.
+     * @param string $params Additional search parameters.
+     * @param string $base   The search base
+     *
+     * @return array The result array.
+     *
+     * @throws Horde_Kolab_Server_Exception If the search operation encountered
+     *                                      a problem.
+     */
+    public function search($filter = null, $params = array(), $base = null)
+    {
+        if (!$this->bound) {
+            $result = $this->bind();
+        }
+
+        $filter = $this->parse($filter);
+        if (isset($params['attributes'])) {
+            $attributes = $params['attributes'];
+            if (!is_array($attributes)) {
+                $attributes = array($attributes);
+            }
+        } else {
+            $attributes = array();
+        }
+        $result = $this->doSearch($filter, $attributes);
+        if (empty($result)) {
+            return null;
+        }
+        if ($base) {
+            $subtree = array();
+            foreach ($result as $entry) {
+                if (strpos($entry['dn'], $base)) {
+                    $subtree[] = $entry;
+                }
+            }
+            $result = $subtree;
+        }
+        return $this->getEntries($result);
+    }
+
+    /**
+     * Perform the search.
+     *
+     * @param array $filter     Filter criteria-
+     * @param array $attributes Restrict the search result to
+     *                          these attributes.
+     *
+     * @return array A LDAP serach result.
+     *
+     * @throws Horde_Kolab_Server_Exception If the search operation is not
+     *                                      available.
+     */
+    protected function doSearch($filter, $attributes = null)
+    {
+        if (isset($filter['log'])) {
+            $result = array();
+            foreach ($this->data as $element) {
+                if (isset($element['data'][$filter['att']])) {
+                    switch ($filter['log']) {
+                    case '=':
+                        $value = $element['data'][$filter['att']];
+                        if (($filter['val'] == '*' && !empty($value))
+                            || $value == $filter['val']
+                            || (is_array($value)
+                                && in_array($filter['val'], $value))) {
+                            if (empty($attributes)) {
+                                $result[] = $element;
+                            } else {
+                                $selection = $element;
+                                foreach ($element['data'] as $attr => $value) {
+                                    if (!in_array($attr, $attributes)) {
+                                        unset($selection['data'][$attr]);
+                                    }
+                                }
+                                $result[] = $selection;
+                            }
+                        }
+                        break;
+                    default:
+                        throw new Horde_Kolab_Server_Exception(_("Not implemented!"));
+                    }
+                }
+            }
+            return $result;
+        } else {
+            $subresult   = array();
+            $filtercount = count($filter['sub']);
+            foreach ($filter['sub'] as $subfilter) {
+                $subresult = array_merge($subresult,
+                                         $this->doSearch($subfilter,
+                                                         $attributes));
+            }
+            $result = array();
+            $dns    = array();
+            foreach ($subresult as $element) {
+                $dns[] = $element['dn'];
+
+                $result[$element['dn']] = $element;
+            }
+            switch ($filter['op']) {
+            case '&':
+                $count     = array_count_values($dns);
+                $selection = array();
+                foreach ($count as $dn => $value) {
+                    if ($value == $filtercount) {
+                        $selection[] = $result[$dn];
+                    }
+                }
+                return $selection;
+            case '|':
+                return array_values($result);
+            case '!':
+                $dns = array();
+                foreach ($result as $entry) {
+                    if (!in_array($entry['dn'], $dns) ) {
+                        $dns[] = $entry['dn'];
+                    }
+                }
+                $all_dns = array_keys($this->data);
+                $diff    = array_diff($all_dns, $dns);
+
+                $result = array();
+                foreach ($diff as $dn) {
+                    if (empty($attributes)) {
+                        $result[] = $this->data[$dn];
+                    } else {
+                        $selection = $this->data[$dn];
+                        foreach ($this->data[$dn]['data']
+                                 as $attr => $value) {
+                            if (!in_array($attr, $attributes)) {
+                                unset($selection['data'][$attr]);
+                            }
+                        }
+                        $result[] = $selection;
+                    }
+                }
+                return $result;
+            default:
+                throw new Horde_Kolab_Server_Exception(_("Not implemented!"));
+            }
+        }
+    }
+
+    /**
+     * Read object data.
+     *
+     * @param string $dn    The object to retrieve.
+     * @param string $attrs Restrict to these attributes
+     *
+     * @return array An array of attributes.
+     *
+     * @throws Horde_Kolab_Server_Exception If the object does not exist.
+     */
+    public function read($dn, $attrs = null)
+    {
+        if (!$this->bound) {
+            $result = $this->bind();
+        }
+
+        if (!isset($this->data[$dn])) {
+            throw new Horde_Kolab_Server_MissingObjectException(sprintf("No such object: %s",
+                                                                        $dn));
+        }
+        if (empty($attrs)) {
+            return $this->data[$dn]['data'];
+        } else {
+            $result = array();
+            $data   = $this->data[$dn]['data'];
+
+            foreach ($attrs as $attr) {
+                if (isset($data[$attr])) {
+                    $result[$attr] = $data[$attr];
+                    array_push($result, $attr);
+                }
+            }
+            return $result;
+        }
+    }
+
+    /**
+     * Add a new object
+     *
+     * @param string $dn   The DN of the object to be added.
+     * @param array  $data The attributes of the object to be added.
+     *
+     * @return boolean  True if adding succeeded.
+     */
+    public function save($dn, $data)
+    {
+        if (!$this->bound) {
+            $result = $this->bind();
+        }
+
+        $ldap_data = array();
+        foreach ($data as $key => $val) {
+            if (!is_array($val)) {
+                $val = array($val);
+            }
+            $ldap_data[$key] = $val;
+        }
+
+        $this->data[$dn] = array(
+            'dn' => $dn,
+            'data' => $ldap_data
+        );
+        $this->store();
+    }
+
+    /**
+     * Return the attributes of an entry.
+     *
+     * @param array $entry The LDAP entry.
+     *
+     * @return array  The attributes of the entry.
+     */
+    protected function getAttributes($entry)
+    {
+        if (is_array($entry)) {
+            return $entry;
+        }
+        return false;
+    }
+
+    /**
+     * Return the current entry of a result.
+     *
+     * @return mixe  The current entry of the result or false.
+     */
+    protected function fetchEntry()
+    {
+        if (is_array($this->_current_result)
+            && $this->_current_index < count($this->_current_result)) {
+
+            $data = array_keys($this->_current_result[$this->_current_index]['data']);
+
+            $data['dn'] = array($this->_current_result[$this->_current_index]['dn']);
+
+            foreach ($this->_current_result[$this->_current_index]['data']
+                     as $attr => $value) {
+                if (!is_array($value)) {
+                    $value = array($value);
+                }
+                $data[$attr] = $value;
+            }
+            $this->_current_index++;
+            return $data;
+        }
+        return false;
+    }
+
+    /**
+     * Return the first entry of a result.
+     *
+     * @param array $result The LDAP search result.
+     *
+     * @return mixed The first entry of the result or false.
+     */
+    protected function firstEntry($result)
+    {
+        $this->_current_result = $result;
+        $this->_current_index  = 0;
+        return $this->fetchEntry();
+    }
+
+    /**
+     * Return the next entry of a result.
+     *
+     * @param resource $entry The current LDAP entry.
+     *
+     * @return resource The next entry of the result.
+     */
+    protected function nextEntry($entry)
+    {
+        return $this->fetchEntry();
+    }
+
+    /**
+     * Return the entries of a result.
+     *
+     * @param array $result The LDAP search result.
+     *
+     * @return mixed The entries of the result or false.
+     */
+    protected function getEntries($result)
+    {
+        if (is_array($result)) {
+            $data = array();
+            foreach ($result as $entry) {
+                $t       = $entry['data'];
+                $t['dn'] = $entry['dn'];
+                $data[]  = $t;
+            }
+            return $data;
+        }
+        return false;
+    }
+
+    /**
+     * Sort the entries of a result.
+     *
+     * @param resource &$result   The LDAP search result.
+     * @param string   $attribute The attribute used for sorting.
+     *
+     * @return boolean  True if sorting succeeded.
+     */
+    public function sort(&$result, $attribute)
+    {
+        if (empty($result)) {
+            return $result;
+        }
+
+        $this->_sort_by = $attribute;
+        usort($result, array($this, 'resultSort'));
+        return false;
+    }
+
+    /**
+     * Sort two entries.
+     *
+     * @param array $a First entry.
+     * @param array $b Second entry.
+     *
+     * @return int  Comparison result.
+     */
+    protected function resultSort($a, $b)
+    {
+        $x = isset($a['data'][$this->_sort_by][0])?$a['data'][$this->_sort_by][0]:'';
+        $y = isset($b['data'][$this->_sort_by][0])?$b['data'][$this->_sort_by][0]:'';
+        return strcasecmp($x, $y);
+    }
+
+
+    /**
+     * Return the current LDAP error number.
+     *
+     * @return int  The current LDAP error number.
+     */
+    protected function errno()
+    {
+        return $this->_errno;
+    }
+
+    /**
+     * Return the current LDAP error description.
+     *
+     * @return string  The current LDAP error description.
+     */
+    protected function error()
+    {
+        return $this->_error;
+    }
+
+    /**
+     * Identify the DN of the first result entry.
+     *
+     * @todo Check if this could be reintegrated with the code in the LDAP handler
+     *       again.
+     *
+     * @param array $result   The LDAP search result.
+     * @param int   $restrict A Horde_Kolab_Server::RESULT_* result restriction.
+     *
+     * @return boolean|string|array The DN(s) or false if there was no result.
+     *
+     * @throws Horde_Kolab_Server_Exception If the number of results did not
+     *                                      meet the expectations.
+     */
+    protected function dnFromResult($result,
+                                    $restrict = Horde_Kolab_Server::RESULT_SINGLE)
+    {
+        if (empty($result)) {
+            return false;
+        }
+        $dns = array();
+        foreach ($result as $entry) {
+            $dns[] = $entry['dn'];
+        }
+
+        switch ($restrict) {
+        case self::RESULT_STRICT:
+            if (count($dns) > 1) {
+                throw new Horde_Kolab_Server_Exception(sprintf(_("Found %s results when expecting only one!"),
+                                                               $count));
+            }
+        case self::RESULT_SINGLE:
+            return $dns[0];
+        case self::RESULT_MANY:
+            return $dns;
+        }
+    }
+
+}
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/file.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/file.php
deleted file mode 100644 (file)
index 6d087ff..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-<?php
-/**
- * A persistent file-based driver for simulating a Kolab user database stored in
- * LDAP.
- *
- * PHP version 5
- *
- * @category Kolab
- * @package  Kolab_Server
- * @author   Gunnar Wrobel <wrobel@pardus.de>
- * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
- * @link     http://pear.horde.org/index.php?package=Kolab_Server
- */
-
-/**
- * This class provides a persistant class for testing the Kolab Server DB.
- *
- * Copyright 2008-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
- *
- * @category Kolab
- * @package  Kolab_Server
- * @author   Gunnar Wrobel <wrobel@pardus.de>
- * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
- * @link     http://pear.horde.org/index.php?package=Kolab_Server
- */
-class Horde_Kolab_Server_file extends Horde_Kolab_Server_test
-{
-
-    /**
-     * The file for storing the database data.
-     *
-     * @var string
-     */
-    private $_file;
-
-    /**
-     * Construct a new Horde_Kolab_Server object.
-     *
-     * @param array $params Parameter array.
-     */
-    public function __construct($params = array())
-    {
-        if (isset($params['file'])) {
-            $this->_file = $params['file'];
-        } else {
-            $this->_file = Horde::getTempFile('Horde_Kolab_Server', false);
-        }
-        parent::__construct($params);
-    }
-
-    
-    /**
-     * Load the current state of the database.
-     *
-     * @return NULL
-     */
-    protected function load()
-    {
-        $raw_data = file_get_contents($this->_file);
-        if (!$raw_data === false) {
-            $data = @unserialize($raw_data);
-            if ($data !== false) {
-                $this->data = $data;
-            } else {
-                $error = error_get_last();
-                Horde::logMessage(sprintf('Horde_Kolab_Server_file failed to read the database from %s. Error was: %s',
-                                          $this->_file, $error['message']), __FILE__,
-                                  __LINE__, PEAR_LOG_WARNING);
-                $this->data = array();
-            }
-        }
-    }
-
-    /**
-     * Store the current state of the database.
-     *
-     * @return NULL
-     */
-    protected function store()
-    {
-        $raw_data = serialize($this->data);
-        $result = @file_put_contents($this->_file, $raw_data);
-        if ($result === false) {
-            $error = error_get_last();
-            Horde::logMessage(sprintf('Horde_Kolab_Server_file failed to store the database in %s. Error was: %s',
-                                      $this->_file,  $error['message']), __FILE__,
-                              __LINE__, PEAR_LOG_WARNING);
-        }
-    }
-
-    /**
-     * Cleans the current state of the database.
-     *
-     * @return NULL
-     */
-    public function clean()
-    {
-        unlink($this->_file);
-        $this->data = array();
-        $this->store();
-    }
-
-    /**
-     * Returns the path to the storage location of the database.
-     *
-     * @return string The path to the database.
-     */
-    public function getStoragePAth()
-    {
-        return $this->_file;
-    }
-}
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/ldap.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/ldap.php
deleted file mode 100644 (file)
index e261cbe..0000000
+++ /dev/null
@@ -1,937 +0,0 @@
-<?php
-/**
- * The driver for accessing the Kolab user database stored in LDAP.
- *
- * PHP version 5
- *
- * @category Kolab
- * @package  Kolab_Server
- * @author   Gunnar Wrobel <wrobel@pardus.de>
- * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
- * @link     http://pear.horde.org/index.php?package=Kolab_Server
- */
-
-/**
- * This class provides methods to deal with Kolab objects stored in
- * the standard Kolab LDAP db.
- *
- * Copyright 2008-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
- *
- * @category Kolab
- * @package  Kolab_Server
- * @author   Gunnar Wrobel <wrobel@pardus.de>
- * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
- * @link     http://pear.horde.org/index.php?package=Kolab_Server
- */
-class Horde_Kolab_Server_ldap extends Horde_Kolab_Server
-{
-
-    /**
-     * The object types supported by this server type.
-     */
-    const USER  = 'kolabInetOrgPerson';
-    const GROUP = 'kolabGroupOfNames';
-
-    /**
-     * LDAP connection handle.
-     *
-     * @var Net_LDAP2
-     */
-    private $_ldap;
-
-    /**
-     * Base DN of the LDAP server.
-     *
-     * @var string
-     */
-    private $_base_dn;
-
-    /**
-     * Construct a new Horde_Kolab_Server_ldap object.
-     *
-     * @param array $params Parameter array.
-     */
-    public function __construct($params = array())
-    {
-        if (!isset($params['charset'])) {
-            $params['charset'] = 'UTF-8';
-        }
-
-        $base_config = array('host'           => 'localhost',
-                             'port'           => 389,
-                             'version'        => 3,
-                             'starttls'       => false,
-                             'uid'            => '',
-                             'pass'           => '',
-                             'basedn'         => '',
-                             'charset'        => '',
-                             'options'        => array(),
-                             'auto_reconnect' => true);
-
-
-        $config = array_merge($base_config, $params);
-
-        $this->_base_dn = $config['basedn'];
-
-        $config['binddn'] = $config['uid'];
-        $config['bindpw'] = $config['pass'];
-
-       $this->connect();
-
-        parent::__construct($params);
-    }
-
-    
-    /**
-     * Connect to the LDAP server.
-     *
-     * @return NULL.
-     *
-     * @throws Horde_Kolab_Server_Exception If the connection failed.
-     */
-    protected function connect()
-    {
-        $this->_ldap = Net_LDAP2::connect($config);
-        if (is_a($this->_ldap, 'PEAR_Error')) {
-            throw new Horde_Kolab_Server_Exception($this->_ldap);
-        }
-    }
-
-    /**
-     * Read object data.
-     *
-     * @param string $dn    The object to retrieve.
-     * @param string $attrs Restrict to these attributes.
-     *
-     * @return array|boolean An array of attributes or false if the specified
-     *                       object was not found.
-     *
-     * @throws Horde_Kolab_Server_Exception If the search operation retrieved a
-     *                                      problematic result.
-     */
-    public function read($dn, $attrs = null)
-    {
-        $params = array('scope' => 'base');
-        if (!empty($attrs)) {
-            $params['attributes'] = $attrs;
-        }
-
-        $data = $this->search(null, $params, $dn);
-        if (empty($data)) {
-            throw new Horde_Kolab_Server_Exception(_("Empty result!"));
-        }            
-
-        if (!isset($data[$dn])) {
-            throw new Horde_Kolab_Server_Exception(sprintf(_("No result found for %s"),
-                                                           $dn));
-        }
-        if (is_a($data[$dn], 'PEAR_Error')) {
-            throw new Horde_Kolab_Server_Exception($data[$dn]);
-        }
-        return $data[$dn];
-    }
-
-    /**
-     * Determine the type of a Kolab object.
-     *
-     * @param string $dn The DN of the object to examine.
-     *
-     * @return int The corresponding Kolab object type.
-     *
-     * @throws Horde_Kolab_Server_Exception If the object type is unknown.
-     */
-    public function determineType($dn)
-    {
-        $oc = $this->getObjectClasses($dn);
-        // Not a user type?
-        if (!in_array('kolabinetorgperson', $oc)) {
-            // Is it a group?
-            if (in_array('kolabgroupofnames', $oc)) {
-                return 'Horde_Kolab_Server_Object_group';
-            }
-            // Is it a shared Folder?
-            if (in_array('kolabsharedfolder', $oc)) {
-                return 'Horde_Kolab_Server_Object_sharedfolder';
-            }
-            throw new Horde_Kolab_Server_Exception(sprintf(_("Unkown Kolab object type for DN %s."),
-                                                           $dn));
-        }
-
-        $groups = $this->getGroups($dn);
-        if (!empty($groups)) {
-            if (in_array('cn=admin,cn=internal,' . $this->_base_dn, $groups)) {
-                return 'Horde_Kolab_Server_Object_administrator';
-            }
-            if (in_array('cn=maintainer,cn=internal,' . $this->_base_dn,
-                         $groups)) {
-                return 'Horde_Kolab_Server_Object_maintainer';
-            }
-            if (in_array('cn=domain-maintainer,cn=internal,' . $this->_base_dn,
-                         $groups)) {
-                return 'Horde_Kolab_Server_Object_domainmaintainer';
-            }
-        }
-
-        if (strpos($dn, 'cn=external') !== false) {
-            return 'Horde_Kolab_Server_Object_address';
-        }
-
-        return 'Horde_Kolab_Server_Object_user';
-    }
-
-    /**
-     * List all objects of a specific type
-     *
-     * @param string $type   The type of the objects to be listed
-     * @param array  $params Additional parameters.
-     *
-     * @return array An array of Kolab objects.
-     *
-     * @throws Horde_Kolab_Server_Exception
-     *
-     * @todo Sorting
-     */
-    public function listObjects($type, $params = null)
-    {
-        if (empty($params['base_dn'])) {
-            $base = $this->_base_dn;
-        } else {
-            $base = $params['base_dn'];
-        }
-
-        $result = Horde_Kolab_Server_Object::loadClass($type);
-        $vars   = get_class_vars($type);
-        $filter = call_user_func(array($type, 'getFilter'));
-        $sort   = $vars['sort_by'];
-
-        if (isset($params['sort'])) {
-            $sort = $params['sort'];
-        }
-
-        $options = array('scope' => 'sub');
-        if (isset($params['attributes'])) {
-            $options['attributes'] = $params['attributes'];
-        } else {
-            $options['attributes'] = $vars['_supported_attributes'];
-        }
-
-        $result = $this->search($filter, $options, $base);
-        if (empty($result)) {
-            return array();
-        }
-
-        if ($sort) {
-            /* FIXME */
-            /*$this->sort($result, $sort); */
-        }
-
-        if (isset($params['from'])) {
-            $from = $params['from'];
-        } else {
-            $from = -1;
-        }
-
-        if (isset($params['to'])) {
-            $sort = $params['to'];
-        } else {
-            $to = -1;
-        }
-
-        $entries = array();
-        foreach ($result as $entry) {
-            $entries[] = $entry['dn'];
-        }
-
-        if (!empty($vars['required_group'])) {
-            $required_group = $this->fetch($vars['required_group'],
-                                           'Horde_Kolab_Server_Object_group');
-        }
-
-        $objects = array();
-        foreach ($entries as $dn) {
-            if (!empty($vars['required_group']) && $required_group->isMember($dn)) {
-                continue;
-            }
-            $result    = $this->fetch($dn, $type);
-            $objects[$dn] = $result;
-        }
-        return $objects;
-    }
-
-    /**
-     * Generates a UID for the given information.
-     *
-     * @param string $type The type of the object to create.
-     * @param string $id   The id of the object.
-     * @param array  $info Any additional information about the object to create.
-     *
-     * @return string The DN.
-     *
-     * @throws Horde_Kolab_Server_Exception If the given type is unknown.
-     */
-    public function generateServerUid($type, $id, $info)
-    {
-        switch ($type) {
-        case 'Horde_Kolab_Server_Object_user':
-            if (!isset($info['user_type']) || $info['user_type'] == 0) {
-                return sprintf('cn=%s,%s', $id, $this->_base_dn);
-            } else if ($info['user_type'] == Horde_Kolab_Server_Object_user::USERTYPE_INTERNAL) {
-                return sprintf('cn=%s,cn=internal,%s', $id, $this->_base_dn);
-            } else if ($info['user_type'] == Horde_Kolab_Server_Object_user::USERTYPE_GROUP) {
-                return sprintf('cn=%s,cn=groups,%s', $id, $this->_base_dn);
-            } else if ($info['user_type'] == Horde_Kolab_Server_Object_user::USERTYPE_RESOURCE) {
-                return sprintf('cn=%s,cn=resources,%s', $id, $this->_base_dn);
-            } else {
-                return sprintf('cn=%s,%s', $id, $this->_base_dn);
-            }
-        case 'Horde_Kolab_Server_Object_address':
-            return sprintf('cn=%s,cn=external,%s', $id, $this->_base_dn);
-        case 'Horde_Kolab_Server_Object_sharedfolder':
-        case 'Horde_Kolab_Server_Object_administrator':
-        case 'Horde_Kolab_Server_Object_maintainer':
-        case 'Horde_Kolab_Server_Object_domainmaintainer':
-            return sprintf('cn=%s,%s', $id, $this->_base_dn);
-        case 'Horde_Kolab_Server_Object_group':
-        case 'Horde_Kolab_Server_Object_distlist':
-            if (!isset($info['visible']) || !empty($info['visible'])) {
-                return sprintf('cn=%s,%s', $id, $this->_base_dn);
-            } else {
-                return sprintf('cn=%s,cn=internal,%s', $id, $this->_base_dn);
-            }
-        default:
-            throw new Horde_Kolab_Server_Exception(_("Not implemented!"));
-        }
-    }
-
-    /**
-     * Return the root of the UID values on this server.
-     *
-     * @return string The base UID on this server (base DN on ldap).
-     */
-    public function getBaseUid()
-    {
-        return $this->_base_dn;
-    }
-
-    /**
-     * Save an object.
-     *
-     * @param string $dn   The DN of the object.
-     * @param array  $data The data for the object.
-     *
-     * @return boolean True if successfull.
-     *
-     * @throws Horde_Kolab_Server_Exception If the given type is unknown.
-     */
-    function save($dn, $data)
-    {
-        $result = $this->_add($dn, $data);
-        if (!$result  && $this->_errno()) {
-            throw new Horde_Kolab_Server_Exception(sprintf(_("Failed saving object. Error was: %s"),
-                                                           $this->_error()));
-        }
-    }
-
-    /**
-     * Identify the UID for the first object found using the specified
-     * search criteria.
-     *
-     * @param array $criteria The search parameters as array.
-     * @param int   $restrict A Horde_Kolab_Server::RESULT_* result restriction.
-     *
-     * @return boolean|string|array The UID(s) or false if there was no result.
-     *
-     * @throws Horde_Kolab_Server_Exception
-     */
-    public function uidForSearch($criteria,
-                                 $restrict = Horde_Kolab_Server::RESULT_SINGLE)
-    {
-        $users = array('field' => 'objectClass',
-                       'op'    => '=',
-                       'test'  => self::USER);
-        if (!empty($criteria)) {
-            $criteria = array('AND' => array($users, $criteria));
-        } else {
-            $criteria = array('AND' => array($users));
-        }
-
-        $filter = $this->searchQuery($criteria);
-        return $this->dnForFilter($filter, $restrict);
-    }
-
-    /**
-     * Identify the GID for the first group found using the specified
-     * search criteria
-     *
-     * @param array $criteria The search parameters as array.
-     * @param int   $restrict A Horde_Kolab_Server::RESULT_* result restriction.
-     *
-     * @return boolean|string|array The GID(s) or false if there was no result.
-     *
-     * @throws Horde_Kolab_Server_Exception
-     */
-    public function gidForSearch($criteria,
-                                 $restrict = Horde_Kolab_Server::RESULT_SINGLE)
-    {
-        $groups = array('field' => 'objectClass',
-                        'op'    => '=',
-                        'test'  => self::GROUP);
-        if (!empty($criteria)) {
-            $criteria = array('AND' => array($groups, $criteria));
-        } else {
-            $criteria = array('AND' => array($groups));
-        }
-
-        $filter = $this->searchQuery($criteria);
-        return $this->dnForFilter($filter, $restrict);
-    }
-
-    /**
-     * Identify attributes for the objects found using a filter.
-     *
-     * @param array $criteria The search parameters as array.
-     * @param array $attrs    The attributes to retrieve.
-     * @param int   $restrict A Horde_Kolab_Server::RESULT_* result restriction.
-     *
-     * @return array The results.
-     *
-     * @throws Horde_Kolab_Server_Exception
-     */
-    public function attrsForSearch($criteria, $attrs,
-                                   $restrict = Horde_Kolab_Server::RESULT_SINGLE)
-    {
-        $params = array('attributes' => $attrs);
-        $filter = $this->searchQuery($criteria);
-        $result = $this->search($filter, $params, $this->_base_dn);
-        return $this->attrsFromResult($result, $attrs, $restrict);
-    }
-
-    /**
-     * Search for object data.
-     *
-     * @param string $filter The LDAP search filter.
-     * @param string $params Additional search parameters.
-     * @param string $base   The search base
-     *
-     * @return array The result array.
-     *
-     * @throws Horde_Kolab_Server_Exception If the search operation encountered
-     *                                      a problem.
-     */
-    public function search($filter = null, $params = array(), $base = null)
-    {
-        if (!isset($base)) {
-            $base = $this->_base_dn;
-        }
-        $result = $this->_ldap->search($base, $filter, $params);
-        if (is_a($result, 'PEAR_Error')) {
-            throw new Horde_Kolab_Server_Exception($result->getMessage());
-        }
-        return $result->as_struct();
-    }
-
-    /**
-     * Get the LDAP object classes for the given DN.
-     *
-     * @param string $dn DN of the object.
-     *
-     * @return array An array of object classes.
-     *
-     * @throws Horde_Kolab_Server_Exception If the object has no
-     *                                      object classes.
-     */
-    public function getObjectClasses($dn)
-    {
-        $object = $this->read($dn, array('objectClass'));
-        if (!isset($object['objectClass'])) {
-            throw new Horde_Kolab_Server_Exception(sprintf(_("The object %s has no object classes!"),
-                                                           $dn));
-        }
-        $result = array_map('strtolower', $object['objectClass']);
-        return $result;
-    }
-
-    /**
-     * Build a search query.
-     *
-     * Taken from the Turba LDAP driver.
-     *
-     * @param array $criteria The array of criteria.
-     *
-     * @return string  An LDAP query filter.
-     */
-    protected function searchQuery($criteria)
-    {
-        /* Build the LDAP filter. */
-        $filter = '';
-        if (count($criteria)) {
-            foreach ($criteria as $key => $vals) {
-                if ($key == 'OR') {
-                    $filter .= '(|' . $this->buildSearchQuery($vals) . ')';
-                } elseif ($key == 'AND') {
-                    $filter .= '(&' . $this->buildSearchQuery($vals) . ')';
-                }
-            }
-        } else {
-            /* Accept everything. */
-            $filter = '(objectclass=*)';
-        }
-
-        /* Add source-wide filters, which are _always_ AND-ed. */
-        if (!empty($this->params['filter'])) {
-            $filter = '(&' . '(' . $this->params['filter'] . ')' . $filter . ')';
-        }
-        return $filter;
-    }
-
-    /**
-     * Build a piece of a search query.
-     *
-     * Taken from the Turba LDAP driver.
-     *
-     * @param array $criteria The array of criteria.
-     *
-     * @return string  An LDAP query fragment.
-     */
-    protected function buildSearchQuery($criteria)
-    {
-        $clause = '';
-        foreach ($criteria as $key => $vals) {
-            if (!empty($vals['OR'])) {
-                $clause .= '(|' . $this->buildSearchQuery($vals) . ')';
-            } elseif (!empty($vals['AND'])) {
-                $clause .= '(&' . $this->buildSearchQuery($vals) . ')';
-            } else {
-                if (isset($vals['field'])) {
-                    require_once 'Horde/String.php';
-                    require_once 'Horde/NLS.php';
-                    $rhs     = String::convertCharset($vals['test'], NLS::getCharset(), $this->params['charset']);
-                    $clause .= Horde_LDAP::buildClause($vals['field'], $vals['op'], $rhs, array('begin' => !empty($vals['begin'])));
-                } else {
-                    foreach ($vals as $test) {
-                        if (!empty($test['OR'])) {
-                            $clause .= '(|' . $this->buildSearchQuery($test) . ')';
-                        } elseif (!empty($test['AND'])) {
-                            $clause .= '(&' . $this->buildSearchQuery($test) . ')';
-                        } else {
-                            $rhs     = String::convertCharset($test['test'], NLS::getCharset(), $this->params['charset']);
-                            $clause .= Horde_LDAP::buildClause($test['field'], $test['op'], $rhs, array('begin' => !empty($vals['begin'])));
-                        }
-                    }
-                }
-            }
-        }
-
-        return $clause;
-    }
-
-    /**
-     * Identify the DN of the first result entry.
-     *
-     * @param array $result   The LDAP search result.
-     * @param int   $restrict A Horde_Kolab_Server::RESULT_* result restriction.
-     *
-     * @return boolean|string|array The DN(s) or false if there was no result.
-     *
-     * @throws Horde_Kolab_Server_Exception If the number of results did not
-     *                                      meet the expectations.
-     */
-    protected function dnFromResult($result,
-                                    $restrict = Horde_Kolab_Server::RESULT_SINGLE)
-    {
-        if (empty($result)) {
-            return false;
-        }
-        $dns = array_keys($result);
-
-        switch ($restrict) {
-        case self::RESULT_STRICT:
-            if (count($dns) > 1) {
-                throw new Horde_Kolab_Server_Exception(sprintf(_("Found %s results when expecting only one!"),
-                                                               $count));
-            }
-        case self::RESULT_SINGLE:
-            return $dns[0];
-        case self::RESULT_MANY:
-            return $dns;
-        }
-    }
-
-    /**
-     * Get the attributes of the first result entry.
-     *
-     * @param array $result   The LDAP search result.
-     * @param array $attrs    The attributes to retrieve.
-     * @param int   $restrict A Horde_Kolab_Server::RESULT_* result restriction.
-     *
-     * @return array The DN.
-     *
-     * @throws Horde_Kolab_Server_Exception If the number of results did not
-     *                                      meet the expectations.
-     */
-    protected function attrsFromResult($result, $attrs,
-                                       $restrict = Horde_Kolab_Server::RESULT_SINGLE)
-    {
-        switch ($restrict) {
-        case self::RESULT_STRICT:
-            if (count($result) > 1) {
-                throw new Horde_Kolab_Server_Exception(sprintf(_("Found %s results when expecting only one!"),
-                                                               $count));
-            }
-        case self::RESULT_SINGLE:
-            if (count($result) > 0) {
-                return $result[0];
-            }
-            return array();
-        case self::RESULT_MANY:
-            return $result;
-        }
-        return array();
-    }
-
-
-    /**
-     * Identify the DN for the first object found using a filter.
-     *
-     * @param string $filter   The LDAP filter to use.
-     * @param int    $restrict A Horde_Kolab_Server::RESULT_* result restriction.
-     *
-     * @return boolean|string|array The DN(s) or false if there was no result.
-     *
-     * @throws Horde_Kolab_Server_Exception
-     */
-    protected function dnForFilter($filter,
-                                   $restrict = Horde_Kolab_Server::RESULT_SINGLE)
-    {
-        $params = array('attributes' => 'dn');
-        $result = $this->search($filter, $params, $this->_base_dn);
-        return $this->dnFromResult($result, $restrict);
-    }
-
-    /**
-     * Identify the UID for the first object found with the given ID.
-     *
-     * @param string $id       Search for objects with this ID.
-     * @param int    $restrict A Horde_Kolab_Server::RESULT_* result restriction.
-     *
-     * @return mixed The UID or false if there was no result.
-     *
-     * @throws Horde_Kolab_Server_Exception
-     */
-    public function uidForId($id,
-                             $restrict = Horde_Kolab_Server::RESULT_SINGLE)
-    {
-        $criteria = array('AND' => array(array('field' => 'uid',
-                                               'op'    => '=',
-                                               'test'  => $id),
-                          ),
-        );
-        return $this->uidForSearch($criteria, $restrict);
-    }
-
-    /**
-     * Identify the UID for the first user found with the given mail.
-     *
-     * @param string $mail     Search for users with this mail address.
-     * @param int    $restrict A Horde_Kolab_Server::RESULT_* result restriction.
-     *
-     * @return mixed The UID or false if there was no result.
-     *
-     * @throws Horde_Kolab_Server_Exception
-     */
-    public function uidForMail($mail,
-                               $restrict = Horde_Kolab_Server::RESULT_SINGLE)
-    {
-        $criteria = array('AND' => array(array('field' => 'mail',
-                                              'op'    => '=',
-                                              'test'  => $mail),
-                         ),
-        );
-        return $this->uidForSearch($criteria, $restrict);
-    }
-
-    /**
-     * Identify the UID for the first object found with the given alias.
-     *
-     * @param string $mail     Search for objects with this mail alias.
-     * @param int    $restrict A Horde_Kolab_Server::RESULT_* result restriction.
-     *
-     * @return mixed The UID or false if there was no result.
-     *
-     * @throws Horde_Kolab_Server_Exception
-     */
-    public function uidForAlias($mail,
-                                $restrict = Horde_Kolab_Server::RESULT_SINGLE)
-    {
-        $criteria = array('AND' => array(array('field' => 'alias',
-                                              'op'    => '=',
-                                              'test'  => $mail),
-                         ),
-        );
-        return $this->uidForSearch($criteria, $restrict);
-    }
-
-    /**
-     * Identify the UID for the first object found with the given ID or mail.
-     *
-     * @param string $id Search for objects with this uid/mail.
-     *
-     * @return string|boolean The UID or false if there was no result.
-     *
-     * @throws Horde_Kolab_Server_Exception
-     */
-    public function uidForIdOrMail($id)
-    {
-        $criteria = array('OR' =>
-                         array(
-                             array('field' => 'uid',
-                                   'op'    => '=',
-                                   'test'  => $id),
-                             array('field' => 'mail',
-                                   'op'    => '=',
-                                   'test'  => $id),
-                         ),
-        );
-        return $this->uidForSearch($criteria);
-    }
-
-    /**
-     * Identify the UID for the first object found with the given mail
-     * address or alias.
-     *
-     * @param string $mail Search for objects with this mail address
-     * or alias.
-     *
-     * @return string|boolean The UID or false if there was no result.
-     *
-     * @throws Horde_Kolab_Server_Exception
-     */
-    public function uidForMailOrAlias($mail)
-    {
-        $criteria = array('OR' =>
-                         array(
-                             array('field' => 'alias',
-                                   'op'    => '=',
-                                   'test'  => $mail),
-                             array('field' => 'mail',
-                                   'op'    => '=',
-                                   'test'  => $mail),
-                         )
-        );
-        return $this->uidForSearch($criteria);
-    }
-
-    /**
-     * Identify the UID for the first object found with the given ID,
-     * mail or alias.
-     *
-     * @param string $id Search for objects with this ID/mail/alias.
-     *
-     * @return string|boolean The UID or false if there was no result.
-     *
-     * @throws Horde_Kolab_Server_Exception
-     */
-    public function uidForIdOrMailOrAlias($id)
-    {
-        $criteria = array('OR' =>
-                         array(
-                             array('field' => 'alias',
-                                   'op'    => '=',
-                                   'test'  => $id),
-                             array('field' => 'mail',
-                                   'op'    => '=',
-                                   'test'  => $id),
-                             array('field' => 'uid',
-                                   'op'    => '=',
-                                   'test'  => $id),
-                         ),
-        );
-        return $this->uidForSearch($criteria);
-    }
-
-    /**
-     * Identify the primary mail attribute for the first object found
-     * with the given ID or mail.
-     *
-     * @param string $id Search for objects with this ID/mail.
-     *
-     * @return mixed The mail address or false if there was no result.
-     *
-     * @throws Horde_Kolab_Server_Exception
-     */
-    public function mailForIdOrMail($id)
-    {
-        $criteria = array('AND' =>
-                         array(
-                             array('field' => 'objectClass',
-                                   'op'    => '=',
-                                   'test'  => self::USER),
-                             array('OR' =>
-                                   array(
-                                       array('field' => 'uid',
-                                             'op'    => '=',
-                                             'test'  => $id),
-                                       array('field' => 'mail',
-                                             'op'    => '=',
-                                             'test'  => $id),
-                                   ),
-                             ),
-                         ),
-        );
-
-        $data = $this->attrsForSearch($criteria, array('mail'),
-                                      self::RESULT_STRICT);
-        if (!empty($data)) {
-            return $data['mail'][0];
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Returns a list of allowed email addresses for the given user.
-     *
-     * @param string $id Search for objects with this ID/mail.
-     *
-     * @return array An array of allowed mail addresses.
-     *
-     * @throws Horde_Kolab_Server_Exception
-     */
-    public function addrsForIdOrMail($id)
-    {
-        $criteria = array('AND' =>
-                         array(
-                             array('field' => 'objectClass',
-                                   'op'    => '=',
-                                   'test'  => self::USER),
-                             array('OR' =>
-                                   array(
-                                       array('field' => 'uid',
-                                             'op'    => '=',
-                                             'test'  => $id),
-                                       array('field' => 'mail',
-                                             'op'    => '=',
-                                             'test'  => $id),
-                                   ),
-                             ),
-                         ),
-        );
-
-        $result = $this->attrsForSearch($criteria, array('mail', 'alias'),
-                                        self::RESULT_STRICT);
-        if (isset($result['alias'])) {
-            $addrs = array_merge((array) $result['mail'], (array) $result['alias']);
-        } else {
-            $addrs = $result['mail'];
-        }
-
-        if (empty($result)) {
-            return array();
-        }
-        $criteria = array('AND' =>
-                         array(
-                             array('field' => 'objectClass',
-                                   'op'    => '=',
-                                   'test'  => self::USER),
-                             array('field' => 'kolabDelegate',
-                                   'op'    => '=',
-                                   'test'  => $result['mail'][0]),
-                         ),
-        );
-
-        $result = $this->attrsForSearch($criteria, array('mail', 'alias'),
-                                      self::RESULT_MANY);
-        if (!empty($result)) {
-            foreach ($result as $adr) {
-                if (isset($adr['mail'])) {
-                    $addrs = array_merge((array) $addrs, (array) $adr['mail']);
-                }
-                if (isset($adr['alias'])) {
-                    $addrs = array_merge((array) $addrs, (array) $adr['alias']);
-                }
-            }
-        }
-
-        $addrs = array_map('strtolower', $addrs);
-
-        return $addrs;
-    }
-
-    /**
-     * Identify the GID for the first group found with the given mail.
-     *
-     * @param string $mail     Search for groups with this mail address.
-     * @param int    $restrict A Horde_Kolab_Server::RESULT_* result restriction.
-     *
-     * @return mixed The GID or false if there was no result.
-     *
-     * @throws Horde_Kolab_Server_Exception
-     */
-    public function gidForMail($mail,
-                               $restrict = Horde_Kolab_Server::RESULT_SINGLE)
-    {
-        $criteria = array('AND' => array(array('field' => 'mail',
-                                              'op'    => '=',
-                                              'test'  => $mail),
-                         ),
-        );
-        return $this->gidForSearch($criteria, $restrict);
-    }
-
-    /**
-     * Is the given UID member of the group with the given mail address?
-     *
-     * @param string $uid  UID of the user.
-     * @param string $mail Search the group with this mail address.
-     *
-     * @return boolean True in case the user is in the group, false otherwise.
-     *
-     * @throws Horde_Kolab_Server_Exception
-     */
-    public function memberOfGroupAddress($uid, $mail)
-    {
-        $criteria = array('AND' =>
-                          array(
-                              array('field' => 'mail',
-                                    'op'    => '=',
-                                    'test'  => $mail),
-                              array('field' => 'member',
-                                    'op'    => '=',
-                                    'test'  => $uid),
-                          ),
-        );
-
-        $result = $this->gidForSearch($criteria,
-                                      self::RESULT_SINGLE);
-        return !empty($result);
-    }
-
-    /**
-     * Get the groups for this object.
-     *
-     * @param string $uid The UID of the object to fetch.
-     *
-     * @return array An array of group ids.
-     *
-     * @throws Horde_Kolab_Server_Exception
-     */
-    public function getGroups($uid)
-    {
-        $criteria = array('AND' =>
-                          array(
-                              array('field' => 'member',
-                                    'op'    => '=',
-                                    'test'  => $uid),
-                          ),
-        );
-
-        $result = $this->gidForSearch($criteria, self::RESULT_MANY);
-        if (empty($result)) {
-            return array();
-        }
-        return $result;
-    }
-}
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/test.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/test.php
deleted file mode 100644 (file)
index daa9086..0000000
+++ /dev/null
@@ -1,715 +0,0 @@
-<?php
-/**
- * A driver for simulating a Kolab user database stored in LDAP.
- *
- * PHP version 5
- *
- * @category Kolab
- * @package  Kolab_Server
- * @author   Gunnar Wrobel <wrobel@pardus.de>
- * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
- * @link     http://pear.horde.org/index.php?package=Kolab_Server
- */
-
-/**
- * This class provides a class for testing the Kolab Server DB.
- *
- * Copyright 2008-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
- *
- * @category Kolab
- * @package  Kolab_Server
- * @author   Gunnar Wrobel <wrobel@pardus.de>
- * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
- * @link     http://pear.horde.org/index.php?package=Kolab_Server
- */
-class Horde_Kolab_Server_test extends Horde_Kolab_Server_ldap
-{
-
-    /**
-     * The current database data.
-     *
-     * @var array
-     */
-    protected $data;
-
-    /**
-     * Indicates if we are bound.
-     *
-     * @var array
-     */
-    protected $bound;
-
-    /**
-     * Array holding the current result set.
-     *
-     * @var array
-     */
-    private $_result;
-
-    /**
-     * Buffer for error numbers.
-     *
-     * @var int
-     */
-    private $_errno = 0;
-
-    /**
-     * Buffer for error descriptions.
-     *
-     * @var int
-     */
-    private $_error = '';
-
-    /**
-     * Attribute used for sorting.
-     *
-     * @var string
-     */
-    private $_sort_by;
-
-    /**
-     * A result cache for iterating over the result.
-     *
-     * @var array
-     */
-    private $_current_result;
-
-    /**
-     * An index into the current result for iterating.
-     *
-     * @var int
-     */
-    private $_current_index;
-
-    /**
-     * Construct a new Horde_Kolab_Server object.
-     *
-     * @param array $params Parameter array.
-     */
-    public function __construct($params = array())
-    {
-        $this->load();
-        if (isset($params['data'])) {
-            $this->data = $params['data'];
-        } else {
-            if (!isset($this->data)) {
-               $this->data  = array();
-            }
-        }
-
-        parent::__construct($params);
-
-        if (isset($this->params['adminuser'])
-            && isset($this->params['adminpass'])) {
-            $base_dn = isset($this->params['basedn']) ? ',' . $this->params['basedn'] : '';
-            $dn = 'cn=' . $this->params['adminuser'] . ',cn=internal' . $base_dn;
-            if (!isset($this->data[$dn])) {
-                $ldap_data = array(
-                    'cn' => array('manager'),
-                    'sn' => array('n/a'),
-                    'uid' => array('manager'),
-                    'userPassword' => array($this->params['adminpass']),
-                    'objectClass' => array('top','inetOrgPerson','kolabInetOrgPerson')
-                );
-                $this->data[$dn] = array(
-                    'dn' => $dn,
-                    'data' => $ldap_data
-                );
-            }
-        }
-
-        $this->store();
-    }
-
-    /**
-     * Connect to the server.
-     *
-     * @return NULL.
-     *
-     * @throws Horde_Kolab_Server_Exception If the connection failed.
-     */
-    protected function connect()
-    {
-    }
-
-    /**
-     * Load the current state of the database.
-     *
-     * @return NULL
-     */
-    protected function load()
-    {
-        if (isset($GLOBALS['KOLAB_SERVER_TEST_DATA'])) {
-            $this->data = $GLOBALS['KOLAB_SERVER_TEST_DATA'];
-        } else {
-            $this->data = array();
-        }
-    }
-
-    /**
-     * Store the current state of the database.
-     *
-     * @return NULL
-     */
-    protected function store()
-    {
-        $GLOBALS['KOLAB_SERVER_TEST_DATA'] = $this->data;
-    }
-
-    /**
-     * Cleans the current state of the database.
-     *
-     * @return NULL
-     */
-    public function clean()
-    {
-        $this->unbind();
-
-        $GLOBALS['KOLAB_SERVER_TEST_DATA'] = array();
-
-        $this->data = array();
-    }
-
-    /**
-     * Binds the LDAP connection with a specific user and pass.
-     *
-     * @param string $dn DN to bind with
-     * @param string $pw Password associated to this DN.
-     *
-     * @return boolean Whether or not the binding succeeded.
-     *
-     * @throws Horde_Kolab_Server_Exception If the user does not exit, he has no
-     *                                      password, provided an incorrect
-     *                                      password or anonymous binding is not
-     *                                      allowed.
-     */
-    protected function bind($dn = false, $pw = '')
-    {
-        if (!$dn) {
-            if (isset($this->params['uid'])) {
-                $dn = $this->params['uid'];
-            } else {
-                $dn = '';
-            }
-        }
-        if (!$pw) {
-            if (isset($this->params['pass'])) {
-                $pw = $this->params['pass'];
-            }
-        }
-
-        if (!empty($dn)) {
-            if (!isset($this->data[$dn])) {
-                throw new Horde_Kolab_Server_Exception('User does not exist!');
-            }
-
-            $this->bound = true;
-
-            try {
-                $data = $this->read($dn, array('userPassword'));
-            } catch (Horde_Kolab_Server_Exception $e) {
-                $this->bound = false;
-                throw $e;
-            }
-            if (!isset($data['userPassword'])) {
-                $this->bound = false;
-                throw new Horde_Kolab_Server_Exception('User has no password entry!');
-            }
-            $this->bound = $data['userPassword'][0] == $pw;
-            if (!$this->bound) {
-                throw new Horde_Kolab_Server_Exception('Incorrect password!');
-            }
-        } else if (!empty($this->params['no_anonymous_bind'])) {
-            $this->bound = false;
-            throw new Horde_Kolab_Server_Exception('Anonymous bind is not allowed!');
-        } else {
-            $this->bound = true;
-        }
-        return $this->bound;
-    }
-
-    /**
-     * Disconnect from LDAP.
-     *
-     * @return NULL
-     */
-    public function unbind()
-    {
-        $this->bound = false;
-    }
-
-    /**
-     * Parse LDAP filter.
-     * Partially derived from Net_LDAP_Filter.
-     *
-     * @param string $filter The filter string.
-     *
-     * @return array An array of the parsed filter.
-     *
-     * @throws Horde_Kolab_Server_Exception If parsing the filter expression
-     *                                      fails.
-     */
-    public function parse($filter)
-    {
-        $result = array();
-        if (preg_match('/^\((.+?)\)$/', $filter, $matches)) {
-            if (in_array(substr($matches[1], 0, 1), array('!', '|', '&'))) {
-                $result['op']  = substr($matches[1], 0, 1);
-                $result['sub'] = $this->parseSub(substr($matches[1], 1));
-                return $result;
-            } else {
-                if (stristr($matches[1], ')(')) {
-                    throw new Horde_Kolab_Server_Exception('Filter parsing error: invalid filter syntax - multiple leaf components detected!');
-                } else {
-                    $filter_parts = preg_split('/(?<!\\\\)(=|=~|>|<|>=|<=)/',
-                                               $matches[1], 2,
-                                               PREG_SPLIT_DELIM_CAPTURE);
-                    if (count($filter_parts) != 3) {
-                        throw new Horde_Kolab_Server_Exception('Filter parsing error: invalid filter syntax - unknown matching rule used');
-                    } else {
-                        $result['att'] = $filter_parts[0];
-                        $result['log'] = $filter_parts[1];
-                        $result['val'] = $filter_parts[2];
-                        return $result;
-                    }
-                }
-            }
-        } else {
-            throw new Horde_Kolab_Server_Exception(sprintf("Filter parsing error: %s - filter components must be enclosed in round brackets",
-                                                           $filter));
-        }
-    }
-
-    /**
-     * Parse a LDAP subfilter.
-     *
-     * @param string $filter The subfilter string.
-     *
-     * @return array An array of the parsed subfilter.
-     *
-     * @throws Horde_Kolab_Server_Exception
-     */
-    public function parseSub($filter)
-    {
-        $result  = array();
-        $level   = 0;
-        $collect = '';
-        while (preg_match('/^(\(.+?\))(.*)/', $filter, $matches)) {
-            if (in_array(substr($matches[1], 0, 2), array('(!', '(|', '(&'))) {
-                $level++;
-            }
-            if ($level) {
-                $collect .= $matches[1];
-                if (substr($matches[2], 0, 1) == ')') {
-                    $collect   .= ')';
-                    $matches[2] = substr($matches[2], 1);
-                    $level--;
-                    if (!$level) {
-                        $result[] = $this->parse($collect);
-                    }
-                }
-            } else {
-                $result[] = $this->parse($matches[1]);
-            }
-            $filter = $matches[2];
-        }
-        return $result;
-    }
-
-    /**
-     * Search for object data.
-     *
-     * @param string $filter The LDAP search filter.
-     * @param string $params Additional search parameters.
-     * @param string $base   The search base
-     *
-     * @return array The result array.
-     *
-     * @throws Horde_Kolab_Server_Exception If the search operation encountered
-     *                                      a problem.
-     */
-    public function search($filter = null, $params = array(), $base = null)
-    {
-        if (!$this->bound) {
-            $result = $this->bind();
-        }
-
-        $filter = $this->parse($filter);
-        if (isset($params['attributes'])) {
-            $attributes = $params['attributes'];
-            if (!is_array($attributes)) {
-                $attributes = array($attributes);
-            }
-        } else {
-            $attributes = array();
-        }
-        $result = $this->doSearch($filter, $attributes);
-        if (empty($result)) {
-            return null;
-        }
-        if ($base) {
-            $subtree = array();
-            foreach ($result as $entry) {
-                if (strpos($entry['dn'], $base)) {
-                    $subtree[] = $entry;
-                }
-            }
-            $result = $subtree;
-        }
-        return $this->getEntries($result);
-    }
-
-    /**
-     * Perform the search.
-     *
-     * @param array $filter     Filter criteria-
-     * @param array $attributes Restrict the search result to
-     *                          these attributes.
-     *
-     * @return array A LDAP serach result.
-     *
-     * @throws Horde_Kolab_Server_Exception If the search operation is not
-     *                                      available.
-     */
-    protected function doSearch($filter, $attributes = null)
-    {
-        if (isset($filter['log'])) {
-            $result = array();
-            foreach ($this->data as $element) {
-                if (isset($element['data'][$filter['att']])) {
-                    switch ($filter['log']) {
-                    case '=':
-                        $value = $element['data'][$filter['att']];
-                        if (($filter['val'] == '*' && !empty($value))
-                            || $value == $filter['val']
-                            || (is_array($value)
-                                && in_array($filter['val'], $value))) {
-                            if (empty($attributes)) {
-                                $result[] = $element;
-                            } else {
-                                $selection = $element;
-                                foreach ($element['data'] as $attr => $value) {
-                                    if (!in_array($attr, $attributes)) {
-                                        unset($selection['data'][$attr]);
-                                    }
-                                }
-                                $result[] = $selection;
-                            }
-                        }
-                        break;
-                    default:
-                        throw new Horde_Kolab_Server_Exception(_("Not implemented!"));
-                    }
-                }
-            }
-            return $result;
-        } else {
-            $subresult   = array();
-            $filtercount = count($filter['sub']);
-            foreach ($filter['sub'] as $subfilter) {
-                $subresult = array_merge($subresult,
-                                         $this->doSearch($subfilter,
-                                                         $attributes));
-            }
-            $result = array();
-            $dns    = array();
-            foreach ($subresult as $element) {
-                $dns[] = $element['dn'];
-
-                $result[$element['dn']] = $element;
-            }
-            switch ($filter['op']) {
-            case '&':
-                $count     = array_count_values($dns);
-                $selection = array();
-                foreach ($count as $dn => $value) {
-                    if ($value == $filtercount) {
-                        $selection[] = $result[$dn];
-                    }
-                }
-                return $selection;
-            case '|':
-                return array_values($result);
-            case '!':
-                $dns = array();
-                foreach ($result as $entry) {
-                    if (!in_array($entry['dn'], $dns) ) {
-                        $dns[] = $entry['dn'];
-                    }
-                }
-                $all_dns = array_keys($this->data);
-                $diff    = array_diff($all_dns, $dns);
-
-                $result = array();
-                foreach ($diff as $dn) {
-                    if (empty($attributes)) {
-                        $result[] = $this->data[$dn];
-                    } else {
-                        $selection = $this->data[$dn];
-                        foreach ($this->data[$dn]['data']
-                                 as $attr => $value) {
-                            if (!in_array($attr, $attributes)) {
-                                unset($selection['data'][$attr]);
-                            }
-                        }
-                        $result[] = $selection;
-                    }
-                }
-                return $result;
-            default:
-                throw new Horde_Kolab_Server_Exception(_("Not implemented!"));
-            }
-        }
-    }
-
-    /**
-     * Read object data.
-     *
-     * @param string $dn    The object to retrieve.
-     * @param string $attrs Restrict to these attributes
-     *
-     * @return array An array of attributes.
-     *
-     * @throws Horde_Kolab_Server_Exception If the object does not exist.
-     */
-    public function read($dn, $attrs = null)
-    {
-        if (!$this->bound) {
-            $result = $this->bind();
-        }
-
-        if (!isset($this->data[$dn])) {
-            throw new Horde_Kolab_Server_MissingObjectException(sprintf("No such object: %s",
-                                                                        $dn));
-        }
-        if (empty($attrs)) {
-            return $this->data[$dn]['data'];
-        } else {
-            $result = array();
-            $data   = $this->data[$dn]['data'];
-
-            foreach ($attrs as $attr) {
-                if (isset($data[$attr])) {
-                    $result[$attr] = $data[$attr];
-                    array_push($result, $attr);
-                }
-            }
-            return $result;
-        }
-    }
-
-    /**
-     * Add a new object
-     *
-     * @param string $dn   The DN of the object to be added.
-     * @param array  $data The attributes of the object to be added.
-     *
-     * @return boolean  True if adding succeeded.
-     */
-    public function save($dn, $data)
-    {
-        if (!$this->bound) {
-            $result = $this->bind();
-        }
-
-        $ldap_data = array();
-        foreach ($data as $key => $val) {
-            if (!is_array($val)) {
-                $val = array($val);
-            }
-            $ldap_data[$key] = $val;
-        }
-
-        $this->data[$dn] = array(
-            'dn' => $dn,
-            'data' => $ldap_data
-        );
-        $this->store();
-    }
-
-    /**
-     * Return the attributes of an entry.
-     *
-     * @param array $entry The LDAP entry.
-     *
-     * @return array  The attributes of the entry.
-     */
-    protected function getAttributes($entry)
-    {
-        if (is_array($entry)) {
-            return $entry;
-        }
-        return false;
-    }
-
-    /**
-     * Return the current entry of a result.
-     *
-     * @return mixe  The current entry of the result or false.
-     */
-    protected function fetchEntry()
-    {
-        if (is_array($this->_current_result)
-            && $this->_current_index < count($this->_current_result)) {
-
-            $data = array_keys($this->_current_result[$this->_current_index]['data']);
-
-            $data['dn'] = array($this->_current_result[$this->_current_index]['dn']);
-
-            foreach ($this->_current_result[$this->_current_index]['data']
-                     as $attr => $value) {
-                if (!is_array($value)) {
-                    $value = array($value);
-                }
-                $data[$attr] = $value;
-            }
-            $this->_current_index++;
-            return $data;
-        }
-        return false;
-    }
-
-    /**
-     * Return the first entry of a result.
-     *
-     * @param array $result The LDAP search result.
-     *
-     * @return mixed The first entry of the result or false.
-     */
-    protected function firstEntry($result)
-    {
-        $this->_current_result = $result;
-        $this->_current_index  = 0;
-        return $this->fetchEntry();
-    }
-
-    /**
-     * Return the next entry of a result.
-     *
-     * @param resource $entry The current LDAP entry.
-     *
-     * @return resource The next entry of the result.
-     */
-    protected function nextEntry($entry)
-    {
-        return $this->fetchEntry();
-    }
-
-    /**
-     * Return the entries of a result.
-     *
-     * @param array $result The LDAP search result.
-     *
-     * @return mixed The entries of the result or false.
-     */
-    protected function getEntries($result)
-    {
-        if (is_array($result)) {
-            $data = array();
-            foreach ($result as $entry) {
-                $t       = $entry['data'];
-                $t['dn'] = $entry['dn'];
-                $data[]  = $t;
-            }
-            return $data;
-        }
-        return false;
-    }
-
-    /**
-     * Sort the entries of a result.
-     *
-     * @param resource &$result   The LDAP search result.
-     * @param string   $attribute The attribute used for sorting.
-     *
-     * @return boolean  True if sorting succeeded.
-     */
-    public function sort(&$result, $attribute)
-    {
-        if (empty($result)) {
-            return $result;
-        }
-
-        $this->_sort_by = $attribute;
-        usort($result, array($this, 'resultSort'));
-        return false;
-    }
-
-    /**
-     * Sort two entries.
-     *
-     * @param array $a First entry.
-     * @param array $b Second entry.
-     *
-     * @return int  Comparison result.
-     */
-    protected function resultSort($a, $b)
-    {
-        $x = isset($a['data'][$this->_sort_by][0])?$a['data'][$this->_sort_by][0]:'';
-        $y = isset($b['data'][$this->_sort_by][0])?$b['data'][$this->_sort_by][0]:'';
-        return strcasecmp($x, $y);
-    }
-
-
-    /**
-     * Return the current LDAP error number.
-     *
-     * @return int  The current LDAP error number.
-     */
-    protected function errno()
-    {
-        return $this->_errno;
-    }
-
-    /**
-     * Return the current LDAP error description.
-     *
-     * @return string  The current LDAP error description.
-     */
-    protected function error()
-    {
-        return $this->_error;
-    }
-
-    /**
-     * Identify the DN of the first result entry.
-     *
-     * @todo Check if this could be reintegrated with the code in the LDAP handler
-     *       again.
-     *
-     * @param array $result   The LDAP search result.
-     * @param int   $restrict A Horde_Kolab_Server::RESULT_* result restriction.
-     *
-     * @return boolean|string|array The DN(s) or false if there was no result.
-     *
-     * @throws Horde_Kolab_Server_Exception If the number of results did not
-     *                                      meet the expectations.
-     */
-    protected function dnFromResult($result,
-                                    $restrict = Horde_Kolab_Server::RESULT_SINGLE)
-    {
-        if (empty($result)) {
-            return false;
-        }
-        $dns = array();
-        foreach ($result as $entry) {
-            $dns[] = $entry['dn'];
-        }
-
-        switch ($restrict) {
-        case self::RESULT_STRICT:
-            if (count($dns) > 1) {
-                throw new Horde_Kolab_Server_Exception(sprintf(_("Found %s results when expecting only one!"),
-                                                               $count));
-            }
-        case self::RESULT_SINGLE:
-            return $dns[0];
-        case self::RESULT_MANY:
-            return $dns;
-        }
-    }
-
-}
index aae96b0..cfb2ba4 100644 (file)
@@ -49,11 +49,11 @@ http://pear.php.net/dtd/package-2.0.xsd">
       <file name="Server.php" role="php" />
       <dir name="Server">
        <file name="Exception.php" role="php" />
-       <file name="file.php" role="php" />
-       <file name="ldap.php" role="php" />
+       <file name="File.php" role="php" />
+       <file name="Ldap.php" role="php" />
        <file name="MissingObjectException.php" role="php" />
        <file name="Object.php" role="php" />
-       <file name="test.php" role="php" />
+       <file name="Test.php" role="php" />
        <dir name="Object">
         <file name="address.php" role="php" />
         <file name="administrator.php" role="php" />
@@ -84,10 +84,10 @@ http://pear.php.net/dtd/package-2.0.xsd">
        <file name="DistListHandlingTest.php" role="test" />
        <file name="GroupHandlingTest.php" role="test" />
        <file name="GroupTest.php" role="test" />
-       <file name="ldapTest.php" role="test" />
+       <file name="LdapTest.php" role="test" />
        <file name="ObjectTest.php" role="test" />
        <file name="ServerTest.php" role="test" />
-       <file name="testTest.php" role="test" />
+       <file name="TestTest.php" role="test" />
        <file name="UserHandlingTest.php" role="test" />
        <file name="UserTest.php" role="test" />
       </dir> <!-- /test/Horde/Kolab/Server -->
@@ -132,10 +132,10 @@ http://pear.php.net/dtd/package-2.0.xsd">
    <install name="lib/Horde/Kolab/Server.php" as="Horde/Kolab/Server.php" />
    <install name="lib/Horde/Kolab/Test/Server.php" as="Horde/Kolab/Test/Server.php" />
    <install name="lib/Horde/Kolab/Server/Exception.php" as="Horde/Kolab/Server/Exception.php" />
-   <install name="lib/Horde/Kolab/Server/file.php" as="Horde/Kolab/Server/file.php" />
-   <install name="lib/Horde/Kolab/Server/ldap.php" as="Horde/Kolab/Server/ldap.php" />
+   <install name="lib/Horde/Kolab/Server/File.php" as="Horde/Kolab/Server/File.php" />
+   <install name="lib/Horde/Kolab/Server/Ldap.php" as="Horde/Kolab/Server/Ldap.php" />
    <install name="lib/Horde/Kolab/Server/MissingObjectException.php" as="Horde/Kolab/Server/MissingObjectException.php" />
-   <install name="lib/Horde/Kolab/Server/test.php" as="Horde/Kolab/Server/test.php" />
+   <install name="lib/Horde/Kolab/Server/Test.php" as="Horde/Kolab/Server/Test.php" />
    <install name="lib/Horde/Kolab/Server/Object.php" as="Horde/Kolab/Server/Object.php" />
    <install name="lib/Horde/Kolab/Server/Object/address.php" as="Horde/Kolab/Server/Object/address.php" />
    <install name="lib/Horde/Kolab/Server/Object/administrator.php" as="Horde/Kolab/Server/Object/administrator.php" />
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/LdapTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/LdapTest.php
new file mode 100644 (file)
index 0000000..086e3b1
--- /dev/null
@@ -0,0 +1,229 @@
+<?php
+/**
+ * Test the LDAP driver.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package  Kolab_Server
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * The Autoloader allows us to omit "require/include" statements.
+ */
+require_once 'Horde/Autoloader.php';
+
+/**
+ * Test the LDAP backend.
+ *
+ * Copyright 2008-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Kolab
+ * @package  Kolab_Server
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_ldapTest extends PHPUnit_Framework_TestCase
+{
+
+    /**
+     * Test handling of object classes.
+     *
+     * @return NULL
+     */
+    public function testGetObjectClasses()
+    {
+/*       $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('read')); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('read') */
+/*             ->will($this->returnValue(array ( */
+/*                                           'objectClass' => */
+/*                                           array ( */
+/*                                               'count' => 4, */
+/*                                               0 => 'top', */
+/*                                               1 => 'inetOrgPerson', */
+/*                                               2 => 'kolabInetOrgPerson', */
+/*                                               3 => 'hordePerson', */
+/*                                           ), */
+/*                                           0 => 'objectClass', */
+/*                                           'count' => 1))); */
+
+/*         $classes = $ldap->getObjectClasses('cn=Gunnar Wrobel,dc=example,dc=org'); */
+/*         if ($classes instanceOf PEAR_Error) { */
+/*             $this->assertEquals('', $classes->getMessage()); */
+/*         } */
+/*         $this->assertContains('top', $classes); */
+/*         $this->assertContains('kolabinetorgperson', $classes); */
+/*         $this->assertContains('hordeperson', $classes); */
+
+/*         $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('read')); */
+/*         $ldap->expects($this->any()) */
+/*              ->method('read') */
+/*              ->will($this->returnValue(PEAR::raiseError('LDAP Error: No such object: cn=DOES NOT EXIST,dc=example,dc=org: No such object'))); */
+
+/*         $classes = $ldap->getObjectClasses('cn=DOES NOT EXIST,dc=example,dc=org'); */
+/*         $this->assertEquals('LDAP Error: No such object: cn=DOES NOT EXIST,dc=example,dc=org: No such object', */
+/*                             $classes->message); */
+    }
+
+    /**
+     * Test retrieving a primary mail for a mail or uid.
+     *
+     * @return NULL
+     */
+/*     public function testMailForUidOrMail() */
+/*     { */
+/*         $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('getAttributes', */
+/*                                                                 'search', 'count', */
+/*                                                                 'firstEntry')); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_getAttributes') */
+/*             ->will($this->returnValue(array ( */
+/*                                           'mail' => */
+/*                                           array ( */
+/*                                               'count' => 1, */
+/*                                               0 => 'wrobel@example.org', */
+/*                                           ), */
+/*                                           0 => 'mail', */
+/*                                           'count' => 1))); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_search') */
+/*             ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_count') */
+/*             ->will($this->returnValue(1)); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_firstEntry') */
+/*             ->will($this->returnValue(1)); */
+
+/*         $mail = $ldap->mailForIdOrMail('wrobel'); */
+/*         $this->assertEquals('wrobel@example.org', $mail); */
+
+/*         $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('_getAttributes', */
+/*                                                                 '_search', */
+/*                                                                 '_count', */
+/*                                                                 '_firstEntry', */
+/*                                                                 '_errno', */
+/*                                                                 '_error')); */
+/*         $ldap->expects($this->any()) */
+/*              ->method('_getAttributes') */
+/*              ->will($this->returnValue(false)); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_search') */
+/*             ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_count') */
+/*             ->will($this->returnValue(1)); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_firstEntry') */
+/*             ->will($this->returnValue(1)); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_errno') */
+/*             ->will($this->returnValue(1)); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_error') */
+/*             ->will($this->returnValue('cn=DOES NOT EXIST,dc=example,dc=org: No such object')); */
+
+/*         $mail = $ldap->mailForIdOrMail('wrobel'); */
+/*         $this->assertEquals('Retrieving attributes failed. Error was: cn=DOES NOT EXIST,dc=example,dc=org: No such object', */
+/*                             $mail->message); */
+
+/*         $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('_getAttributes', */
+/*                                                                 '_search', */
+/*                                                                 '_count')); */
+/*         $ldap->expects($this->any()) */
+/*              ->method('_getAttributes') */
+/*              ->will($this->returnValue(false)); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_search') */
+/*             ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_count') */
+/*             ->will($this->returnValue(4)); */
+
+/*         $mail = $ldap->mailForIdOrMail('wrobel'); */
+/*         $this->assertEquals('Found 4 results when expecting only one!', */
+/*                             $mail->message); */
+/*     } */
+
+/*     /\** */
+/*      * Test retrieving a DN for a mail or uid. */
+/*      * */
+/*      * @return NULL */
+/*      *\/ */
+/*     public function testDnForUidOrMail() */
+/*     { */
+/*         $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('_getDn', */
+/*                                                                 '_search', '_count', */
+/*                                                                 '_firstEntry')); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_getDn') */
+/*             ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_search') */
+/*             ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_count') */
+/*             ->will($this->returnValue(1)); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_firstEntry') */
+/*             ->will($this->returnValue(1)); */
+
+/*         $dn = $ldap->uidForIdOrMail('wrobel'); */
+/*         $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $dn); */
+
+/*         $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('_getDn', */
+/*                                                                 '_search', */
+/*                                                                 '_count', */
+/*                                                                 '_firstEntry', */
+/*                                                                 '_errno', */
+/*                                                                 '_error')); */
+/*         $ldap->expects($this->any()) */
+/*              ->method('_getDn') */
+/*              ->will($this->returnValue(false)); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_search') */
+/*             ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_count') */
+/*             ->will($this->returnValue(1)); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_firstEntry') */
+/*             ->will($this->returnValue(1)); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_errno') */
+/*             ->will($this->returnValue(1)); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_error') */
+/*             ->will($this->returnValue('cn=DOES NOT EXIST,dc=example,dc=org: No such object')); */
+
+/*         $dn = $ldap->uidForIdOrMail('wrobel'); */
+/*         $this->assertEquals('Retrieving DN failed. Error was: cn=DOES NOT EXIST,dc=example,dc=org: No such object', */
+/*                             $dn->message); */
+
+/*         $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('_getDn', */
+/*                                                                 '_search', */
+/*                                                                 '_count')); */
+/*         $ldap->expects($this->any()) */
+/*              ->method('_getDn') */
+/*              ->will($this->returnValue(false)); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_search') */
+/*             ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
+/*         $ldap->expects($this->any()) */
+/*             ->method('_count') */
+/*             ->will($this->returnValue(4)); */
+
+/*         $dn = $ldap->uidForIdOrMail('wrobel'); */
+/*         $this->assertEquals('Found 4 results when expecting only one!', */
+/*                             $dn->message); */
+/*     } */
+
+}
index 266af33..6a532d2 100644 (file)
@@ -56,7 +56,7 @@ class Horde_Kolab_Server_ServerTest extends PHPUnit_Framework_TestCase
             $this->assertFail('No error!');
         } catch (Horde_Kolab_Server_Exception $e) {
             $this->assertEquals($e->getMessage(),
-                                'Server type definition "Horde_Kolab_Server_dummy" missing.');
+                                'Server type definition "Horde_Kolab_Server_Dummy" missing.');
         }
     }
 
@@ -110,7 +110,7 @@ class Horde_Kolab_Server_ServerTest extends PHPUnit_Framework_TestCase
  * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
  * @link     http://pear.horde.org/index.php?package=Kolab_Server
  */
-class Horde_Kolab_Server_none extends Horde_Kolab_Server
+class Horde_Kolab_Server_None extends Horde_Kolab_Server
 {
     /**
      * Stub for reading object data.
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/TestTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/TestTest.php
new file mode 100644 (file)
index 0000000..f28321f
--- /dev/null
@@ -0,0 +1,656 @@
+<?php
+/**
+ * Test the test driver.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package  Kolab_Server
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * The Autoloader allows us to omit "require/include" statements.
+ */
+require_once 'Horde/Autoloader.php';
+
+/**
+ * Test the test backend.
+ *
+ * Copyright 2008-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Kolab
+ * @package  Kolab_Server
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_testTest extends Horde_Kolab_Test_Server
+{
+
+    /**
+     * Test search base.
+     *
+     * @dataProvider provideServerTypes
+     *
+     * @return NULL
+     */
+    public function testSearchBase($type)
+    {
+        $server = &$this->prepareBasicServer($type);
+
+        $result = $server->search('(objectClass=top)', array('objectClass'));
+        $this->assertEquals(13, count($result));
+      
+        $result = $server->search('(objectClass=top)',
+                                  array('objectClass'),
+                                  'cn=internal,dc=example,dc=org');
+        $this->assertNoError($result);
+        $this->assertEquals(4, count($result));
+    }
+
+    /**
+     * Test sorting.
+     *
+     * @dataProvider provideServerTypes
+     *
+     * @return NULL
+     */
+    public function testSorting($type)
+    {
+        $server = &$this->prepareBasicServer($type);
+
+/*         $result = $server->search('(mail=*)', array('mail')); */
+/*         $this->assertNoError($result); */
+/*         $this->assertEquals(5, count($result)); */
+/*         $server->sort($result, 'mail'); */
+/*         foreach ($result as $object) { */
+/*             if (isset($object['data']['dn'])) { */
+/*                 switch ($object['data']['dn']) { */
+/*                 case 'cn=Test Address,cn=external,dc=example,dc=org': */
+/*                     $this->assertContains('address@example.org', $object['data']['mail']); */
+/*                     break; */
+/*                 case '': */
+/*                     $this->assertContains('address@example.org', $object['data']['mail']); */
+/*                     break; */
+/*                 } */
+/*             } */
+/*         } */
+    }
+
+    /**
+     * Test listing objects.
+     *
+     * @dataProvider provideServerTypes
+     *
+     * @return NULL
+     */
+    public function testListObjects($type)
+    {
+        $server = &$this->prepareBasicServer($type);
+
+        $filter     = '(&(objectClass=kolabInetOrgPerson)(uid=*)(mail=*)(sn=*))';
+        $attributes = array(
+            Horde_Kolab_Server_Object_base::ATTRIBUTE_SN,
+            Horde_Kolab_Server_Object_base::ATTRIBUTE_CN,
+            Horde_Kolab_Server_Object::ATTRIBUTE_UID,
+            Horde_Kolab_Server_Object_base::ATTRIBUTE_MAIL,
+            Horde_Kolab_Server_Object_base::ATTRIBUTE_DELETED,
+        );
+
+        $sort   = Horde_Kolab_Server_Object_base::ATTRIBUTE_SN;
+        $result = $server->search($filter);
+        $this->assertNoError($result);
+        $this->assertEquals(2, count($result));
+
+        $result = $server->listObjects('Horde_Kolab_Server_Object_user');
+        $this->assertNoError($result);
+        $this->assertEquals(2, count($result));
+        $this->assertEquals('Horde_Kolab_Server_Object_user', get_class(array_shift($result)));
+
+        $result = $server->listObjects('Horde_Kolab_Server_Object_sharedfolder');
+        $this->assertNoError($result);
+        $this->assertEquals(1, count($result));
+        $this->assertEquals('Horde_Kolab_Server_Object_sharedfolder', get_class(array_shift($result)));
+    }
+
+    /**
+     * Test handling of object classes.
+     *
+     * @dataProvider provideServerTypes
+     *
+     * @return NULL
+     */
+    public function testGetObjectClasses($type)
+    {
+        $server = &$this->prepareBasicServer($type);
+
+        $classes = $server->getObjectClasses('cn=Gunnar Wrobel,dc=example,dc=org');
+        $this->assertNoError($classes);
+        $this->assertContains('top', $classes);
+        $this->assertContains('kolabinetorgperson', $classes);
+        $this->assertContains('hordeperson', $classes);
+
+        try {
+            $classes = $server->getObjectClasses('cn=DOES NOT EXIST,dc=example,dc=org');
+        } catch (Horde_Kolab_Server_Exception $classes) {
+        }
+        $this->assertError($classes,
+                           'No such object: cn=DOES NOT EXIST,dc=example,dc=org');
+
+        $classes = $server->getObjectClasses('cn=The Administrator,dc=example,dc=org');
+        $this->assertNoError($classes);
+        $this->assertContains('kolabinetorgperson', $classes);
+    }
+
+    /**
+     * Test handling of object types.
+     *
+     * @dataProvider provideServerTypes
+     *
+     * @return NULL
+     */
+    public function testDetermineType($type)
+    {
+        $server = &$this->prepareBasicServer($type);
+
+        $type = $server->determineType('cn=empty.group@example.org,dc=example,dc=org');
+        $this->assertNoError($type);
+        $this->assertEquals('Horde_Kolab_Server_Object_group', $type);
+
+        $type = $server->determineType('cn=shared@example.org,dc=example,dc=org');
+        $this->assertNoError($type);
+        $this->assertEquals('Horde_Kolab_Server_Object_sharedfolder', $type);
+
+        $type = $server->determineType('cn=The Administrator,dc=example,dc=org');
+        $this->assertNoError($type);
+        $this->assertEquals('Horde_Kolab_Server_Object_administrator', $type);
+
+        $type = $server->determineType('cn=Main Tainer,dc=example,dc=org');
+        $this->assertNoError($type);
+        $this->assertEquals('Horde_Kolab_Server_Object_maintainer', $type);
+
+        $type = $server->determineType('cn=Domain Maintainer,dc=example,dc=org');
+        $this->assertNoError($type);
+        $this->assertEquals('Horde_Kolab_Server_Object_domainmaintainer', $type);
+
+        $type = $server->determineType('cn=Test Address,cn=external,dc=example,dc=org');
+        $this->assertNoError($type);
+        $this->assertEquals('Horde_Kolab_Server_Object_address', $type);
+
+        $type = $server->determineType('cn=Gunnar Wrobel,dc=example,dc=org');
+        $this->assertNoError($type);
+        $this->assertEquals('Horde_Kolab_Server_Object_user', $type);
+    }
+
+    /**
+     * Test retrieving a primary mail for a mail or id.
+     *
+     * @dataProvider provideServerTypes
+     *
+     * @return NULL
+     */
+    public function testMailForIdOrMail($type)
+    {
+        $server = &$this->prepareBasicServer($type);
+
+        $mail = $server->mailForIdOrMail('wrobel');
+        $this->assertEquals('wrobel@example.org', $mail);
+
+        $mail = $server->mailForIdOrMail('wrobel@example.org');
+        $this->assertNoError($mail);
+        $this->assertEquals('wrobel@example.org', $mail);
+
+        $mail = $server->mailForIdOrMail('DOES NOT EXIST');
+        $this->assertNoError($mail);
+        $this->assertSame(false, $mail);
+    }
+
+    /**
+     * Test retrieving a UID for a mail or id.
+     *
+     * @dataProvider provideServerTypes
+     *
+     * @return NULL
+     */
+    public function testUidForIdOrMail($type)
+    {
+        $server = &$this->prepareBasicServer($type);
+
+        $uid = $server->uidForIdOrMail('wrobel');
+        $this->assertNoError($uid);
+        $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
+
+        $uid = $server->uidForIdOrMail('wrobel@example.org');
+        $this->assertNoError($uid);
+        $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
+
+        $uid = $server->uidForIdOrMail('DOES NOT EXIST');
+        $this->assertNoError($uid);
+        $this->assertSame(false, $uid);
+    }
+
+    /**
+     * Test retrieving a UID for a mail or id.
+     *
+     * @dataProvider provideServerTypes
+     *
+     * @return NULL
+     */
+    public function testUidForMailOrIdOrAlias($type)
+    {
+        $server = &$this->prepareBasicServer($type);
+
+        $uid = $server->uidForIdOrMailOrAlias('g.wrobel@example.org');
+        $this->assertNoError($uid);
+        $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
+
+        $uid = $server->uidForIdOrMailOrAlias('wrobel@example.org');
+        $this->assertNoError($uid);
+        $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
+
+        $uid = $server->uidForIdOrMailOrAlias('wrobel');
+        $this->assertNoError($uid);
+        $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
+
+        $uid = $server->uidForIdOrMailOrAlias('DOES NOT EXIST');
+        $this->assertNoError($uid);
+        $this->assertSame(false, $uid);
+    }
+
+    /**
+     * Test retrieving all addresses for a mail or id.
+     *
+     * @dataProvider provideServerTypes
+     *
+     * @return NULL
+     */
+    public function testAddrsForIdOrMail($type)
+    {
+        $server = &$this->prepareBasicServer($type);
+
+        $addrs = $server->addrsForIdOrMail('wrobel');
+
+        $testuser = $server->fetch('cn=Test Test,dc=example,dc=org');
+        $this->assertNoError($testuser);
+        $this->assertContains('wrobel@example.org',
+                              $testuser->get(Horde_Kolab_Server_Object_base::ATTRIBUTE_DELEGATE, false));
+
+        $this->assertNoError($addrs);
+        $this->assertContains('wrobel@example.org', $addrs);
+        $this->assertContains('test@example.org', $addrs);
+        $this->assertContains('t.test@example.org', $addrs);
+        $this->assertContains('g.wrobel@example.org', $addrs);
+        $this->assertContains('gunnar@example.org', $addrs);
+
+        $addrs = $server->addrsForIdOrMail('test@example.org');
+        $this->assertNoError($addrs);
+        $this->assertContains('test@example.org', $addrs);
+        $this->assertContains('t.test@example.org', $addrs);
+    }
+
+    /**
+     * Test retrieving a UID for a primary mail.
+     *
+     * @dataProvider provideServerTypes
+     *
+     * @return NULL
+     */
+    public function testUidForMailAddress($type)
+    {
+        $server = &$this->prepareBasicServer($type);
+
+        $uid = $server->uidForIdOrMailOrAlias('wrobel@example.org');
+        $this->assertNoError($uid);
+        $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
+
+        $uid = $server->uidForIdOrMailOrAlias('test@example.org');
+        $this->assertNoError($uid);
+        $this->assertEquals('cn=Test Test,dc=example,dc=org', $uid);
+
+        $uid = $server->uidForIdOrMailOrAlias('gunnar@example.org');
+        $this->assertNoError($uid);
+        $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
+
+        $uid = $server->uidForIdOrMailOrAlias('wrobel');
+        $this->assertNoError($uid);
+        $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
+    }
+
+    /**
+     * Test retrieving a UID for an attribute.
+     *
+     * @dataProvider provideServerTypes
+     *
+     * @return NULL
+     */
+    public function testUidForAttr($type)
+    {
+        $server = &$this->prepareBasicServer($type);
+
+        $uid = $server->uidForSearch(array('AND' => array(array('field' => 'alias',
+                                                                    'op' => '=',
+                                                                    'test' => 'g.wrobel@example.org'))));
+        $this->assertNoError($uid);
+        $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
+    }
+
+    /**
+     * Test group membership testing.
+     *
+     * @dataProvider provideServerTypes
+     *
+     * @return NULL
+     */
+    public function testMemberOfGroupAddress($type)
+    {
+        $server = &$this->prepareBasicServer($type);
+
+        $uid = $server->uidForIdOrMailOrAlias('g.wrobel@example.org');
+        $this->assertNoError($uid);
+        $member = $server->memberOfGroupAddress($uid, 'group@example.org');
+        $this->assertNoError($member);
+        $this->assertTrue($member);
+
+        $member = $server->memberOfGroupAddress(
+            $server->uidForIdOrMailOrAlias('test@example.org'),
+            'group@example.org');
+        $this->assertNoError($member);
+        $this->assertTrue($member);
+
+        $member = $server->memberOfGroupAddress(
+            $server->uidForIdOrMailOrAlias('somebody@example.org'),
+            'group@example.org');
+        $this->assertNoError($member);
+        $this->assertFalse($member);
+    }
+
+    /**
+     * Test group fetching.
+     *
+     * @dataProvider provideServerTypes
+     *
+     * @return NULL
+     */
+    public function testGetGroups($type)
+    {
+        $server = &$this->prepareBasicServer($type);
+
+        $filter = '(&(objectClass=kolabGroupOfNames)(member='
+            . Horde_LDAP::quote('cn=The Administrator,dc=example,dc=org') . '))';
+        $result = $server->search($filter, array());
+        $this->assertNoError($result);
+        $this->assertTrue(!empty($result));
+
+/*         $entry = $server->_firstEntry($result); */
+/*         $this->assertNoError($entry); */
+/*         $this->assertTrue(!empty($entry)); */
+
+/*         $uid = $server->_getDn($entry); */
+/*         $this->assertNoError($uid); */
+/*         $this->assertTrue(!empty($uid)); */
+
+/*         $entry = $server->_nextEntry($entry); */
+/*         $this->assertNoError($entry); */
+/*         $this->assertTrue(empty($entry)); */
+
+/*         $entries = $server->_getDns($result); */
+/*         $this->assertNoError($entries); */
+/*         $this->assertTrue(!empty($entries)); */
+
+        $groups = $server->getGroups('cn=The Administrator,dc=example,dc=org');
+        $this->assertNoError($groups);
+        $this->assertTrue(!empty($groups));
+
+        $groups = $server->getGroups($server->uidForIdOrMailOrAlias('g.wrobel@example.org'));
+        $this->assertNoError($groups);
+        $this->assertContains('cn=group@example.org,dc=example,dc=org', $groups);
+
+        $groups = $server->getGroups($server->uidForIdOrMailOrAlias('test@example.org'));
+        $this->assertNoError($groups);
+        $this->assertContains('cn=group@example.org,dc=example,dc=org', $groups);
+
+        $groups = $server->getGroups('nobody');
+        $this->assertNoError($groups);
+        $this->assertTrue(empty($groups));
+
+    }
+
+    /**
+     * Test parsing of LDAP filters.
+     *
+     * @return NULL
+     */
+    public function testFilterParse()
+    {
+        $db = &Horde_Kolab_Server::factory('test', array());
+
+        $a = $db->parse('(a=b)');
+        $this->assertNoError($a);
+        $this->assertEquals(array('att' => 'a', 'log' => '=', 'val' => 'b'),
+                            $a);
+
+        $a = $db->parse('(&(a=b)(c=d))');
+        $this->assertNoError($a);
+        $this->assertEquals(array('op' => '&', 'sub' => array(
+                                      array('att' => 'a', 'log' => '=', 'val' => 'b'),
+                                      array('att' => 'c', 'log' => '=', 'val' => 'd'),
+                                  )), $a);
+
+        $a = $db->parse('(&(a=1)(|(b=2)(c=3)))');
+        $this->assertNoError($a);
+        $this->assertEquals(array('op' => '&', 'sub' => array(
+                                      array('att' => 'a', 'log' => '=', 'val' => '1'),
+                                      array('op' => '|', 'sub' =>
+                                            array(
+                                                array('att' => 'b', 'log' => '=', 'val' => '2'),
+                                                array('att' => 'c', 'log' => '=', 'val' => '3'),
+                                            )))), $a);
+
+        $a = $db->parseSub('(!(x=2))(b=1)');
+        $this->assertNoError($a);
+        $this->assertEquals(array(array('op' => '!', 'sub' =>
+                                        array(
+                                            array('att' => 'x', 'log' => '=', 'val' => '2'),
+                                        )
+                                  ),
+                                  array('att' => 'b', 'log' => '=', 'val' => '1'),
+                            ), $a);
+
+        $a = $db->parse('(&(!(x=2))(b=1))');
+        $this->assertNoError($a);
+        $this->assertEquals(array('op' => '&', 'sub' => array(
+                                      array('op' => '!', 'sub' =>
+                                            array(
+                                                array('att' => 'x', 'log' => '=', 'val' => '2'),
+                                            )
+                                      ),
+                                      array('att' => 'b', 'log' => '=', 'val' => '1'),
+                                  )), $a);
+
+    }
+
+    /**
+     * Test searching in the simulated LDAP data.
+     *
+     * @return NULL
+     */
+    public function testSearch()
+    {
+/*         $db = &Horde_Kolab_Server::factory('test', */
+/*                                            array('data' => */
+/*                                                  array( */
+/*                                                      'cn=a' => array( */
+/*                                                          'dn' => 'cn=a', */
+/*                                                          'data' => array( */
+/*                                                              'a' => '1', */
+/*                                                              'b' => '1', */
+/*                                                              'c' => '1', */
+/*                                                          ) */
+/*                                                      ), */
+/*                                                      'cn=b' => array( */
+/*                                                          'dn' => 'cn=b', */
+/*                                                          'data' => array( */
+/*                                                              'a' => '1', */
+/*                                                              'b' => '2', */
+/*                                                              'c' => '2', */
+/*                                                          ) */
+/*                                                      ), */
+/*                                                      'cn=c' => array( */
+/*                                                          'dn' => 'cn=c', */
+/*                                                          'data' => array( */
+/*                                                              'a' => '1', */
+/*                                                              'b' => '2', */
+/*                                                              'c' => '3', */
+/*                                                          ) */
+/*                                                      ), */
+/*                                                      'cn=d' => array( */
+/*                                                          'dn' => 'cn=d', */
+/*                                                          'data' => array( */
+/*                                                              'a' => '2', */
+/*                                                              'b' => '2', */
+/*                                                              'c' => '1', */
+/*                                                          ) */
+/*                                                      ), */
+/*                                                  ) */
+/*                                            ) */
+/*         ); */
+
+/*         $a = $db->search('(c=1)'); */
+/*         $this->assertNoError($a); */
+/*         $this->assertEquals( */
+/*             array( */
+/*                 array( */
+/*                     'dn' => 'cn=a', */
+/*                     'data' => array( */
+/*                         'a' => '1', */
+/*                         'b' => '1', */
+/*                         'c' => '1', */
+/*                     ) */
+/*                 ), */
+/*                 array( */
+/*                     'dn' => 'cn=d', */
+/*                     'data' => array( */
+/*                         'a' => '2', */
+/*                         'b' => '2', */
+/*                         'c' => '1', */
+/*                     ) */
+/*                 ), */
+/*             ), */
+/*             $a */
+/*         ); */
+
+/*         $a = $db->_search('(c=3)'); */
+/*         $this->assertNoError($a); */
+/*         $this->assertEquals( */
+/*             array( */
+/*                 array( */
+/*                     'dn' => 'cn=c', */
+/*                     'data' => array( */
+/*                         'a' => '1', */
+/*                         'b' => '2', */
+/*                         'c' => '3', */
+/*                     ) */
+/*                 ), */
+/*             ), */
+/*             $a */
+/*         ); */
+
+/*         $a = $db->_search('(c=3)', array('a')); */
+/*         $this->assertNoError($a); */
+/*         $this->assertEquals( */
+/*             array( */
+/*                 array( */
+/*                     'dn' => 'cn=c', */
+/*                     'data' => array( */
+/*                         'a' => '1', */
+/*                     ) */
+/*                 ), */
+/*             ), */
+/*             $a */
+/*         ); */
+
+/*         $a = $db->_search('(&(a=1)(b=2))', array('a', 'b')); */
+/*         $this->assertNoError($a); */
+/*         $this->assertEquals( */
+/*             array( */
+/*                 array( */
+/*                     'dn' => 'cn=b', */
+/*                     'data' => array( */
+/*                         'a' => '1', */
+/*                         'b' => '2', */
+/*                     ) */
+/*                 ), */
+/*                 array( */
+/*                     'dn' => 'cn=c', */
+/*                     'data' => array( */
+/*                         'a' => '1', */
+/*                         'b' => '2', */
+/*                     ) */
+/*                 ), */
+/*             ), */
+/*             $a */
+/*         ); */
+
+/*         $a = $db->_search('(&(b=2))', array('b')); */
+/*         $this->assertNoError($a); */
+/*         $this->assertEquals( */
+/*             array( */
+/*                 array( */
+/*                     'dn' => 'cn=b', */
+/*                     'data' => array( */
+/*                         'b' => '2', */
+/*                     ) */
+/*                 ), */
+/*                 array( */
+/*                     'dn' => 'cn=c', */
+/*                     'data' => array( */
+/*                         'b' => '2', */
+/*                     ) */
+/*                 ), */
+/*                 array( */
+/*                     'dn' => 'cn=d', */
+/*                     'data' => array( */
+/*                         'b' => '2', */
+/*                     ) */
+/*                 ), */
+/*             ), */
+/*             $a */
+/*         ); */
+
+/*         $a = $db->_search('(!(b=2))', array('a', 'b')); */
+/*         $this->assertNoError($a); */
+/*         $this->assertEquals( */
+/*             array( */
+/*                 array( */
+/*                     'dn' => 'cn=a', */
+/*                     'data' => array( */
+/*                         'a' => '1', */
+/*                         'b' => '1', */
+/*                     ) */
+/*                 ), */
+/*             ), */
+/*             $a */
+/*         ); */
+
+/*         $a = $db->_search('(&(!(x=2))(b=1))', array('b')); */
+/*         $this->assertNoError($a); */
+/*         $this->assertEquals( */
+/*             array( */
+/*                 array( */
+/*                     'dn' => 'cn=a', */
+/*                     'data' => array( */
+/*                         'b' => '1', */
+/*                     ) */
+/*                 ), */
+/*             ), */
+/*             $a */
+/*         ); */
+    }
+
+}
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/ldapTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/ldapTest.php
deleted file mode 100644 (file)
index 086e3b1..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-<?php
-/**
- * Test the LDAP driver.
- *
- * PHP version 5
- *
- * @category Kolab
- * @package  Kolab_Server
- * @author   Gunnar Wrobel <wrobel@pardus.de>
- * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
- * @link     http://pear.horde.org/index.php?package=Kolab_Server
- */
-
-/**
- * The Autoloader allows us to omit "require/include" statements.
- */
-require_once 'Horde/Autoloader.php';
-
-/**
- * Test the LDAP backend.
- *
- * Copyright 2008-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
- *
- * @category Kolab
- * @package  Kolab_Server
- * @author   Gunnar Wrobel <wrobel@pardus.de>
- * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
- * @link     http://pear.horde.org/index.php?package=Kolab_Server
- */
-class Horde_Kolab_Server_ldapTest extends PHPUnit_Framework_TestCase
-{
-
-    /**
-     * Test handling of object classes.
-     *
-     * @return NULL
-     */
-    public function testGetObjectClasses()
-    {
-/*       $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('read')); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('read') */
-/*             ->will($this->returnValue(array ( */
-/*                                           'objectClass' => */
-/*                                           array ( */
-/*                                               'count' => 4, */
-/*                                               0 => 'top', */
-/*                                               1 => 'inetOrgPerson', */
-/*                                               2 => 'kolabInetOrgPerson', */
-/*                                               3 => 'hordePerson', */
-/*                                           ), */
-/*                                           0 => 'objectClass', */
-/*                                           'count' => 1))); */
-
-/*         $classes = $ldap->getObjectClasses('cn=Gunnar Wrobel,dc=example,dc=org'); */
-/*         if ($classes instanceOf PEAR_Error) { */
-/*             $this->assertEquals('', $classes->getMessage()); */
-/*         } */
-/*         $this->assertContains('top', $classes); */
-/*         $this->assertContains('kolabinetorgperson', $classes); */
-/*         $this->assertContains('hordeperson', $classes); */
-
-/*         $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('read')); */
-/*         $ldap->expects($this->any()) */
-/*              ->method('read') */
-/*              ->will($this->returnValue(PEAR::raiseError('LDAP Error: No such object: cn=DOES NOT EXIST,dc=example,dc=org: No such object'))); */
-
-/*         $classes = $ldap->getObjectClasses('cn=DOES NOT EXIST,dc=example,dc=org'); */
-/*         $this->assertEquals('LDAP Error: No such object: cn=DOES NOT EXIST,dc=example,dc=org: No such object', */
-/*                             $classes->message); */
-    }
-
-    /**
-     * Test retrieving a primary mail for a mail or uid.
-     *
-     * @return NULL
-     */
-/*     public function testMailForUidOrMail() */
-/*     { */
-/*         $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('getAttributes', */
-/*                                                                 'search', 'count', */
-/*                                                                 'firstEntry')); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_getAttributes') */
-/*             ->will($this->returnValue(array ( */
-/*                                           'mail' => */
-/*                                           array ( */
-/*                                               'count' => 1, */
-/*                                               0 => 'wrobel@example.org', */
-/*                                           ), */
-/*                                           0 => 'mail', */
-/*                                           'count' => 1))); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_search') */
-/*             ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_count') */
-/*             ->will($this->returnValue(1)); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_firstEntry') */
-/*             ->will($this->returnValue(1)); */
-
-/*         $mail = $ldap->mailForIdOrMail('wrobel'); */
-/*         $this->assertEquals('wrobel@example.org', $mail); */
-
-/*         $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('_getAttributes', */
-/*                                                                 '_search', */
-/*                                                                 '_count', */
-/*                                                                 '_firstEntry', */
-/*                                                                 '_errno', */
-/*                                                                 '_error')); */
-/*         $ldap->expects($this->any()) */
-/*              ->method('_getAttributes') */
-/*              ->will($this->returnValue(false)); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_search') */
-/*             ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_count') */
-/*             ->will($this->returnValue(1)); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_firstEntry') */
-/*             ->will($this->returnValue(1)); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_errno') */
-/*             ->will($this->returnValue(1)); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_error') */
-/*             ->will($this->returnValue('cn=DOES NOT EXIST,dc=example,dc=org: No such object')); */
-
-/*         $mail = $ldap->mailForIdOrMail('wrobel'); */
-/*         $this->assertEquals('Retrieving attributes failed. Error was: cn=DOES NOT EXIST,dc=example,dc=org: No such object', */
-/*                             $mail->message); */
-
-/*         $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('_getAttributes', */
-/*                                                                 '_search', */
-/*                                                                 '_count')); */
-/*         $ldap->expects($this->any()) */
-/*              ->method('_getAttributes') */
-/*              ->will($this->returnValue(false)); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_search') */
-/*             ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_count') */
-/*             ->will($this->returnValue(4)); */
-
-/*         $mail = $ldap->mailForIdOrMail('wrobel'); */
-/*         $this->assertEquals('Found 4 results when expecting only one!', */
-/*                             $mail->message); */
-/*     } */
-
-/*     /\** */
-/*      * Test retrieving a DN for a mail or uid. */
-/*      * */
-/*      * @return NULL */
-/*      *\/ */
-/*     public function testDnForUidOrMail() */
-/*     { */
-/*         $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('_getDn', */
-/*                                                                 '_search', '_count', */
-/*                                                                 '_firstEntry')); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_getDn') */
-/*             ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_search') */
-/*             ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_count') */
-/*             ->will($this->returnValue(1)); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_firstEntry') */
-/*             ->will($this->returnValue(1)); */
-
-/*         $dn = $ldap->uidForIdOrMail('wrobel'); */
-/*         $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $dn); */
-
-/*         $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('_getDn', */
-/*                                                                 '_search', */
-/*                                                                 '_count', */
-/*                                                                 '_firstEntry', */
-/*                                                                 '_errno', */
-/*                                                                 '_error')); */
-/*         $ldap->expects($this->any()) */
-/*              ->method('_getDn') */
-/*              ->will($this->returnValue(false)); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_search') */
-/*             ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_count') */
-/*             ->will($this->returnValue(1)); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_firstEntry') */
-/*             ->will($this->returnValue(1)); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_errno') */
-/*             ->will($this->returnValue(1)); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_error') */
-/*             ->will($this->returnValue('cn=DOES NOT EXIST,dc=example,dc=org: No such object')); */
-
-/*         $dn = $ldap->uidForIdOrMail('wrobel'); */
-/*         $this->assertEquals('Retrieving DN failed. Error was: cn=DOES NOT EXIST,dc=example,dc=org: No such object', */
-/*                             $dn->message); */
-
-/*         $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('_getDn', */
-/*                                                                 '_search', */
-/*                                                                 '_count')); */
-/*         $ldap->expects($this->any()) */
-/*              ->method('_getDn') */
-/*              ->will($this->returnValue(false)); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_search') */
-/*             ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
-/*         $ldap->expects($this->any()) */
-/*             ->method('_count') */
-/*             ->will($this->returnValue(4)); */
-
-/*         $dn = $ldap->uidForIdOrMail('wrobel'); */
-/*         $this->assertEquals('Found 4 results when expecting only one!', */
-/*                             $dn->message); */
-/*     } */
-
-}
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/testTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/testTest.php
deleted file mode 100644 (file)
index f28321f..0000000
+++ /dev/null
@@ -1,656 +0,0 @@
-<?php
-/**
- * Test the test driver.
- *
- * PHP version 5
- *
- * @category Kolab
- * @package  Kolab_Server
- * @author   Gunnar Wrobel <wrobel@pardus.de>
- * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
- * @link     http://pear.horde.org/index.php?package=Kolab_Server
- */
-
-/**
- * The Autoloader allows us to omit "require/include" statements.
- */
-require_once 'Horde/Autoloader.php';
-
-/**
- * Test the test backend.
- *
- * Copyright 2008-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
- *
- * @category Kolab
- * @package  Kolab_Server
- * @author   Gunnar Wrobel <wrobel@pardus.de>
- * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
- * @link     http://pear.horde.org/index.php?package=Kolab_Server
- */
-class Horde_Kolab_Server_testTest extends Horde_Kolab_Test_Server
-{
-
-    /**
-     * Test search base.
-     *
-     * @dataProvider provideServerTypes
-     *
-     * @return NULL
-     */
-    public function testSearchBase($type)
-    {
-        $server = &$this->prepareBasicServer($type);
-
-        $result = $server->search('(objectClass=top)', array('objectClass'));
-        $this->assertEquals(13, count($result));
-      
-        $result = $server->search('(objectClass=top)',
-                                  array('objectClass'),
-                                  'cn=internal,dc=example,dc=org');
-        $this->assertNoError($result);
-        $this->assertEquals(4, count($result));
-    }
-
-    /**
-     * Test sorting.
-     *
-     * @dataProvider provideServerTypes
-     *
-     * @return NULL
-     */
-    public function testSorting($type)
-    {
-        $server = &$this->prepareBasicServer($type);
-
-/*         $result = $server->search('(mail=*)', array('mail')); */
-/*         $this->assertNoError($result); */
-/*         $this->assertEquals(5, count($result)); */
-/*         $server->sort($result, 'mail'); */
-/*         foreach ($result as $object) { */
-/*             if (isset($object['data']['dn'])) { */
-/*                 switch ($object['data']['dn']) { */
-/*                 case 'cn=Test Address,cn=external,dc=example,dc=org': */
-/*                     $this->assertContains('address@example.org', $object['data']['mail']); */
-/*                     break; */
-/*                 case '': */
-/*                     $this->assertContains('address@example.org', $object['data']['mail']); */
-/*                     break; */
-/*                 } */
-/*             } */
-/*         } */
-    }
-
-    /**
-     * Test listing objects.
-     *
-     * @dataProvider provideServerTypes
-     *
-     * @return NULL
-     */
-    public function testListObjects($type)
-    {
-        $server = &$this->prepareBasicServer($type);
-
-        $filter     = '(&(objectClass=kolabInetOrgPerson)(uid=*)(mail=*)(sn=*))';
-        $attributes = array(
-            Horde_Kolab_Server_Object_base::ATTRIBUTE_SN,
-            Horde_Kolab_Server_Object_base::ATTRIBUTE_CN,
-            Horde_Kolab_Server_Object::ATTRIBUTE_UID,
-            Horde_Kolab_Server_Object_base::ATTRIBUTE_MAIL,
-            Horde_Kolab_Server_Object_base::ATTRIBUTE_DELETED,
-        );
-
-        $sort   = Horde_Kolab_Server_Object_base::ATTRIBUTE_SN;
-        $result = $server->search($filter);
-        $this->assertNoError($result);
-        $this->assertEquals(2, count($result));
-
-        $result = $server->listObjects('Horde_Kolab_Server_Object_user');
-        $this->assertNoError($result);
-        $this->assertEquals(2, count($result));
-        $this->assertEquals('Horde_Kolab_Server_Object_user', get_class(array_shift($result)));
-
-        $result = $server->listObjects('Horde_Kolab_Server_Object_sharedfolder');
-        $this->assertNoError($result);
-        $this->assertEquals(1, count($result));
-        $this->assertEquals('Horde_Kolab_Server_Object_sharedfolder', get_class(array_shift($result)));
-    }
-
-    /**
-     * Test handling of object classes.
-     *
-     * @dataProvider provideServerTypes
-     *
-     * @return NULL
-     */
-    public function testGetObjectClasses($type)
-    {
-        $server = &$this->prepareBasicServer($type);
-
-        $classes = $server->getObjectClasses('cn=Gunnar Wrobel,dc=example,dc=org');
-        $this->assertNoError($classes);
-        $this->assertContains('top', $classes);
-        $this->assertContains('kolabinetorgperson', $classes);
-        $this->assertContains('hordeperson', $classes);
-
-        try {
-            $classes = $server->getObjectClasses('cn=DOES NOT EXIST,dc=example,dc=org');
-        } catch (Horde_Kolab_Server_Exception $classes) {
-        }
-        $this->assertError($classes,
-                           'No such object: cn=DOES NOT EXIST,dc=example,dc=org');
-
-        $classes = $server->getObjectClasses('cn=The Administrator,dc=example,dc=org');
-        $this->assertNoError($classes);
-        $this->assertContains('kolabinetorgperson', $classes);
-    }
-
-    /**
-     * Test handling of object types.
-     *
-     * @dataProvider provideServerTypes
-     *
-     * @return NULL
-     */
-    public function testDetermineType($type)
-    {
-        $server = &$this->prepareBasicServer($type);
-
-        $type = $server->determineType('cn=empty.group@example.org,dc=example,dc=org');
-        $this->assertNoError($type);
-        $this->assertEquals('Horde_Kolab_Server_Object_group', $type);
-
-        $type = $server->determineType('cn=shared@example.org,dc=example,dc=org');
-        $this->assertNoError($type);
-        $this->assertEquals('Horde_Kolab_Server_Object_sharedfolder', $type);
-
-        $type = $server->determineType('cn=The Administrator,dc=example,dc=org');
-        $this->assertNoError($type);
-        $this->assertEquals('Horde_Kolab_Server_Object_administrator', $type);
-
-        $type = $server->determineType('cn=Main Tainer,dc=example,dc=org');
-        $this->assertNoError($type);
-        $this->assertEquals('Horde_Kolab_Server_Object_maintainer', $type);
-
-        $type = $server->determineType('cn=Domain Maintainer,dc=example,dc=org');
-        $this->assertNoError($type);
-        $this->assertEquals('Horde_Kolab_Server_Object_domainmaintainer', $type);
-
-        $type = $server->determineType('cn=Test Address,cn=external,dc=example,dc=org');
-        $this->assertNoError($type);
-        $this->assertEquals('Horde_Kolab_Server_Object_address', $type);
-
-        $type = $server->determineType('cn=Gunnar Wrobel,dc=example,dc=org');
-        $this->assertNoError($type);
-        $this->assertEquals('Horde_Kolab_Server_Object_user', $type);
-    }
-
-    /**
-     * Test retrieving a primary mail for a mail or id.
-     *
-     * @dataProvider provideServerTypes
-     *
-     * @return NULL
-     */
-    public function testMailForIdOrMail($type)
-    {
-        $server = &$this->prepareBasicServer($type);
-
-        $mail = $server->mailForIdOrMail('wrobel');
-        $this->assertEquals('wrobel@example.org', $mail);
-
-        $mail = $server->mailForIdOrMail('wrobel@example.org');
-        $this->assertNoError($mail);
-        $this->assertEquals('wrobel@example.org', $mail);
-
-        $mail = $server->mailForIdOrMail('DOES NOT EXIST');
-        $this->assertNoError($mail);
-        $this->assertSame(false, $mail);
-    }
-
-    /**
-     * Test retrieving a UID for a mail or id.
-     *
-     * @dataProvider provideServerTypes
-     *
-     * @return NULL
-     */
-    public function testUidForIdOrMail($type)
-    {
-        $server = &$this->prepareBasicServer($type);
-
-        $uid = $server->uidForIdOrMail('wrobel');
-        $this->assertNoError($uid);
-        $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
-
-        $uid = $server->uidForIdOrMail('wrobel@example.org');
-        $this->assertNoError($uid);
-        $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
-
-        $uid = $server->uidForIdOrMail('DOES NOT EXIST');
-        $this->assertNoError($uid);
-        $this->assertSame(false, $uid);
-    }
-
-    /**
-     * Test retrieving a UID for a mail or id.
-     *
-     * @dataProvider provideServerTypes
-     *
-     * @return NULL
-     */
-    public function testUidForMailOrIdOrAlias($type)
-    {
-        $server = &$this->prepareBasicServer($type);
-
-        $uid = $server->uidForIdOrMailOrAlias('g.wrobel@example.org');
-        $this->assertNoError($uid);
-        $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
-
-        $uid = $server->uidForIdOrMailOrAlias('wrobel@example.org');
-        $this->assertNoError($uid);
-        $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
-
-        $uid = $server->uidForIdOrMailOrAlias('wrobel');
-        $this->assertNoError($uid);
-        $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
-
-        $uid = $server->uidForIdOrMailOrAlias('DOES NOT EXIST');
-        $this->assertNoError($uid);
-        $this->assertSame(false, $uid);
-    }
-
-    /**
-     * Test retrieving all addresses for a mail or id.
-     *
-     * @dataProvider provideServerTypes
-     *
-     * @return NULL
-     */
-    public function testAddrsForIdOrMail($type)
-    {
-        $server = &$this->prepareBasicServer($type);
-
-        $addrs = $server->addrsForIdOrMail('wrobel');
-
-        $testuser = $server->fetch('cn=Test Test,dc=example,dc=org');
-        $this->assertNoError($testuser);
-        $this->assertContains('wrobel@example.org',
-                              $testuser->get(Horde_Kolab_Server_Object_base::ATTRIBUTE_DELEGATE, false));
-
-        $this->assertNoError($addrs);
-        $this->assertContains('wrobel@example.org', $addrs);
-        $this->assertContains('test@example.org', $addrs);
-        $this->assertContains('t.test@example.org', $addrs);
-        $this->assertContains('g.wrobel@example.org', $addrs);
-        $this->assertContains('gunnar@example.org', $addrs);
-
-        $addrs = $server->addrsForIdOrMail('test@example.org');
-        $this->assertNoError($addrs);
-        $this->assertContains('test@example.org', $addrs);
-        $this->assertContains('t.test@example.org', $addrs);
-    }
-
-    /**
-     * Test retrieving a UID for a primary mail.
-     *
-     * @dataProvider provideServerTypes
-     *
-     * @return NULL
-     */
-    public function testUidForMailAddress($type)
-    {
-        $server = &$this->prepareBasicServer($type);
-
-        $uid = $server->uidForIdOrMailOrAlias('wrobel@example.org');
-        $this->assertNoError($uid);
-        $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
-
-        $uid = $server->uidForIdOrMailOrAlias('test@example.org');
-        $this->assertNoError($uid);
-        $this->assertEquals('cn=Test Test,dc=example,dc=org', $uid);
-
-        $uid = $server->uidForIdOrMailOrAlias('gunnar@example.org');
-        $this->assertNoError($uid);
-        $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
-
-        $uid = $server->uidForIdOrMailOrAlias('wrobel');
-        $this->assertNoError($uid);
-        $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
-    }
-
-    /**
-     * Test retrieving a UID for an attribute.
-     *
-     * @dataProvider provideServerTypes
-     *
-     * @return NULL
-     */
-    public function testUidForAttr($type)
-    {
-        $server = &$this->prepareBasicServer($type);
-
-        $uid = $server->uidForSearch(array('AND' => array(array('field' => 'alias',
-                                                                    'op' => '=',
-                                                                    'test' => 'g.wrobel@example.org'))));
-        $this->assertNoError($uid);
-        $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
-    }
-
-    /**
-     * Test group membership testing.
-     *
-     * @dataProvider provideServerTypes
-     *
-     * @return NULL
-     */
-    public function testMemberOfGroupAddress($type)
-    {
-        $server = &$this->prepareBasicServer($type);
-
-        $uid = $server->uidForIdOrMailOrAlias('g.wrobel@example.org');
-        $this->assertNoError($uid);
-        $member = $server->memberOfGroupAddress($uid, 'group@example.org');
-        $this->assertNoError($member);
-        $this->assertTrue($member);
-
-        $member = $server->memberOfGroupAddress(
-            $server->uidForIdOrMailOrAlias('test@example.org'),
-            'group@example.org');
-        $this->assertNoError($member);
-        $this->assertTrue($member);
-
-        $member = $server->memberOfGroupAddress(
-            $server->uidForIdOrMailOrAlias('somebody@example.org'),
-            'group@example.org');
-        $this->assertNoError($member);
-        $this->assertFalse($member);
-    }
-
-    /**
-     * Test group fetching.
-     *
-     * @dataProvider provideServerTypes
-     *
-     * @return NULL
-     */
-    public function testGetGroups($type)
-    {
-        $server = &$this->prepareBasicServer($type);
-
-        $filter = '(&(objectClass=kolabGroupOfNames)(member='
-            . Horde_LDAP::quote('cn=The Administrator,dc=example,dc=org') . '))';
-        $result = $server->search($filter, array());
-        $this->assertNoError($result);
-        $this->assertTrue(!empty($result));
-
-/*         $entry = $server->_firstEntry($result); */
-/*         $this->assertNoError($entry); */
-/*         $this->assertTrue(!empty($entry)); */
-
-/*         $uid = $server->_getDn($entry); */
-/*         $this->assertNoError($uid); */
-/*         $this->assertTrue(!empty($uid)); */
-
-/*         $entry = $server->_nextEntry($entry); */
-/*         $this->assertNoError($entry); */
-/*         $this->assertTrue(empty($entry)); */
-
-/*         $entries = $server->_getDns($result); */
-/*         $this->assertNoError($entries); */
-/*         $this->assertTrue(!empty($entries)); */
-
-        $groups = $server->getGroups('cn=The Administrator,dc=example,dc=org');
-        $this->assertNoError($groups);
-        $this->assertTrue(!empty($groups));
-
-        $groups = $server->getGroups($server->uidForIdOrMailOrAlias('g.wrobel@example.org'));
-        $this->assertNoError($groups);
-        $this->assertContains('cn=group@example.org,dc=example,dc=org', $groups);
-
-        $groups = $server->getGroups($server->uidForIdOrMailOrAlias('test@example.org'));
-        $this->assertNoError($groups);
-        $this->assertContains('cn=group@example.org,dc=example,dc=org', $groups);
-
-        $groups = $server->getGroups('nobody');
-        $this->assertNoError($groups);
-        $this->assertTrue(empty($groups));
-
-    }
-
-    /**
-     * Test parsing of LDAP filters.
-     *
-     * @return NULL
-     */
-    public function testFilterParse()
-    {
-        $db = &Horde_Kolab_Server::factory('test', array());
-
-        $a = $db->parse('(a=b)');
-        $this->assertNoError($a);
-        $this->assertEquals(array('att' => 'a', 'log' => '=', 'val' => 'b'),
-                            $a);
-
-        $a = $db->parse('(&(a=b)(c=d))');
-        $this->assertNoError($a);
-        $this->assertEquals(array('op' => '&', 'sub' => array(
-                                      array('att' => 'a', 'log' => '=', 'val' => 'b'),
-                                      array('att' => 'c', 'log' => '=', 'val' => 'd'),
-                                  )), $a);
-
-        $a = $db->parse('(&(a=1)(|(b=2)(c=3)))');
-        $this->assertNoError($a);
-        $this->assertEquals(array('op' => '&', 'sub' => array(
-                                      array('att' => 'a', 'log' => '=', 'val' => '1'),
-                                      array('op' => '|', 'sub' =>
-                                            array(
-                                                array('att' => 'b', 'log' => '=', 'val' => '2'),
-                                                array('att' => 'c', 'log' => '=', 'val' => '3'),
-                                            )))), $a);
-
-        $a = $db->parseSub('(!(x=2))(b=1)');
-        $this->assertNoError($a);
-        $this->assertEquals(array(array('op' => '!', 'sub' =>
-                                        array(
-                                            array('att' => 'x', 'log' => '=', 'val' => '2'),
-                                        )
-                                  ),
-                                  array('att' => 'b', 'log' => '=', 'val' => '1'),
-                            ), $a);
-
-        $a = $db->parse('(&(!(x=2))(b=1))');
-        $this->assertNoError($a);
-        $this->assertEquals(array('op' => '&', 'sub' => array(
-                                      array('op' => '!', 'sub' =>
-                                            array(
-                                                array('att' => 'x', 'log' => '=', 'val' => '2'),
-                                            )
-                                      ),
-                                      array('att' => 'b', 'log' => '=', 'val' => '1'),
-                                  )), $a);
-
-    }
-
-    /**
-     * Test searching in the simulated LDAP data.
-     *
-     * @return NULL
-     */
-    public function testSearch()
-    {
-/*         $db = &Horde_Kolab_Server::factory('test', */
-/*                                            array('data' => */
-/*                                                  array( */
-/*                                                      'cn=a' => array( */
-/*                                                          'dn' => 'cn=a', */
-/*                                                          'data' => array( */
-/*                                                              'a' => '1', */
-/*                                                              'b' => '1', */
-/*                                                              'c' => '1', */
-/*                                                          ) */
-/*                                                      ), */
-/*                                                      'cn=b' => array( */
-/*                                                          'dn' => 'cn=b', */
-/*                                                          'data' => array( */
-/*                                                              'a' => '1', */
-/*                                                              'b' => '2', */
-/*                                                              'c' => '2', */
-/*                                                          ) */
-/*                                                      ), */
-/*                                                      'cn=c' => array( */
-/*                                                          'dn' => 'cn=c', */
-/*                                                          'data' => array( */
-/*                                                              'a' => '1', */
-/*                                                              'b' => '2', */
-/*                                                              'c' => '3', */
-/*                                                          ) */
-/*                                                      ), */
-/*                                                      'cn=d' => array( */
-/*                                                          'dn' => 'cn=d', */
-/*                                                          'data' => array( */
-/*                                                              'a' => '2', */
-/*                                                              'b' => '2', */
-/*                                                              'c' => '1', */
-/*                                                          ) */
-/*                                                      ), */
-/*                                                  ) */
-/*                                            ) */
-/*         ); */
-
-/*         $a = $db->search('(c=1)'); */
-/*         $this->assertNoError($a); */
-/*         $this->assertEquals( */
-/*             array( */
-/*                 array( */
-/*                     'dn' => 'cn=a', */
-/*                     'data' => array( */
-/*                         'a' => '1', */
-/*                         'b' => '1', */
-/*                         'c' => '1', */
-/*                     ) */
-/*                 ), */
-/*                 array( */
-/*                     'dn' => 'cn=d', */
-/*                     'data' => array( */
-/*                         'a' => '2', */
-/*                         'b' => '2', */
-/*                         'c' => '1', */
-/*                     ) */
-/*                 ), */
-/*             ), */
-/*             $a */
-/*         ); */
-
-/*         $a = $db->_search('(c=3)'); */
-/*         $this->assertNoError($a); */
-/*         $this->assertEquals( */
-/*             array( */
-/*                 array( */
-/*                     'dn' => 'cn=c', */
-/*                     'data' => array( */
-/*                         'a' => '1', */
-/*                         'b' => '2', */
-/*                         'c' => '3', */
-/*                     ) */
-/*                 ), */
-/*             ), */
-/*             $a */
-/*         ); */
-
-/*         $a = $db->_search('(c=3)', array('a')); */
-/*         $this->assertNoError($a); */
-/*         $this->assertEquals( */
-/*             array( */
-/*                 array( */
-/*                     'dn' => 'cn=c', */
-/*                     'data' => array( */
-/*                         'a' => '1', */
-/*                     ) */
-/*                 ), */
-/*             ), */
-/*             $a */
-/*         ); */
-
-/*         $a = $db->_search('(&(a=1)(b=2))', array('a', 'b')); */
-/*         $this->assertNoError($a); */
-/*         $this->assertEquals( */
-/*             array( */
-/*                 array( */
-/*                     'dn' => 'cn=b', */
-/*                     'data' => array( */
-/*                         'a' => '1', */
-/*                         'b' => '2', */
-/*                     ) */
-/*                 ), */
-/*                 array( */
-/*                     'dn' => 'cn=c', */
-/*                     'data' => array( */
-/*                         'a' => '1', */
-/*                         'b' => '2', */
-/*                     ) */
-/*                 ), */
-/*             ), */
-/*             $a */
-/*         ); */
-
-/*         $a = $db->_search('(&(b=2))', array('b')); */
-/*         $this->assertNoError($a); */
-/*         $this->assertEquals( */
-/*             array( */
-/*                 array( */
-/*                     'dn' => 'cn=b', */
-/*                     'data' => array( */
-/*                         'b' => '2', */
-/*                     ) */
-/*                 ), */
-/*                 array( */
-/*                     'dn' => 'cn=c', */
-/*                     'data' => array( */
-/*                         'b' => '2', */
-/*                     ) */
-/*                 ), */
-/*                 array( */
-/*                     'dn' => 'cn=d', */
-/*                     'data' => array( */
-/*                         'b' => '2', */
-/*                     ) */
-/*                 ), */
-/*             ), */
-/*             $a */
-/*         ); */
-
-/*         $a = $db->_search('(!(b=2))', array('a', 'b')); */
-/*         $this->assertNoError($a); */
-/*         $this->assertEquals( */
-/*             array( */
-/*                 array( */
-/*                     'dn' => 'cn=a', */
-/*                     'data' => array( */
-/*                         'a' => '1', */
-/*                         'b' => '1', */
-/*                     ) */
-/*                 ), */
-/*             ), */
-/*             $a */
-/*         ); */
-
-/*         $a = $db->_search('(&(!(x=2))(b=1))', array('b')); */
-/*         $this->assertNoError($a); */
-/*         $this->assertEquals( */
-/*             array( */
-/*                 array( */
-/*                     'dn' => 'cn=a', */
-/*                     'data' => array( */
-/*                         'b' => '1', */
-/*                     ) */
-/*                 ), */
-/*             ), */
-/*             $a */
-/*         ); */
-    }
-
-}