Cleanup
authorJan Schneider <jan@horde.org>
Fri, 17 Sep 2010 11:18:26 +0000 (13:18 +0200)
committerJan Schneider <jan@horde.org>
Fri, 17 Sep 2010 12:29:18 +0000 (14:29 +0200)
framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Ldap.php
framework/Ldap/lib/Horde/Ldap.php
framework/Ldap/lib/Horde/Ldap/Entry.php
framework/Ldap/lib/Horde/Ldap/Filter.php
framework/Ldap/lib/Horde/Ldap/Ldif.php
framework/Ldap/lib/Horde/Ldap/RootDse.php
framework/Ldap/lib/Horde/Ldap/Schema.php
framework/Ldap/lib/Horde/Ldap/Search.php
framework/Ldap/package.xml

index 258d702..9c4fc5b 100644 (file)
@@ -66,8 +66,7 @@ implements Horde_Kolab_Server_Query_Interface
     {
         try {
             $filter = $this->_criteria->convert($this);
-            $result = $filter->asString();
-            return $result;
+            return (string)$filter;
         } catch (Horde_Kolab_Server_Exception $e) {
             return '';
         }
index 6ac2c59..25c50f0 100644 (file)
@@ -131,6 +131,7 @@ class Horde_Ldap
     public function __construct($config = array())
     {
         $this->setConfig($config);
+        $this->bind();
     }
 
     /**
@@ -344,7 +345,7 @@ class Horde_Ldap
              * If the above call failed, we try an v2 bind here and set the
              * version afterwards (with checking to the rootDSE). */
             try {
-                $msg = $this->bind();
+                $this->bind();
             } catch (Exception $e) {
                 /* The bind failed, discard link and save error msg.
                  * Then record the host as down and try next one. */
@@ -524,8 +525,8 @@ class Horde_Ldap
     public function add(Horde_Ldap_Entry $entry)
     {
         /* Rebind as the write DN. */
-        if (!empty($this->writedn)) {
-            $this->bind($this->writedn, $this->writepw);
+        if (!empty($this->_config['writedn'])) {
+            $this->bind($this->_config['writedn'], $this->_config['writepw']);
         }
 
         /* Continue attempting the add operation in a loop until we get a
@@ -541,7 +542,9 @@ class Horde_Ldap
             if (@ldap_add($link, $entry->dn(), $entry->getValues())) {
                 /* Entry successfully added, we should update its Horde_Ldap
                  * reference in case it is not set so far (fresh entry). */
-                if (!($entry->getLDAP() instanceof Horde_Ldap)) {
+                try {
+                    $entry->getLDAP();
+                } catch (Horde_Ldap_Exception $e) {
                     $entry->setLDAP($this);
                 }
                 /* Store that the entry is present inside the directory. */
@@ -552,13 +555,11 @@ class Horde_Ldap
             /* We have a failure.  What kind?  We may be able to reconnect and
              * try again. */
             $error_code = @ldap_errno($link);
-            $error_name = $this->errorMessage($error_code);
-
-            if ($error_name != 'LDAP_OPERATIONS_ERROR' |
+            if ($this->errorName($error_code) != 'LDAP_OPERATIONS_ERROR' |
                 !$this->_config['auto_reconnect']) {
                 /* Errors other than the above are just passed back to the user
                  * so he may react upon them. */
-                throw new Horde_Ldap_Exception('Could not add entry ' . $entry->dn() . ' ' . $error_name, $error_code);
+                throw new Horde_Ldap_Exception('Could not add entry ' . $entry->dn() . ': ' . ldap_err2str($error_code), $error_code);
             }
 
             /* The server has disconnected before trying the operation.  We
@@ -586,16 +587,17 @@ class Horde_Ldap
         }
 
         /* Re-bind as the write DN if not using searchdn credentials. */
-        if (!empty($this->writedn)) {
-            $this->bind($this->writedn, $this->writepw);
+        if (!empty($this->_config['writedn'])) {
+            $this->bind($this->_config['writedn'], $this->_config['writepw']);
         }
 
         /* Recursive delete searches for children and calls delete for them. */
         if ($recursive) {
             $result = @ldap_list($this->_link, $dn, '(objectClass=*)', array(null), 0, 0);
-            if (@ldap_count_entries($this->_link, $result)) {
+            if ($result && @ldap_count_entries($this->_link, $result)) {
                 for ($subentry = @ldap_first_entry($this->_link, $result);
-                     $subentry = @ldap_next_entry($this->_link, $subentry);) {
+                     $subentry;
+                     $subentry = @ldap_next_entry($this->_link, $subentry)) {
                     $this->delete(@ldap_get_dn($this->_link, $subentry), true);
                 }
             }
@@ -611,7 +613,8 @@ class Horde_Ldap
                 throw new Horde_Ldap_Exception('Could not add entry ' . $dn . ' no valid LDAP connection could be found.');
             }
 
-            if (@ldap_delete($link, $dn)) {
+            $s = @ldap_delete($link, $dn);
+            if ($s) {
                 /* Entry successfully deleted. */
                 return;
             }
@@ -619,24 +622,23 @@ class Horde_Ldap
             /* We have a failure.  What kind? We may be able to reconnect and
              * try again. */
             $error_code = @ldap_errno($link);
-            $error_name = $this->errorMessage($error_code);
-            if ($this->errorMessage($error_code) == 'LDAP_OPERATIONS_ERROR' &&
+            if ($this->errorName($error_code) == 'LDAP_OPERATIONS_ERROR' &&
                 $this->_config['auto_reconnect']) {
                 /* The server has disconnected before trying the operation.  We
                  * should try again, possibly with a different server. */
                 $this->_link = false;
                 $this->_reconnect();
-            } elseif ($error_code == 66) {
+            } elseif ($this->errorName($error_code) == 'LDAP_NOT_ALLOWED_ON_NONLEAF') {
                 /* Subentries present, server refused to delete.
                  * Deleting subentries is the clients responsibility, but since
                  * the user may not know of the subentries, we do not force
                  * that here but instead notify the developer so he may take
                  * actions himself. */
-                throw new Horde_Ldap_Exception('Could not delete entry ' . $dn . ' because of subentries. Use the recursive parameter to delete them.');
+                throw new Horde_Ldap_Exception('Could not delete entry ' . $dn . ' because of subentries. Use the recursive parameter to delete them.', $error_code);
             } else {
                 /* Errors other than the above catched are just passed back to
                  * the user so he may react upon them. */
-                throw new Horde_Ldap_Exception('Could not delete entry ' . $dn . ' ' . $error_name, $error_code);
+                throw new Horde_Ldap_Exception('Could not delete entry ' . $dn . ': ' . ldap_err2str($error_code), $error_code);
             }
         }
     }
@@ -681,8 +683,8 @@ class Horde_Ldap
     public function modify($entry, $parms = array())
     {
         /* Re-bind as the write DN. */
-        if (!empty($this->writedn)) {
-            $this->bind($this->writedn, $this->writepw);
+        if (!empty($this->_config['writedn'])) {
+            $this->bind($this->_config['writedn'], $this->_config['writepw']);
         }
 
         if (is_string($entry)) {
@@ -711,9 +713,9 @@ class Horde_Ldap
                     /* We have a failure.  What kind?  We may be able to
                      * reconnect and try again. */
                     $error_code = $e->getCode();
-                    $error_name = $this->errorMessage($error_code);
+                    $error_name = $this->errorName($error_code);
 
-                    if ($this->errorMessage($error_code) != 'LDAP_OPERATIONS_ERROR' ||
+                    if ($this->errorName($error_code) != 'LDAP_OPERATIONS_ERROR' ||
                         !$this->_config['auto_reconnect']) {
                         /* Errors other than the above catched are just passed
                          * back to the user so he may react upon them. */
@@ -784,7 +786,7 @@ class Horde_Ldap
         }
         if ($filter instanceof Horde_Ldap_Filter) {
             /* Convert Horde_Ldap_Filter to string representation. */
-            $filter = $filter->asString();
+            $filter = (string)$filter;
         }
 
         /* Setting search parameters.  */
@@ -832,27 +834,23 @@ class Horde_Ldap
                                       $sizelimit,
                                       $timelimit);
 
-            if ($err = @ldap_errno($link)) {
-                if ($err == 32) {
-                    /* Errorcode 32 = no such object, i.e. a nullresult. */
-                    return new Horde_Ldap_Search ($search, $this, $attributes);
+            if ($errno = @ldap_errno($link)) {
+                $err = $this->errorName($errno);
+                if ($err == 'LDAP_NO_SUCH_OBJECT' ||
+                    $err == 'LDAP_SIZELIMIT_EXCEEDED') {
+                    return new Horde_Ldap_Search($search, $this, $attributes);
                 }
-                if ($err == 4) {
-                    /* Errorcode 4 = sizelimit exeeded. */
-                    return new Horde_Ldap_Search ($search, $this, $attributes);
-                }
-                if ($err == 87) {
+                if ($err == 'LDAP_FILTER_ERROR') {
                     /* Bad search filter. */
-                    throw new Horde_Ldap_Exception($this->errorMessage($err) . '($filter)', $err);
+                    throw new Horde_Ldap_Exception(ldap_err2str($errno) . ' ($filter)', $errno);
                 }
-                if (($err == 1) && ($this->_config['auto_reconnect'])) {
-                    /* Errorcode 1 = LDAP_OPERATIONS_ERROR but we can try a
-                     * reconnect. */
+                if ($err == 'LDAP_OPERATIONS_ERROR' &&
+                    $this->_config['auto_reconnect']) {
                     $this->_link = false;
                     $this->_reconnect();
                 } else {
                     $msg = "\nParameters:\nBase: $base\nFilter: $filter\nScope: $scope";
-                    throw new Horde_Ldap_Exception($this->errorMessage($err) . $msg, $err);
+                    throw new Horde_Ldap_Exception(ldap_err2str($errno) . $msg, $errno);
                 }
             } else {
                 return new Horde_Ldap_Search($search, $this, $attributes);
@@ -881,12 +879,9 @@ class Horde_Ldap
         }
         $err = @ldap_errno($this->_link);
         if ($err) {
-            $msg = @ldap_err2str($err);
-        } else {
-            $err = 1000;
-            $msg = $this->errorMessage($err);
+            throw new Horde_Ldap_Exception(ldap_err2str($err), $err);
         }
-        throw new Horde_Ldap_Exception($msg, $err);
+        throw new Horde_Ldap_Exception('Unknown error');
     }
 
     /**
@@ -910,12 +905,9 @@ class Horde_Ldap
         }
         $err = @ldap_errno($this->_link);
         if ($err) {
-            $msg = @ldap_err2str($err);
-        } else {
-            $err = 1000;
-            $msg = $this->errorMessage($err);
+            throw new Horde_Ldap_Exception(ldap_err2str($err), $err);
         }
-        throw new Horde_Ldap_Exception($msg, $err);
+        throw new Horde_Ldap_Exception('Unknown error');
     }
 
     /**
@@ -956,10 +948,10 @@ class Horde_Ldap
 
         /* Check to see if the server supports this version first.
          *
-         * TODO: Why is this so horribly slow? $this->rootDSE() is
-         * very fast, as well as Horde_Ldap_RootDSE::fetch() seems
-         * like a problem at copiyng the object inside PHP??
-         * Additionally, this is not always reproducable... */
+         * TODO: Why is this so horribly slow? $this->rootDSE() is very fast,
+         * as well as Horde_Ldap_RootDse(). Seems like a problem at copying the
+         * object inside PHP??  Additionally, this is not always
+         * reproducable... */
         if (!$force) {
             $rootDSE = $this->rootDSE();
             $supported_versions = $rootDSE->getValue('supportedLDAPVersion');
@@ -968,6 +960,7 @@ class Horde_Ldap
             }
             $check_ok = in_array($version, $supported_versions);
         }
+        $check_ok = true;
 
         if ($force || $check_ok) {
             return $this->setOption('LDAP_OPT_PROTOCOL_VERSION', $version);
@@ -1009,11 +1002,11 @@ class Horde_Ldap
         if (@ldap_count_entries($this->_link, $result)) {
             return true;
         }
-        if (ldap_errno($this->_link) == 32) {
+        if ($this->errorName(@ldap_errno($this->_link)) == 'LDAP_NO_SUCH_OBJECT') {
             return false;
         }
-        if (ldap_errno($this->_link) != 0) {
-            throw new Horde_Ldap_Exception(ldap_error($this->_link), ldap_errno($this->_link));
+        if (@ldap_errno($this->_link)) {
+            throw new Horde_Ldap_Exception(@ldap_error($this->_link), @ldap_errno($this->_link));
         }
         return false;
     }
@@ -1161,7 +1154,7 @@ class Horde_Ldap
      *
      * @return string The description for the error.
      */
-    public function errorMessage($errorcode)
+    public static function errorName($errorcode)
     {
         $errorMessages = array(
             0x00 => 'LDAP_SUCCESS',
@@ -1240,7 +1233,7 @@ class Horde_Ldap
      *
      * @param array $attrs Array of attributes to search for.
      *
-     * @return Horde_Ldap_RootDSE Horde_Ldap_RootDSE object
+     * @return Horde_Ldap_RootDse Horde_Ldap_RootDse object
      * @throws Horde_Ldap_Exception
      */
     public function rootDSE(array $attrs = array())
@@ -1250,7 +1243,7 @@ class Horde_Ldap
         /* See if we need to fetch a fresh object, or if we already
          * requested this object with the same attributes. */
         if (!isset($this->_rootDSECache[$attrs_signature])) {
-            $this->_rootDSECache[$attrs_signature] = Horde_Ldap_RootDSE::fetch($this, $attrs);
+            $this->_rootDSECache[$attrs_signature] = new Horde_Ldap_RootDse($this, $attrs);
         }
 
         return $this->_rootDSECache[$attrs_signature];
@@ -1286,9 +1279,9 @@ class Horde_Ldap
             /* Store a temporary error message so subsequent calls to
              * schema() can detect that we are fetching the schema
              * already. Otherwise we will get an infinite loop at
-             * Horde_Ldap_Schema::fetch(). */
+             * Horde_Ldap_Schema. */
             $this->_schema = new Horde_Ldap_Exception('Schema not initialized');
-            $this->_schema = Horde_Ldap_Schema::fetch($this, $dn);
+            $this->_schema = new Horde_Ldap_Schema($this, $dn);
 
             /* If schema caching is active, advise the cache to store
              * the schema. */
index 9ec6c31..fb8387b 100644 (file)
@@ -277,7 +277,11 @@ class Horde_Ldap_Entry
             is_resource($this->_link)) {
             /* Fetch schema. */
             if ($this->_ldap instanceof Horde_Ldap) {
-                $schema = $this->_ldap->schema();
+                try {
+                    $schema = $this->_ldap->schema();
+                } catch (Horde_Ldap_Exception $e) {
+                    $schema = null;
+                }
             }
 
             /* Fetch attributes. */
@@ -626,9 +630,6 @@ class Horde_Ldap_Entry
     {
         /* Ensure we have a valid LDAP object. */
         $ldap = $this->getLDAP();
-        if (!($ldap instanceof Horde_Ldap)) {
-            throw new Horde_Ldap_Exception('The entries LDAP object is not valid');
-        }
 
         /* Get and check link. */
         $link = $ldap->getLink();
@@ -742,7 +743,7 @@ class Horde_Ldap_Entry
     public function getLDAP()
     {
         if (!($this->_ldap instanceof Horde_Ldap)) {
-            throw new Horde_Ldap_Exception('LDAP is not a valid Horde_Ldap object');
+            throw new Horde_Ldap_Exception('ldap property is not a valid Horde_Ldap object');
         }
         return $this->_ldap;
     }
index cc8aa85..de84c23 100644 (file)
 <?php
 /**
- * File containing the Horde_Ldap_Filter interface class.
+ * Object representation of a part of a LDAP filter.
  *
- * PHP version 5
+ * The purpose of this class is to easily build LDAP filters without having to
+ * worry about correct escaping etc.
  *
- * @category  Net
- * @package   Horde_Ldap
- * @author    Benedikt Hallinger <beni@php.net>
- * @author    Ben Klang <ben@alkaloid.net>
- * @copyright 2009 Benedikt Hallinger, The Horde Project
- * @license   http://www.gnu.org/licenses/lgpl-3.0.txt LGPLv3
- */
-
-/**
- * Includes
- */
-#require_once 'PEAR.php';
-#require_once 'Util.php';
-
-/**
- * Object representation of a part of a LDAP filter.
+ * A filter is built using several independent filter objects which are
+ * combined afterwards. This object works in two modes, depending how the
+ * object is created.
  *
- * This Class is not completely compatible to the PERL interface!
+ * If the object is created using the {@link create()} method, then this is a
+ * leaf-object. If the object is created using the {@link combine()} method,
+ * then this is a container object.
  *
- * The purpose of this class is, that users can easily build LDAP filters
- * without having to worry about right escaping etc.
- * A Filter is built using several independent filter objects
- * which are combined afterwards. This object works in two
- * modes, depending how the object is created.
- * If the object is created using the {@link create()} method, then this is a leaf-object.
- * If the object is created using the {@link combine()} method, then this is a container object.
+ * LDAP filters are defined in RFC 2254.
  *
- * LDAP filters are defined in RFC-2254 and can be found under
- * {@link http://www.ietf.org/rfc/rfc2254.txt}
+ * @see http://www.ietf.org/rfc/rfc2254.txt
  *
- * Here a quick copy&paste example:
+ * A short example:
  * <code>
- * $filter0 = Horde_Ldap_Filter::create('stars', 'equals', '***');
+ * $filter0     = Horde_Ldap_Filter::create('stars', 'equals', '***');
  * $filter_not0 = Horde_Ldap_Filter::combine('not', $filter0);
  *
- * $filter1 = Horde_Ldap_Filter::create('gn', 'begins', 'bar');
- * $filter2 = Horde_Ldap_Filter::create('gn', 'ends', 'baz');
- * $filter_comp = Horde_Ldap_Filter::combine('or',array($filter_not0, $filter1, $filter2));
+ * $filter1     = Horde_Ldap_Filter::create('gn', 'begins', 'bar');
+ * $filter2     = Horde_Ldap_Filter::create('gn', 'ends', 'baz');
+ * $filter_comp = Horde_Ldap_Filter::combine('or', array($filter_not0, $filter1, $filter2));
  *
- * echo $filter_comp->asString();
- * // This will output: (|(!(stars=\0x5c0x2a\0x5c0x2a\0x5c0x2a))(gn=bar *)(gn= *baz))
+ * echo (string)$filter_comp;
+ * // This will output: (|(!(stars=\0x5c0x2a\0x5c0x2a\0x5c0x2a))(gn=bar*)(gn=*baz))
  * // The stars in $filter0 are treaten as real stars unless you disable escaping.
  * </code>
  *
- * @category Net
- * @package  Horde_Ldap
- * @author   Benedikt Hallinger <beni@php.net>
- * @license  http://www.gnu.org/copyleft/lesser.html LGPL
- * @link     http://pear.php.net/package/Horde_Ldap/
+ * @category  Horde
+ * @package   Ldap
+ * @author    Benedikt Hallinger <beni@php.net>
+ * @author    Jan Schneider <jan@horde.org>
+ * @copyright 2009 Benedikt Hallinger
+ * @copyright 2010 The Horde Project
+ * @license   http://www.gnu.org/copyleft/lesser.html LGPL
  */
-class Horde_Ldap_Filter extends PEAR
+class Horde_Ldap_Filter
 {
     /**
-     * Storage for combination of filters
+     * Storage for combination of filters.
      *
-     * This variable holds a array of filter objects
-     * that should be combined by this filter object.
+     * This variable holds a array of filter objects that should be combined by
+     * this filter object.
      *
-     * @access protected
      * @var array
      */
-    protected $_subfilters = array();
+    protected $_filters = array();
 
     /**
-     * Match of this filter
+     * Operator for sub-filters.
      *
-     * If this is a leaf filter, then a matching rule is stored,
-     * if it is a container, then it is a logical operator
-     *
-     * @access protected
      * @var string
      */
-    protected $_match;
+    protected $_operator;
 
     /**
-     * Single filter
+     * Single filter.
      *
-     * If we operate in leaf filter mode,
-     * then the constructing method stores
-     * the filter representation here
+     * If this is a leaf filter, the filter representation is store here.
      *
-     * @acces private
      * @var string
      */
     protected $_filter;
 
     /**
-     * Create a new Horde_Ldap_Filter object and parse $filter.
+     * Constructor.
      *
-     * This is for PERL Net::LDAP interface.
      * Construction of Horde_Ldap_Filter objects should happen through either
      * {@link create()} or {@link combine()} which give you more control.
-     * However, you may use the perl iterface if you already have generated filters.
-     *
-     * @param string $filter LDAP filter string
+     * However, you may use the constructor if you already have generated
+     * filters.
      *
-     * @see parse()
+     * @param array $params List of object parameters
      */
-    public function __construct($filter = false)
+    protected function __construct(array $params)
     {
-        // The optional parameter must remain here, because otherwise create() crashes
-        if (false !== $filter) {
-            $filter_o = self::parse($filter);
-            if (PEAR::isError($filter_o)) {
-                $this->_filter = $filter_o; // assign error, so asString() can report it
-            } else {
-                $this->_filter = $filter_o->asString();
+        foreach ($params as $param => $value) {
+            if (in_array($param, array('filter', 'filters', 'operator'))) {
+                $this->{'_' . $param} = $value;
             }
         }
     }
 
     /**
-     * Constructor of a new part of a LDAP filter.
+     * Creates a new part of an LDAP filter.
      *
      * The following matching rules exists:
-     *    - equals:         One of the attributes values is exactly $value
-     *                      Please note that case sensitiviness is depends on the
-     *                      attributes syntax configured in the server.
-     *    - begins:         One of the attributes values must begin with $value
-     *    - ends:           One of the attributes values must end with $value
-     *    - contains:       One of the attributes values must contain $value
-     *    - present | any:  The attribute can contain any value but must be existent
-     *    - greater:        The attributes value is greater than $value
-     *    - less:           The attributes value is less than $value
-     *    - greaterOrEqual: The attributes value is greater or equal than $value
-     *    - lessOrEqual:    The attributes value is less or equal than $value
-     *    - approx:         One of the attributes values is similar to $value
-     *
-     * If $escape is set to true (default) then $value will be escaped
-     * properly. If it is set to false then $value will be treaten as raw filter value string.
-     * You should escape yourself using {@link Horde_Ldap_Util::escape_filter_value()}!
+     * - equals:         One of the attributes values is exactly $value.
+     *                   Please note that case sensitiviness depends on the
+     *                   attributes syntax configured in the server.
+     * - begins:         One of the attributes values must begin with $value.
+     * - ends:           One of the attributes values must end with $value.
+     * - contains:       One of the attributes values must contain $value.
+     * - present | any:  The attribute can contain any value but must exist.
+     * - greater:        The attributes value is greater than $value.
+     * - less:           The attributes value is less than $value.
+     * - greaterOrEqual: The attributes value is greater or equal than $value.
+     * - lessOrEqual:    The attributes value is less or equal than $value.
+     * - approx:         One of the attributes values is similar to $value.
+     *
+     * If $escape is set to true then $value will be escaped. If set to false
+     * then $value will be treaten as a raw filter value string.  You should
+     * then escape it yourself using {@link
+     * Horde_Ldap_Util::escape_filter_value()}.
      *
      * Examples:
      * <code>
-     *   // This will find entries that contain an attribute "sn" that ends with "foobar":
-     *   $filter = new Horde_Ldap_Filter('sn', 'ends', 'foobar');
+     * // This will find entries that contain an attribute "sn" that ends with
+     * // "foobar":
+     * $filter = Horde_Ldap_Filter::create('sn', 'ends', 'foobar');
      *
-     *   // This will find entries that contain an attribute "sn" that has any value set:
-     *   $filter = new Horde_Ldap_Filter('sn', 'any');
+     * // This will find entries that contain an attribute "sn" that has any
+     * // value set:
+     * $filter = Horde_Ldap_Filter::create('sn', 'any');
      * </code>
      *
-     * @param string  $attr_name Name of the attribute the filter should apply to
-     * @param string  $match     Matching rule (equals, begins, ends, contains, greater, less, greaterOrEqual, lessOrEqual, approx, any)
-     * @param string  $value     (optional) if given, then this is used as a filter
-     * @param boolean $escape    Should $value be escaped? (default: yes, see {@link Horde_Ldap_Util::escape_filter_value()} for detailed information)
+     * @param string  $attribute Name of the attribute the filter should apply
+     *                           to.
+     * @param string  $match     Matching rule (equals, begins, ends, contains,
+     *                           greater, less, greaterOrEqual, lessOrEqual,
+     *                           approx, any).
+     * @param string  $value     If given, then this is used as a filter value.
+     * @param boolean $escape    Should $value be escaped?
      *
-     * @return Horde_Ldap_Filter|Horde_Ldap_Error
+     * @return Horde_Ldap_Filter
+     * @throws Horde_Ldap_Exception
      */
-    public static function &create($attr_name, $match, $value = '', $escape = true)
+    public static function create($attribute, $match, $value = '',
+                                  $escape = true)
     {
-        $leaf_filter = new Horde_Ldap_Filter();
         if ($escape) {
             $array = Horde_Ldap_Util::escape_filter_value(array($value));
             $value = $array[0];
         }
-        switch (strtolower($match)) {
+
+        switch (Horde_String::lower($match)) {
         case 'equals':
-            $leaf_filter->_filter = '(' . $attr_name . '=' . $value . ')';
+            $filter = '(' . $attribute . '=' . $value . ')';
             break;
         case 'begins':
-            $leaf_filter->_filter = '(' . $attr_name . '=' . $value . '*)';
+            $filter = '(' . $attribute . '=' . $value . '*)';
             break;
         case 'ends':
-            $leaf_filter->_filter = '(' . $attr_name . '=*' . $value . ')';
+            $filter = '(' . $attribute . '=*' . $value . ')';
             break;
         case 'contains':
-            $leaf_filter->_filter = '(' . $attr_name . '=*' . $value . '*)';
+            $filter = '(' . $attribute . '=*' . $value . '*)';
             break;
         case 'greater':
-            $leaf_filter->_filter = '(' . $attr_name . '>' . $value . ')';
+            $filter = '(' . $attribute . '>' . $value . ')';
             break;
         case 'less':
-            $leaf_filter->_filter = '(' . $attr_name . '<' . $value . ')';
+            $filter = '(' . $attribute . '<' . $value . ')';
             break;
         case 'greaterorequal':
         case '>=':
-            $leaf_filter->_filter = '(' . $attr_name . '>=' . $value . ')';
+            $filter = '(' . $attribute . '>=' . $value . ')';
             break;
         case 'lessorequal':
         case '<=':
-            $leaf_filter->_filter = '(' . $attr_name . '<=' . $value . ')';
+            $filter = '(' . $attribute . '<=' . $value . ')';
             break;
         case 'approx':
         case '~=':
-            $leaf_filter->_filter = '(' . $attr_name . '~=' . $value . ')';
+            $filter = '(' . $attribute . '~=' . $value . ')';
             break;
         case 'any':
-        case 'present': // alias that may improve user code readability
-            $leaf_filter->_filter = '(' . $attr_name . '=*)';
+        case 'present':
+            $filter = '(' . $attribute . '=*)';
             break;
         default:
-            throw new Horde_Ldap_Exception('Horde_Ldap_Filter create error: matching rule "' . $match . '" not known!');
+            throw new Horde_Ldap_Exception('Matching rule "' . $match . '" unknown');
         }
-        return $leaf_filter;
+
+        return new Horde_Ldap_Filter(array('filter' => $filter));
+
     }
 
     /**
-     * Combine two or more filter objects using a logical operator
+     * Combines two or more filter objects using a logical operator.
+     *
+     * Example:
+     * <code>
+     * $filter = Horde_Ldap_Filter::combine('or', array($filter1, $filter2));
+     * </code>
      *
-     * This static method combines two or more filter objects and returns one single
-     * filter object that contains all the others.
-     * Call this method statically: $filter = Horde_Ldap_Filter('or', array($filter1, $filter2))
-     * If the array contains filter strings instead of filter objects, we will try to parse them.
+     * If the array contains filter strings instead of filter objects, they
+     * will be parsed.
      *
-     * @param string                 $log_op  The locicall operator. May be "and", "or", "not" or the subsequent logical equivalents "&", "|", "!"
-     * @param array|Horde_Ldap_Filter $filters array with Horde_Ldap_Filter objects
+     * @param string $operator
+     *     The logical operator, either "and", "or", "not" or the logical
+     *     equivalents "&", "|", "!".
+     * @param array|Horde_Ldap_Filter|string $filters
+     *     Array with Horde_Ldap_Filter objects and/or strings or a single
+     *     filter when using the "not" operator.
      *
-     * @return Horde_Ldap_Filter|Horde_Ldap_Error
-     * @static
+     * @return Horde_Ldap_Filter
+     * @throws Horde_Ldap_Exception
      */
-    public static function &combine($log_op, $filters)
+    public static function combine($operator, $filters)
     {
-        // substitude named operators to logical operators
-        if ($log_op == 'and') $log_op = '&';
-        if ($log_op == 'or')  $log_op = '|';
-        if ($log_op == 'not') $log_op = '!';
+        // Substitute named operators with logical operators.
+        switch ($operator) {
+        case 'and': $operator = '&'; break;
+        case 'or':  $operator = '|'; break;
+        case 'not': $operator = '!'; break;
+        }
 
-        // tests for sane operation
-        if ($log_op == '!') {
-            // Not-combination, here we only accept one filter object or filter string
+        // Tests for sane operation.
+        switch ($operator) {
+        case '!':
+            // Not-combination, here we only accept one filter object or filter
+            // string.
             if ($filters instanceof Horde_Ldap_Filter) {
                 $filters = array($filters); // force array
             } elseif (is_string($filters)) {
-                try {
-                    $filter_o = self::parse($filters);
-                } catch (Exception $e) {
-                    throw new Horde_Ldap_Exception('Horde_Ldap_Filter combine error: '.$e->getMessage());
-                }
-                $filters = array($filter_o);
+                $filters = array(self::parse($filters));
             } elseif (is_array($filters)) {
-                throw new Horde_Ldap_Exception('Horde_Ldap_Filter combine error: operator is "not" but $filter is an array!');
+                throw new Horde_Ldap_Exception('Operator is "not" but $filter is an array');
             } else {
-                throw new Horde_Ldap_Exception('Horde_Ldap_Filter combine error: operator is "not" but $filter is not a valid Horde_Ldap_Filter nor a filter string!');
+                throw new Horde_Ldap_Exception('Operator is "not" but $filter is not a valid Horde_Ldap_Filter nor a filter string');
             }
-        } elseif ($log_op == '&' || $log_op == '|') {
+            break;
+
+        case '&':
+        case '|':
             if (!is_array($filters) || count($filters) < 2) {
-                throw new Horde_Ldap_Exception('Horde_Ldap_Filter combine error: parameter $filters is not an array or contains less than two Horde_Ldap_Filter objects!');
+                throw new Horde_Ldap_Exception('Parameter $filters is not an array or contains less than two Horde_Ldap_Filter objects');
             }
-        } else {
-            throw new Horde_Ldap_Exception('Horde_Ldap_Filter combine error: logical operator is not known!');
+        break;
+
+        default:
+            throw new Horde_Ldap_Exception('Logical operator is unknown');
         }
 
-        $combined_filter = new Horde_Ldap_Filter();
-        foreach ($filters as $key => $testfilter) {     // check for errors
+        foreach ($filters as $key => $testfilter) {
+            // Check for errors.
             if (is_string($testfilter)) {
-                // string found, try to parse into an filter object
-                $filter_o = self::parse($testfilter);
-                $filters[$key] = $filter_o;
-            } elseif (!$testfilter instanceof Horde_Ldap_Filter) {
-                throw new Horde_Ldap_Exception('Horde_Ldap_Filter combine error: invalid object passed in array $filters!');
+                // String found, try to parse into an filter object.
+                $filters[$key] = self::parse($testfilter);
+            } elseif (!($testfilter instanceof Horde_Ldap_Filter)) {
+                throw new Horde_Ldap_Exception('Invalid object passed in array $filters!');
             }
         }
 
-        $combined_filter->_subfilters = $filters;
-        $combined_filter->_match      = $log_op;
-        return $combined_filter;
+        return new Horde_Ldap_Filter(array('filters' => $filters,
+                                           'operator' => $operator));
     }
 
     /**
-     * Parse FILTER into a Horde_Ldap_Filter object
+     * Parses a string into a Horde_Ldap_Filter object.
      *
-     * This parses an filter string into Horde_Ldap_Filter objects.
+     * @todo Leaf-mode: Do we need to escape at all? what about *-chars? Check
+     * for the need of encoding values, tackle problems (see code comments).
      *
-     * @param string $FILTER The filter string
+     * @param string $filter An LDAP filter string.
      *
-     * @access static
-     * @return Horde_Ldap_Filter|Horde_Ldap_Error
-     * @todo Leaf-mode: Do we need to escape at all? what about *-chars?check for the need of encoding values, tackle problems (see code comments)
+     * @return Horde_Ldap_Filter
+     * @throws Horde_Ldap_Exception
      */
-    public static function parse($FILTER)
+    public static function parse($filter)
     {
-        if (preg_match('/^\((.+?)\)$/', $FILTER, $matches)) {
-            if (in_array(substr($matches[1], 0, 1), array('!', '|', '&'))) {
-                // Subfilter processing: pass subfilters to parse() and combine
-                // the objects using the logical operator detected
-                // we have now something like "&(...)(...)(...)" but at least one part ("!(...)").
-                // Each subfilter could be an arbitary complex subfilter.
-
-                // extract logical operator and filter arguments
-                $log_op              = substr($matches[1], 0, 1);
-                $remaining_component = substr($matches[1], 1);
-
-                // split $remaining_component into individual subfilters
-                // we cannot use split() for this, because we do not know the
-                // complexiness of the subfilter. Thus, we look trough the filter
-                // string and just recognize ending filters at the first level.
-                // We record the index number of the char and use that information
-                // later to split the string.
-                $sub_index_pos = array();
-                $prev_char     = ''; // previous character looked at
-                $level         = 0;  // denotes the current bracket level we are,
-                                     //   >1 is too deep, 1 is ok, 0 is outside any
-                                     //   subcomponent
-                for ($curpos = 0; $curpos < strlen($remaining_component); $curpos++) {
-                    $cur_char = substr($remaining_component, $curpos, 1);
-
-                    // rise/lower bracket level
-                    if ($cur_char == '(' && $prev_char != '\\') {
-                        $level++;
-                    } elseif  ($cur_char == ')' && $prev_char != '\\') {
-                        $level--;
-                    }
-
-                    if ($cur_char == '(' && $prev_char == ')' && $level == 1) {
-                        array_push($sub_index_pos, $curpos); // mark the position for splitting
-                    }
-                    $prev_char = $cur_char;
-                }
-
-                // now perform the splits. To get also the last part, we
-                // need to add the "END" index to the split array
-                array_push($sub_index_pos, strlen($remaining_component));
-                $subfilters = array();
-                $oldpos = 0;
-                foreach ($sub_index_pos as $s_pos) {
-                    $str_part = substr($remaining_component, $oldpos, $s_pos - $oldpos);
-                    array_push($subfilters, $str_part);
-                    $oldpos = $s_pos;
-                }
-
-                // some error checking...
-                if (count($subfilters) == 1) {
-                    // only one subfilter found
-                } elseif (count($subfilters) > 1) {
-                    // several subfilters found
-                    if ($log_op == "!") {
-                        throw new Horde_Ldap_Exception("Filter parsing error: invalid filter syntax - NOT operator detected but several arguments given!");
-                    }
-                } else {
-                    // this should not happen unless the user specified a wrong filter
-                    throw new Horde_Ldap_Exception("Filter parsing error: invalid filter syntax - got operator '$log_op' but no argument!");
-                }
-
-                // Now parse the subfilters into objects and combine them using the operator
-                $subfilters_o = array();
-                foreach ($subfilters as $s_s) {
-                    $o = self::parse($s_s);
-                    array_push($subfilters_o, self::parse($s_s));
-                }
-
-                $filter_o = self::combine($log_op, $subfilters_o);
-                return $filter_o;
-
-            } else {
-                // This is one leaf filter component, do some syntax checks, then escape and build filter_o
-                // $matches[1] should be now something like "foo=bar"
+        if (!preg_match('/^\((.+?)\)$/', $filter, $matches)) {
+            throw new Horde_Ldap_Exception('Invalid filter syntax, filter components must be enclosed in round brackets');
+        }
 
-                // detect multiple leaf components
-                // [TODO] Maybe this will make problems with filters containing brackets inside the value
-                if (stristr($matches[1], ')(')) {
-                    throw new Horde_Ldap_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_Ldap_Exception("Filter parsing error: invalid filter syntax - unknown matching rule used");
-                    } else {
-                        $filter_o          = new Horde_Ldap_Filter();
-                        // [TODO]: Do we need to escape at all? what about *-chars user provide and that should remain special?
-                        //         I think, those prevent escaping! We need to check against PERL Net::LDAP!
-                        // $value_arr         = Horde_Ldap_Util::escape_filter_value(array($filter_parts[2]));
-                        // $value             = $value_arr[0];
-                        $value             = $filter_parts[2];
-                        $filter_o->_filter = '('.$filter_parts[0].$filter_parts[1].$value.')';
-                        return $filter_o;
-                    }
-                }
-            }
+        if (in_array(substr($matches[1], 0, 1), array('!', '|', '&'))) {
+            return self::_parseCombination($matches[1]);
         } else {
-               // ERROR: Filter components must be enclosed in round brackets
-               throw new Horde_Ldap_Exception("Filter parsing error: invalid filter syntax - filter components must be enclosed in round brackets");
+            return self::_parseLeaf($matches[1]);
         }
     }
 
     /**
-     * Get the string representation of this filter
+     * Parses combined subfilter strings.
      *
-     * This method runs through all filter objects and creates
-     * the string representation of the filter. If this
-     * filter object is a leaf filter, then it will return
-     * the string representation of this filter.
+     * Passes subfilters to parse() and combines the objects using the logical
+     * operator detected.  Each subfilter could be an arbitary complex
+     * subfilter.
      *
-     * @return string|Horde_Ldap_Error
+     * @param string $filter An LDAP filter string.
+     *
+     * @return Horde_Ldap_Filter
+     * @throws Horde_Ldap_Exception
      */
-    public function asString()
+    protected static function _parseCombination($filter)
     {
-        if ($this->isLeaf()) {
-            $return = $this->_filter;
-        } else {
-            $return = '';
-            foreach ($this->_subfilters as $filter) {
-                $return = $return.$filter->asString();
+        // Extract logical operator and filter arguments.
+        $operator = substr($filter, 0, 1);
+        $filter = substr($filter, 1);
+
+        // Split $filter into individual subfilters. We cannot use split() for
+        // this, because we do not know the complexiness of the
+        // subfilter. Thus, we look trough the filter string and just recognize
+        // ending filters at the first level. We record the index number of the
+        // char and use that information later to split the string.
+        $sub_index_pos = array();
+        // Previous character looked at.
+        $prev_char = '';
+        // Denotes the current bracket level we are, >1 is too deep, 1 is ok, 0
+        // is outside any subcomponent.
+        $level = 0;
+        for ($curpos = 0; $curpos < strlen($filter); $curpos++) {
+            $cur_char = $filter{$curpos};
+
+            // Rise/lower bracket level.
+            if ($cur_char == '(' && $prev_char != '\\') {
+                $level++;
+            } elseif ($cur_char == ')' && $prev_char != '\\') {
+                $level--;
+            }
+
+            if ($cur_char == '(' && $prev_char == ')' && $level == 1) {
+                // Mark the position for splitting.
+                array_push($sub_index_pos, $curpos);
             }
-            $return = '(' . $this->_match . $return . ')';
+            $prev_char = $cur_char;
         }
-        return $return;
-    }
 
-    /**
-     * Alias for perl interface as_string()
-     *
-     * @see asString()
-     * @return string|Horde_Ldap_Error
-     */
-    public function as_string()
-    {
-        return $this->asString();
-    }
+        // Now perform the splits. To get the last part too, we need to add the
+        // "END" index to the split array.
+        array_push($sub_index_pos, strlen($filter));
+        $subfilters = array();
+        $oldpos = 0;
+        foreach ($sub_index_pos as $s_pos) {
+            $str_part = substr($filter, $oldpos, $s_pos - $oldpos);
+            array_push($subfilters, $str_part);
+            $oldpos = $s_pos;
+        }
 
-    /**
-     * Print the text representation of the filter to FH, or the currently selected output handle if FH is not given
-     *
-     * This method is only for compatibility to the perl interface.
-     * However, the original method was called "print" but due to PHP language restrictions,
-     * we can't have a print() method.
-     *
-     * @param resource $FH (optional) A filehandle resource
-     *
-     * @return true|Horde_Ldap_Error
-     */
-    public function printMe($FH = false)
-    {
-        if (!is_resource($FH)) {
-            $filter_str = $this->asString();
-            print($filter_str);
-        } else {
-            $filter_str = $this->asString();
-            $res = @fwrite($FH, $this->asString());
-            if ($res == false) {
-                throw new Horde_Ldap_Exception("Unable to write filter string to filehandle \$FH!");
+        // Some error checking...
+        if (count($subfilters) == 1) {
+            // Only one subfilter found.
+        } elseif (count($subfilters) > 1) {
+            // Several subfilters found.
+            if ($operator == '!') {
+                throw new Horde_Ldap_Exception('Invalid filter syntax: NOT operator detected but several arguments given');
             }
+        } else {
+            // This should not happen unless the user specified a wrong filter.
+            throw new Horde_Ldap_Exception('Invalid filter syntax: got operator ' . $operator . ' but no argument');
+        }
+
+        // Now parse the subfilters into objects and combine them using the
+        // operator.
+        $subfilters_o = array();
+        foreach ($subfilters as $s_s) {
+            $o = self::parse($s_s);
+            array_push($subfilters_o, self::parse($s_s));
+        }
+        if (count($subfilters_o) == 1) {
+            $subfilters_o = $subfilters_o[0];
         }
-        return true;
+
+        return self::combine($operator, $subfilters_o);
     }
 
     /**
-     * This can be used to escape a string to provide a valid LDAP-Filter.
-     *
-     * LDAP will only recognise certain characters as the
-     * character istself if they are properly escaped. This is
-     * what this method does.
-     * The method can be called statically, so you can use it outside
-     * for your own purposes (eg for escaping only parts of strings)
+     * Parses a single leaf component.
      *
-     * In fact, this is just a shorthand to {@link Horde_Ldap_Util::escape_filter_value()}.
-     * For upward compatibiliy reasons you are strongly encouraged to use the escape
-     * methods provided by the Horde_Ldap_Util class.
+     * @param string $filter An LDAP filter string.
      *
-     * @param string $value Any string who should be escaped
-     *
-     * @static
-     * @return string         The string $string, but escaped
-     * @deprecated  Do not use this method anymore, instead use Horde_Ldap_Util::escape_filter_value() directly
+     * @return Horde_Ldap_Filter
+     * @throws Horde_Ldap_Exception
      */
-    public static function escape($value)
+    protected static function _parseLeaf($filter)
     {
-        $return = Horde_Ldap_Util::escape_filter_value(array($value));
-        return $return[0];
+        // Detect multiple leaf components.
+        // [TODO] Maybe this will make problems with filters containing
+        // brackets inside the value.
+        if (strpos($filter, ')(')) {
+            throw new Horde_Ldap_Exception('Invalid filter syntax: multiple leaf components detected');
+        }
+
+        $filter_parts = preg_split('/(?<!\\\\)(=|=~|>|<|>=|<=)/', $filter, 2, PREG_SPLIT_DELIM_CAPTURE);
+        if (count($filter_parts) != 3) {
+            throw new Horde_Ldap_Exception('Invalid filter syntax: unknown matching rule used');
+        }
+
+        // [TODO]: Do we need to escape at all? what about *-chars user provide
+        //         and that should remain special?  I think, those prevent
+        //         escaping! We need to check against PERL Net::LDAP!
+        // $value_arr = Horde_Ldap_Util::escape_filter_value(array($filter_parts[2]));
+        // $value     = $value_arr[0];
+
+        return new Horde_Ldap_Filter(array('filter' => '(' . $filter_parts[0] . $filter_parts[1] . $filter_parts[2] . ')'));
     }
 
     /**
-     * Is this a container or a leaf filter object?
+     * Returns the string representation of this filter.
+     *
+     * This method runs through all filter objects and creates the string
+     * representation of the filter.
      *
-     * @access protected
-     * @return boolean
+     * @return string
      */
-    protected function isLeaf()
+    public function __toString()
     {
-        if (count($this->_subfilters) > 0) {
-            return false; // Container!
-        } else {
-            return true; // Leaf!
+        if (!count($this->_filters)) {
+            return $this->_filter;
+        }
+
+        $return = '';
+        foreach ($this->_filters as $filter) {
+            $return .= (string)$filter;
         }
+
+        return '(' . $this->_operator . $return . ')';
     }
 }
-?>
index 96e2fa2..e90a87d 100644 (file)
@@ -36,7 +36,7 @@
  * @see       http://www.ietf.org/rfc/rfc2849.txt
  * @todo      LDAPv3 controls are not implemented yet
  */
-class Horde_Ldap_LDIF
+class Horde_Ldap_Ldif
 {
     /**
      * Options.
@@ -183,7 +183,7 @@ class Horde_Ldap_LDIF
             return;
         }
 
-        switch ($imode) {
+        switch ($mode) {
         case 'r':
             if (!file_exists($file)) {
                 throw new Horde_Ldap_Exception('Unable to open ' . $file . ' for reading: file not found');
index 31b5e69..0b7d35d 100644 (file)
@@ -1,64 +1,36 @@
 <?php
 /**
- * File containing the Horde_Ldap_RootDSE interface class.
+ * Getting the rootDSE entry of a LDAP server.
  *
- * PHP version 5
- *
- * @category  Net
- * @package   Horde_Ldap
+ * @category  Horde
+ * @package   Ldap
  * @author    Jan Wagner <wagner@netsols.de>
+ * @author    Jan Schneider <jan@horde.org>
  * @copyright 2009 Jan Wagner
- * @license   http://www.gnu.org/licenses/lgpl-3.0.txt LGPLv3
- * @version   SVN: $Id: RootDSE.php 286718 2009-08-03 07:30:49Z beni $
- * @link      http://pear.php.net/package/Horde_Ldap/
- */
-
-/**
- * Includes
- */
-#require_once 'PEAR.php';
-
-/**
- * Getting the rootDSE entry of a LDAP server
- *
- * @category Net
- * @package  Horde_Ldap
- * @author   Jan Wagner <wagner@netsols.de>
- * @license  http://www.gnu.org/copyleft/lesser.html LGPL
- * @link     http://pear.php.net/package/Horde_Ldap2/
+ * @copyright 2010 The Horde Project
+ * @license   http://www.gnu.org/copyleft/lesser.html LGPL
  */
-class Horde_Ldap_RootDSE
+class Horde_Ldap_RootDse
 {
     /**
-     * @access protected
      * @var object Horde_Ldap_Entry
-     **/
-    protected $_entry;
-
-    /**
-     * Class constructor
-     *
-     * @param Horde_Ldap_Entry &$entry Horde_Ldap_Entry object of the RootDSE
      */
-    protected function __construct(&$entry)
-    {
-        $this->_entry = $entry;
-    }
+    protected $_entry;
 
     /**
-     * Fetches a RootDSE object from an LDAP connection
+     * Constructor.
      *
-     * @param Horde_Ldap $ldap  Directory from which the RootDSE should be fetched
-     * @param array     $attrs Array of attributes to search for
+     * Fetches a RootDSE object from an LDAP connection.
      *
-     * @access static
-     * @return Horde_Ldap_RootDSE
+     * @param Horde_Ldap $ldap  Directory from which the RootDSE should be
+     *                          fetched.
+     * @param array      $attrs Array of attributes to search for.
      *
      * @throws Horde_Ldap_Exception
      */
-    public static function fetch(Horde_Ldap $ldap, $attrs = null)
+    public function __construct(Horde_Ldap $ldap, $attrs = null)
     {
-        if (is_array($attrs) && count($attrs) > 0 ) {
+        if (is_array($attrs) && count($attrs)) {
             $attributes = $attrs;
         } else {
             $attributes = array('vendorName',
@@ -69,52 +41,39 @@ class Horde_Ldap_RootDSE
                                 'supportedControl',
                                 'supportedSASLMechanisms',
                                 'supportedLDAPVersion',
-                                'subschemaSubentry' );
+                                'subschemaSubentry');
         }
-        $result = $ldap->search('', '(objectClass=*)', array('attributes' => $attributes, 'scope' => 'base'));
+        $result = $ldap->search('', '(objectClass=*)',
+                                array('attributes' => $attributes,
+                                      'scope' => 'base'));
         $entry = $result->shiftEntry();
-        if (false === $entry) {
+        if (!$entry) {
             throw new Horde_Ldap_Exception('Could not fetch RootDSE entry');
         }
-        $ret = new Horde_Ldap_RootDSE($entry);
-        return $ret;
+        $this->_entry = $entry;
     }
 
     /**
-     * Gets the requested attribute value
-     *
-     * Same usuage as {@link Horde_Ldap_Entry::getValue()}
+     * Returns the requested attribute value.
      *
-     * @param string $attr    Attribute name
-     * @param array  $options Array of options
+     * @see Horde_Ldap_Entry::getValue()
      *
-     * @access public
-     * @return mixed Horde_Ldap_Error object or attribute values
-     * @see Horde_Ldap_Entry::get_value()
-     */
-    public function getValue($attr = '', $options = '')
-    {
-        return $this->_entry->get_value($attr, $options);
-    }
-
-    /**
-     * Alias function of getValue() for perl-ldap interface
+     * @param string $attr    Attribute name.
+     * @param array  $options Array of options.
      *
-     * @see getValue()
-     * @return mixed
+     * @return string|array Attribute value(s).
+     * @throws Horde_Ldap_Exception
      */
-    public function get_value()
+    public function getValue($attr, $options = '')
     {
-        $args = func_get_args();
-        return call_user_func_array(array( &$this, 'getValue' ), $args);
+        return $this->_entry->getValue($attr, $options);
     }
 
     /**
-     * Determines if the extension is supported
+     * Determines if the extension is supported.
      *
-     * @param array $oids Array of oids to check
+     * @param array $oids Array of OIDs to check.
      *
-     * @access public
      * @return boolean
      */
     public function supportedExtension($oids)
@@ -123,23 +82,10 @@ class Horde_Ldap_RootDSE
     }
 
     /**
-     * Alias function of supportedExtension() for perl-ldap interface
+     * Determines if the version is supported.
      *
-     * @see supportedExtension()
-     * @return boolean
-     */
-    public function supported_extension()
-    {
-        $args = func_get_args();
-        return call_user_func_array(array( &$this, 'supportedExtension'), $args);
-    }
-
-    /**
-     * Determines if the version is supported
+     * @param array $versions Versions to check.
      *
-     * @param array $versions Versions to check
-     *
-     * @access public
      * @return boolean
      */
     public function supportedVersion($versions)
@@ -148,23 +94,10 @@ class Horde_Ldap_RootDSE
     }
 
     /**
-     * Alias function of supportedVersion() for perl-ldap interface
-     *
-     * @see supportedVersion()
-     * @return boolean
-     */
-    public function supported_version()
-    {
-        $args = func_get_args();
-        return call_user_func_array(array(&$this, 'supportedVersion'), $args);
-    }
-
-    /**
-     * Determines if the control is supported
+     * Determines if the control is supported.
      *
-     * @param array $oids Control oids to check
+     * @param array $oids Control OIDs to check.
      *
-     * @access public
      * @return boolean
      */
     public function supportedControl($oids)
@@ -173,23 +106,10 @@ class Horde_Ldap_RootDSE
     }
 
     /**
-     * Alias function of supportedControl() for perl-ldap interface
+     * Determines if the sasl mechanism is supported.
      *
-     * @see supportedControl()
-     * @return boolean
-     */
-    public function supported_control()
-    {
-        $args = func_get_args();
-        return call_user_func_array(array(&$this, 'supportedControl' ), $args);
-    }
-
-    /**
-     * Determines if the sasl mechanism is supported
+     * @param array $mechlist SASL mechanisms to check.
      *
-     * @param array $mechlist SASL mechanisms to check
-     *
-     * @access public
      * @return boolean
      */
     public function supportedSASLMechanism($mechlist)
@@ -198,37 +118,25 @@ class Horde_Ldap_RootDSE
     }
 
     /**
-     * Alias function of supportedSASLMechanism() for perl-ldap interface
+     * Checks for existance of value in attribute.
      *
-     * @see supportedSASLMechanism()
-     * @return boolean
-     */
-    public function supported_sasl_mechanism()
-    {
-        $args = func_get_args();
-        return call_user_func_array(array(&$this, 'supportedSASLMechanism'), $args);
-    }
-
-    /**
-     * Checks for existance of value in attribute
-     *
-     * @param array  $values values to check
-     * @param string $attr   attribute name
+     * @param array  $values Values to check.
+     * @param string $attr   Attribute name.
      *
-     * @access protected
      * @return boolean
      */
     protected function checkAttr($values, $attr)
     {
-        if (!is_array($values)) $values = array($values);
+        if (!is_array($values)) {
+            $values = array($values);
+        }
 
         foreach ($values as $value) {
-            if (!@in_array($value, $this->get_value($attr, 'all'))) {
+            if (!in_array($value, $this->get_value($attr, 'all'))) {
                 return false;
             }
         }
+
         return true;
     }
 }
-
-?>
index 26e95c2..eb56f44 100644 (file)
@@ -1,36 +1,5 @@
 <?php
 /**
- * File containing the Horde_Ldap_Schema interface class.
- *
- * PHP version 5
- *
- * @category  Net
- * @package   Horde_Ldap
- * @author    Jan Wagner <wagner@netsols.de>
- * @author    Benedikt Hallinger <beni@php.net>
- * @copyright 2009 Jan Wagner, Benedikt Hallinger
- * @license   http://www.gnu.org/licenses/lgpl-3.0.txt LGPLv3
- * @version   SVN: $Id: Schema.php 286718 2009-08-03 07:30:49Z beni $
- * @link      http://pear.php.net/package/Horde_Ldap/
- * @todo see the comment at the end of the file
- */
-
-/**
- * Syntax definitions
- *
- * Please don't forget to add binary attributes to isBinary() below
- * to support proper value fetching from Horde_Ldap_Entry
- */
-define('HORDE_LDAP_SYNTAX_BOOLEAN',            '1.3.6.1.4.1.1466.115.121.1.7');
-define('HORDE_LDAP_SYNTAX_DIRECTORY_STRING',   '1.3.6.1.4.1.1466.115.121.1.15');
-define('HORDE_LDAP_SYNTAX_DISTINGUISHED_NAME', '1.3.6.1.4.1.1466.115.121.1.12');
-define('HORDE_LDAP_SYNTAX_INTEGER',            '1.3.6.1.4.1.1466.115.121.1.27');
-define('HORDE_LDAP_SYNTAX_JPEG',               '1.3.6.1.4.1.1466.115.121.1.28');
-define('HORDE_LDAP_SYNTAX_NUMERIC_STRING',     '1.3.6.1.4.1.1466.115.121.1.36');
-define('HORDE_LDAP_SYNTAX_OID',                '1.3.6.1.4.1.1466.115.121.1.38');
-define('HORDE_LDAP_SYNTAX_OCTET_STRING',       '1.3.6.1.4.1.1466.115.121.1.40');
-
-/**
  * Load an LDAP Schema and provide information
  *
  * This class takes a Subschema entry, parses this information
@@ -38,36 +7,50 @@ define('HORDE_LDAP_SYNTAX_OCTET_STRING',       '1.3.6.1.4.1.1466.115.121.1.40');
  * inspired by perl-ldap( http://perl-ldap.sourceforge.net).
  * You will find portions of their implementation in here.
  *
- * @category Net
- * @package  Horde_Ldap
- * @author   Jan Wagner <wagner@netsols.de>
- * @author   Benedikt Hallinger <beni@php.net>
- * @license  http://www.gnu.org/copyleft/lesser.html LGPL
- * @link     http://pear.php.net/package/Horde_Ldap2/
+ * @category  Horde
+ * @package   Ldap
+ * @author    Jan Wagner <wagner@netsols.de>
+ * @author    Benedikt Hallinger <beni@php.net>
+ * @author    Jan Schneider <jan@horde.org>
+ * @copyright 2009 Jan Wagner, Benedikt Hallinger
+ * @copyright 2010 The Horde Project
+ * @license   http://www.gnu.org/copyleft/lesser.html LGPL
  */
 class Horde_Ldap_Schema
 {
     /**
-     * Map of entry types to ldap attributes of subschema entry
+     * Syntax definitions.
+     *
+     * Please don't forget to add binary attributes to isBinary() below to
+     * support proper value fetching from Horde_Ldap_Entry.
+     */
+    const SYNTAX_BOOLEAN =            '1.3.6.1.4.1.1466.115.121.1.7';
+    const SYNTAX_DIRECTORY_STRING =   '1.3.6.1.4.1.1466.115.121.1.15';
+    const SYNTAX_DISTINGUISHED_NAME = '1.3.6.1.4.1.1466.115.121.1.12';
+    const SYNTAX_INTEGER =            '1.3.6.1.4.1.1466.115.121.1.27';
+    const SYNTAX_JPEG =               '1.3.6.1.4.1.1466.115.121.1.28';
+    const SYNTAX_NUMERIC_STRING =     '1.3.6.1.4.1.1466.115.121.1.36';
+    const SYNTAX_OID =                '1.3.6.1.4.1.1466.115.121.1.38';
+    const SYNTAX_OCTET_STRING =       '1.3.6.1.4.1.1466.115.121.1.40';
+
+    /**
+     * Map of entry types to LDAP attributes of subschema entry.
      *
-     * @access public
      * @var array
      */
     public $types = array(
-            'attribute'        => 'attributeTypes',
-            'ditcontentrule'   => 'dITContentRules',
-            'ditstructurerule' => 'dITStructureRules',
-            'matchingrule'     => 'matchingRules',
-            'matchingruleuse'  => 'matchingRuleUse',
-            'nameform'         => 'nameForms',
-            'objectclass'      => 'objectClasses',
-            'syntax'           => 'ldapSyntaxes'
-        );
+        'attribute'        => 'attributeTypes',
+        'ditcontentrule'   => 'dITContentRules',
+        'ditstructurerule' => 'dITStructureRules',
+        'matchingrule'     => 'matchingRules',
+        'matchingruleuse'  => 'matchingRuleUse',
+        'nameform'         => 'nameForms',
+        'objectclass'      => 'objectClasses',
+        'syntax'           => 'ldapSyntaxes' );
 
     /**
      * Array of entries belonging to this type
      *
-     * @access protected
      * @var array
      */
     protected $_attributeTypes    = array();
@@ -81,143 +64,139 @@ class Horde_Ldap_Schema
 
 
     /**
-     * hash of all fetched oids
+     * Hash of all fetched OIDs.
      *
-     * @access protected
      * @var array
      */
     protected $_oids = array();
 
     /**
-     * Tells if the schema is initialized
+     * Whether the schema is initialized.
      *
-     * @access protected
-     * @var boolean
      * @see parse(), get()
+     * @var boolean
      */
     protected $_initialized = false;
 
     /**
-     * Fetch the Schema from an LDAP connection
+     * Constructor.
+     *
+     * Fetches the Schema from an LDAP connection.
      *
-     * @param Horde_Ldap $ldap LDAP connection
-     * @param string    $dn   (optional) Subschema entry dn
+     * @param Horde_Ldap $ldap LDAP connection.
+     * @param string     $dn   Subschema entry DN.
      *
-     * @access public
-     * @return Horde_Ldap_Schema|Horde_Ldap_Error
+     * @throws Horde_Ldap_Exception
      */
-    public function fetch(Horde_Ldap $ldap, $dn = null)
+    public function __construct(Horde_Ldap $ldap, $dn = null)
     {
-        $schema_o = new Horde_Ldap_Schema();
-
         if (is_null($dn)) {
-            // get the subschema entry via root dse
+            // Get the subschema entry via rootDSE.
             $dse = $ldap->rootDSE(array('subschemaSubentry'));
-           $base = $dse->getValue('subschemaSubentry', 'single');
-           $dn = $base;
+            $base = $dse->getValue('subschemaSubentry', 'single');
+            $dn = $base;
         }
 
-        // Support for buggy LDAP servers (e.g. Siemens DirX 6.x) that incorrectly
-        // call this entry subSchemaSubentry instead of subschemaSubentry.
-        // Note the correct case/spelling as per RFC 2251.
+        // Support for buggy LDAP servers (e.g. Siemens DirX 6.x) that
+        // incorrectly call this entry subSchemaSubentry instead of
+        // subschemaSubentry. Note the correct case/spelling as per RFC 2251.
         if (is_null($dn)) {
-            // get the subschema entry via root dse
+            // Get the subschema entry via rootDSE.
             $dse = $ldap->rootDSE(array('subSchemaSubentry'));
-           $base = $dse->getValue('subSchemaSubentry', 'single');
-           $dn = $base;
+            $base = $dse->getValue('subSchemaSubentry', 'single');
+            $dn = $base;
         }
 
-        // Final fallback case where there is no subschemaSubentry attribute
-        // in the root DSE (this is a bug for an LDAP v3 server so report this
-        // to your LDAP vendor if you get this far).
+        // Final fallback in case there is no subschemaSubentry attribute in
+        // the root DSE (this is a bug for an LDAPv3 server so report this to
+        // your LDAP vendor if you get this far).
         if (is_null($dn)) {
             $dn = 'cn=Subschema';
         }
 
-        // fetch the subschema entry
+        // Fetch the subschema entry.
         $result = $ldap->search($dn, '(objectClass=*)',
-                                array('attributes' => array_values($schema_o->types),
-                                        'scope' => 'base'));
+                                array('attributes' => array_values($this->types),
+                                      'scope' => 'base'));
         $entry = $result->shiftEntry();
-        if (!$entry instanceof Horde_Ldap_Entry) {
+        if (!($entry instanceof Horde_Ldap_Entry)) {
             throw new Horde_Ldap_Exception('Could not fetch Subschema entry');
         }
 
-        $schema_o->parse($entry);
-        return $schema_o;
+        $this->parse($entry);
     }
 
     /**
-     * Return a hash of entries for the given type
+     * Returns a hash of entries for the given type.
      *
-     * Returns a hash of entry for th givene type. Types may be:
-     * objectclasses, attributes, ditcontentrules, ditstructurerules, matchingrules,
-     * matchingruleuses, nameforms, syntaxes
+     * Types may be: objectclasses, attributes, ditcontentrules,
+     * ditstructurerules, matchingrules, matchingruleuses, nameforms, syntaxes.
      *
-     * @param string $type Type to fetch
+     * @param string $type Type to fetch.
      *
-     * @access public
-     * @return array|Horde_Ldap_Error Array or Horde_Ldap_Error
+     * @return array
+     * @throws Horde_Ldap_Exception
      */
-    public function &getAll($type)
+    public function getAll($type)
     {
-        $map = array('objectclasses'     => &$this->_objectClasses,
-                     'attributes'        => &$this->_attributeTypes,
-                     'ditcontentrules'   => &$this->_dITContentRules,
-                     'ditstructurerules' => &$this->_dITStructureRules,
-                     'matchingrules'     => &$this->_matchingRules,
-                     'matchingruleuses'  => &$this->_matchingRuleUse,
-                     'nameforms'         => &$this->_nameForms,
-                     'syntaxes'          => &$this->_ldapSyntaxes );
-
-        $key = strtolower($type);
-       if (!key_exists($key, $map)) {
-         throw new Horde_Ldap_Exception("Unknown type $type");
-       }
+        $map = array('objectclasses'     => $this->_objectClasses,
+                     'attributes'        => $this->_attributeTypes,
+                     'ditcontentrules'   => $this->_dITContentRules,
+                     'ditstructurerules' => $this->_dITStructureRules,
+                     'matchingrules'     => $this->_matchingRules,
+                     'matchingruleuses'  => $this->_matchingRuleUse,
+                     'nameforms'         => $this->_nameForms,
+                     'syntaxes'          => $this->_ldapSyntaxes);
+
+        $key = Horde_String::lower($type);
+        if (!isset($map[$key])) {
+            throw new Horde_Ldap_Exception("Unknown type $type");
+        }
+
         return $map[$key];
     }
 
     /**
-     * Return a specific entry
+     * Returns a specific entry.
      *
-     * @param string $type Type of name
-     * @param string $name Name or OID to fetch
+     * @param string $type Type of name.
+     * @param string $name Name or OID to fetch.
      *
-     * @access public
-     * @return mixed Entry or Horde_Ldap_Error
+     * @return mixed
+     * @throws Horde_Ldap_Exception
      */
-    public function &get($type, $name)
+    public function get($type, $name)
     {
-        if ($this->_initialized) {
-            $type = strtolower($type);
-            if (false == key_exists($type, $this->types)) {
-                throw new Horde_Ldap_Exception("No such type $type");
-            }
+        if (!$this->_initialized) {
+            return null;
+        }
 
-            $name     = strtolower($name);
-            $type_var = &$this->{'_' . $this->types[$type]};
+        $type = Horde_String::lower($type);
+        if (!isset($this->types[$type])) {
+            throw new Horde_Ldap_Exception("No such type $type");
+        }
 
-            if (key_exists($name, $type_var)) {
-                return $type_var[$name];
-            } elseif (key_exists($name, $this->_oids) && $this->_oids[$name]['type'] == $type) {
-                return $this->_oids[$name];
-            } else {
-                throw new Horde_Ldap_Exception("Could not find $type $name");
-            }
-        } else {
-            $return = null;
-            return $return;
+        $name     = Horde_String::lower($name);
+        $type_var = $this->{'_' . $this->types[$type]};
+
+        if (isset($type_var[$name])) {
+            return $type_var[$name];
         }
+        if (isset($this->_oids[$name]) &&
+            $this->_oids[$name]['type'] == $type) {
+            return $this->_oids[$name];
+        }
+        throw new Horde_Ldap_Exception("Could not find $type $name");
     }
 
 
     /**
-     * Fetches attributes that MAY be present in the given objectclass
+     * Fetches attributes that MAY be present in the given objectclass.
      *
-     * @param string $oc Name or OID of objectclass
+     * @param string $oc Name or OID of objectclass.
      *
-     * @access public
-     * @return array|Horde_Ldap_Error Array with attributes or Horde_Ldap_Error
+     * @return array Array with attributes.
+     * @throws Horde_Ldap_Exception
      */
     public function may($oc)
     {
@@ -225,12 +204,12 @@ class Horde_Ldap_Schema
     }
 
     /**
-     * Fetches attributes that MUST be present in the given objectclass
+     * Fetches attributes that MUST be present in the given objectclass.
      *
-     * @param string $oc Name or OID of objectclass
+     * @param string $oc Name or OID of objectclass.
      *
-     * @access public
-     * @return array|Horde_Ldap_Error Array with attributes or Horde_Ldap_Error
+     * @return array Array with attributes.
+     * @throws Horde_Ldap_Exception
      */
     public function must($oc)
     {
@@ -238,81 +217,76 @@ class Horde_Ldap_Schema
     }
 
     /**
-     * Fetches the given attribute from the given objectclass
+     * Fetches the given attribute from the given objectclass.
      *
-     * @param string $oc   Name or OID of objectclass
-     * @param string $attr Name of attribute to fetch
+     * @param string $oc   Name or OID of objectclass.
+     * @param string $attr Name of attribute to fetch.
      *
-     * @access protected
-     * @return array|Horde_Ldap_Error The attribute or Horde_Ldap_Error
+     * @return array The attribute.
+     * @throws Horde_Ldap_Exception
      */
     protected function _getAttr($oc, $attr)
     {
-        $oc = strtolower($oc);
-        if (key_exists($oc, $this->_objectClasses) && key_exists($attr, $this->_objectClasses[$oc])) {
+        $oc = Horde_String::lower($oc);
+        if (isset($this->_objectClasses[$oc]) &&
+            isset($this->_objectClasses[$oc][$attr])) {
             return $this->_objectClasses[$oc][$attr];
-        } elseif (key_exists($oc, $this->_oids) &&
-                $this->_oids[$oc]['type'] == 'objectclass' &&
-                key_exists($attr, $this->_oids[$oc])) {
+        }
+        if (isset($this->_oids[$oc]) &&
+            $this->_oids[$oc]['type'] == 'objectclass' &&
+            isset($this->_oids[$oc][$attr])) {
             return $this->_oids[$oc][$attr];
-        } else {
-            throw new Horde_Ldap_Exception("Could not find $attr attributes for $oc ");
         }
+        throw new Horde_Ldap_Exception("Could not find $attr attributes for $oc ");
     }
 
     /**
-     * Returns the name(s) of the immediate superclass(es)
+     * Returns the name(s) of the immediate superclass(es).
      *
-     * @param string $oc Name or OID of objectclass
+     * @param string $oc Name or OID of objectclass.
      *
-     * @access public
-     * @return array|Horde_Ldap_Error  Array of names or Horde_Ldap_Error
+     * @return array
+     * @throws Horde_Ldap_Exception
      */
     public function superclass($oc)
     {
         $o = $this->get('objectclass', $oc);
-        return (key_exists('sup', $o) ? $o['sup'] : array());
+        return isset($o['sup']) ? $o['sup'] : array();
     }
 
     /**
-     * Parses the schema of the given Subschema entry
+     * Parses the schema of the given subschema entry.
      *
-     * @param Horde_Ldap_Entry &$entry Subschema entry
-     *
-     * @access public
-     * @return void
+     * @param Horde_Ldap_Entry $entry Subschema entry.
      */
-    public function parse(&$entry)
+    public function parse($entry)
     {
         foreach ($this->types as $type => $attr) {
-            // initialize map type to entry
+            // Initialize map type to entry.
             $type_var          = '_' . $attr;
             $this->{$type_var} = array();
 
-            // get values for this type
-            if ($entry->exists($attr)) {
-                $values = $entry->getValue($attr);
-                if (is_array($values)) {
-                    foreach ($values as $value) {
-
-                        unset($schema_entry); // this was a real mess without it
-
-                        // get the schema entry
-                        $schema_entry = $this->_parse_entry($value);
-
-                        // set the type
-                        $schema_entry['type'] = $type;
-
-                        // save a ref in $_oids
-                        $this->_oids[$schema_entry['oid']] = &$schema_entry;
+            if (!$entry->exists($attr)) {
+                continue;
+            }
 
-                        // save refs for all names in type map
-                        $names = $schema_entry['aliases'];
-                        array_push($names, $schema_entry['name']);
-                        foreach ($names as $name) {
-                            $this->{$type_var}[strtolower($name)] = &$schema_entry;
-                        }
-                    }
+            // Get values for this type.
+            $values = $entry->getValue($attr);
+            if (!is_array($values)) {
+                continue;
+            }
+            foreach ($values as $value) {
+                // Get the schema entry.
+                $schema_entry = $this->_parse_entry($value);
+                // Set the type.
+                $schema_entry['type'] = $type;
+                // Save a ref in $_oids.
+                $this->_oids[$schema_entry['oid']] = $schema_entry;
+                // Save refs for all names in type map.
+                $names = $schema_entry['aliases'];
+                array_push($names, $schema_entry['name']);
+                foreach ($names as $name) {
+                    $this->{$type_var}[Horde_String::lower($name)] = $schema_entry;
                 }
             }
         }
@@ -320,16 +294,15 @@ class Horde_Ldap_Schema
     }
 
     /**
-     * Parses an attribute value into a schema entry
+     * Parses an attribute value into a schema entry.
      *
-     * @param string $value Attribute value
+     * @param string $value Attribute value.
      *
-     * @access protected
-     * @return array|false Schema entry array or false
+     * @return array Schema entry array.
      */
-    protected function &_parse_entry($value)
+    protected function _parse_entry($value)
     {
-        // tokens that have no value associated
+        // Tokens that have no value associated.
         $noValue = array('single-value',
                          'obsolete',
                          'collective',
@@ -338,147 +311,148 @@ class Horde_Ldap_Schema
                          'structural',
                          'auxiliary');
 
-        // tokens that can have multiple values
+        // Tokens that can have multiple values.
         $multiValue = array('must', 'may', 'sup');
 
-        $schema_entry = array('aliases' => array()); // initilization
-
-        $tokens = $this->_tokenize($value); // get an array of tokens
+        // Get an array of tokens.
+        $tokens = $this->_tokenize($value);
 
-        // remove surrounding brackets
-        if ($tokens[0] == '(') array_shift($tokens);
-        if ($tokens[count($tokens) - 1] == ')') array_pop($tokens); // -1 doesnt work on arrays :-(
+        // Remove surrounding brackets.
+        if ($tokens[0] == '(') {
+            array_shift($tokens);
+        }
+        if ($tokens[count($tokens) - 1] == ')') {
+            array_pop($tokens);
+        }
 
-        $schema_entry['oid'] = array_shift($tokens); // first token is the oid
+        // First token is the oid.
+        $schema_entry = array('aliases' => array(),
+                              'oid' => array_shift($tokens));
 
-        // cycle over the tokens until none are left
+        // Cycle over the tokens until none are left.
         while (count($tokens) > 0) {
-            $token = strtolower(array_shift($tokens));
+            $token = Horde_String::lower(array_shift($tokens));
             if (in_array($token, $noValue)) {
-                $schema_entry[$token] = 1; // single value token
+                // Single value token.
+                $schema_entry[$token] = 1;
             } else {
-                // this one follows a string or a list if it is multivalued
+                // Follow a string or a list if it is multivalued.
                 if (($schema_entry[$token] = array_shift($tokens)) == '(') {
-                    // this creates the list of values and cycles through the tokens
-                    // until the end of the list is reached ')'
+                    // Create the list of values and cycles through the tokens
+                    // until the end of the list is reached ')'.
                     $schema_entry[$token] = array();
                     while ($tmp = array_shift($tokens)) {
-                        if ($tmp == ')') break;
-                        if ($tmp != '$') array_push($schema_entry[$token], $tmp);
+                        if ($tmp == ')') {
+                            break;
+                        }
+                        if ($tmp != '$') {
+                            array_push($schema_entry[$token], $tmp);
+                        }
                     }
                 }
-                // create a array if the value should be multivalued but was not
-                if (in_array($token, $multiValue) && !is_array($schema_entry[$token])) {
+                // Create an array if the value should be multivalued but was
+                // not.
+                if (in_array($token, $multiValue) &&
+                    !is_array($schema_entry[$token])) {
                     $schema_entry[$token] = array($schema_entry[$token]);
                 }
             }
         }
-        // get max length from syntax
-        if (key_exists('syntax', $schema_entry)) {
+
+        // Get max length from syntax.
+        if (isset($schema_entry['syntax'])) {
             if (preg_match('/{(\d+)}/', $schema_entry['syntax'], $matches)) {
                 $schema_entry['max_length'] = $matches[1];
             }
         }
-        // force a name
+
+        // Force a name.
         if (empty($schema_entry['name'])) {
             $schema_entry['name'] = $schema_entry['oid'];
         }
-        // make one name the default and put the other ones into aliases
+
+        // Make one name the default and put the other ones into aliases.
         if (is_array($schema_entry['name'])) {
             $aliases                 = $schema_entry['name'];
             $schema_entry['name']    = array_shift($aliases);
             $schema_entry['aliases'] = $aliases;
         }
+
         return $schema_entry;
     }
 
     /**
-     * Tokenizes the given value into an array of tokens
+     * Tokenizes the given value into an array of tokens.
      *
-     * @param string $value String to parse
+     * @param string $value String to parse.
      *
-     * @access protected
-     * @return array Array of tokens
+     * @return array Array of tokens.
      */
     protected function _tokenize($value)
     {
-        $tokens  = array();       // array of tokens
-        $matches = array();       // matches[0] full pattern match, [1,2,3] subpatterns
-
-        // this one is taken from perl-ldap, modified for php
-        $pattern = "/\s* (?:([()]) | ([^'\s()]+) | '((?:[^']+|'[^\s)])*)') \s*/x";
-
-        /**
-          * This one matches one big pattern wherin only one of the three subpatterns matched
-          * We are interested in the subpatterns that matched. If it matched its value will be
-          * non-empty and so it is a token. Tokens may be round brackets, a string, or a string
-          * enclosed by '
-          */
-        preg_match_all($pattern, $value, $matches);
-
-        for ($i = 0; $i < count($matches[0]); $i++) {     // number of tokens (full pattern match)
-            for ($j = 1; $j < 4; $j++) {                  // each subpattern
-                if (null != trim($matches[$j][$i])) {     // pattern match in this subpattern
-                    $tokens[$i] = trim($matches[$j][$i]); // this is the token
+        /* Match one big pattern where only one of the three subpatterns
+         * matches.  We are interested in the subpatterns that matched. If it
+         * matched its value will be non-empty and so it is a token. Tokens may
+         * be round brackets, a string, or a string enclosed by ''. */
+        preg_match_all("/\s* (?:([()]) | ([^'\s()]+) | '((?:[^']+|'[^\s)])*)') \s*/x", $value, $matches);
+
+        $tokens  = array();
+        // Number of tokens (full pattern match).
+        for ($i = 0; $i < count($matches[0]); $i++) {
+            // Each subpattern.
+            for ($j = 1; $j < 4; $j++) {
+                // Pattern match in this subpattern.
+                if (null != trim($matches[$j][$i])) {
+                    // This is the token.
+                    $tokens[$i] = trim($matches[$j][$i]);
                 }
             }
         }
+
         return $tokens;
     }
 
     /**
-     * Returns wether a attribute syntax is binary or not
+     * Returns wether a attribute syntax is binary or not.
      *
-     * This method gets used by Horde_Ldap_Entry to decide which
-     * PHP function needs to be used to fetch the value in the
-     * proper format (e.g. binary or string)
+     * This method is used by Horde_Ldap_Entry to decide which PHP function
+     * needs to be used to fetch the value in the proper format (e.g. binary or
+     * string).
      *
-     * @param string $attribute The name of the attribute (eg.: 'sn')
+     * @param string $attribute The name of the attribute (eg.: 'sn').
      *
-     * @access public
-     * @return boolean
+     * @return boolean  True if the attribute is a binary type.
      */
     public function isBinary($attribute)
     {
-        $return = false; // default to false
-
-        // This list contains all syntax that should be treaten as
-        // containing binary values
-        // The Syntax Definitons go into constants at the top of this page
-        $syntax_binary = array(
-                           HORDE_LDAP_SYNTAX_OCTET_STRING,
-                           HORDE_LDAP_SYNTAX_JPEG
-                         );
-
-        // Check Syntax
-       try {
-         $attr_s = $this->get('attribute', $attribute);
-       } catch (Horde_Ldap_Exception $e) {
-            // Attribute not found in schema
-            $return = false; // consider attr not binary
-       }
-        if (isset($attr_s['syntax']) && in_array($attr_s['syntax'], $syntax_binary)) {
+        // All syntax that should be treaten as containing binary values.
+        $syntax_binary = array(self::SYNTAX_OCTET_STRING, self::SYNTAX_JPEG);
+
+        // Check Syntax.
+        try {
+            $attr_s = $this->get('attribute', $attribute);
+        } catch (Horde_Ldap_Exception $e) {
+            // Attribute not found in schema, consider attr not binary.
+            return false;
+        }
+
+        if (isset($attr_s['syntax']) &&
+            in_array($attr_s['syntax'], $syntax_binary)) {
             // Syntax is defined as binary in schema
-            $return = true;
-        } else {
-            // Syntax not defined as binary, or not found
-            // if attribute is a subtype, check superior attribute syntaxes
-            if (isset($attr_s['sup'])) {
-                foreach ($attr_s['sup'] as $superattr) {
-                    $return = $this->isBinary($superattr);
-                    if ($return) {
-                        break; // stop checking parents since we are binary
-                    }
+            return true;
+        }
+
+        // Syntax not defined as binary, or not found if attribute is a
+        // subtype, check superior attribute syntaxes.
+        if (isset($attr_s['sup'])) {
+            foreach ($attr_s['sup'] as $superattr) {
+                if ($this->isBinary($superattr)) {
+                    // Stop checking parents since we are binary.
+                    return true;
                 }
             }
         }
 
-        return $return;
+        return false;
     }
-
-    // [TODO] add method that allows us to see to which objectclasses a certain attribute belongs to
-    // it should return the result structured, e.g. sorted in "may" and "must". Optionally it should
-    // be able to return it just "flat", e.g. array_merge()d.
-    // We could use get_all() to achieve this easily, i think
 }
-?>
index 1d49a33..035452d 100644 (file)
 <?php
 /**
- * File containing the Horde_Ldap_Search interface class.
- *
- * PHP version 5
+ * Result set of an LDAP search
  *
- * @category  Net
- * @package   Horde_Ldap
+ * @category  Horde
+ * @package   Ldap
  * @author    Tarjej Huse <tarjei@bergfald.no>
  * @author    Benedikt Hallinger <beni@php.net>
- * @copyright 2009 Tarjej Huse, Benedikt Hallinger
- * @license   http://www.gnu.org/licenses/lgpl-3.0.txt LGPLv3
- * @version   SVN: $Id: Search.php 286718 2009-08-03 07:30:49Z beni $
- * @link      http://pear.php.net/package/Horde_Ldap/
- */
-
-/**
- * Includes
- */
-#require_once 'PEAR.php';
-
-/**
- * Result set of an LDAP search
- *
- * @category Net
- * @package  Horde_Ldap
- * @author   Tarjej Huse <tarjei@bergfald.no>
- * @author   Benedikt Hallinger <beni@php.net>
- * @license  http://www.gnu.org/copyleft/lesser.html LGPL
- * @link     http://pear.php.net/package/Horde_Ldap2/
+ * @author    Jan Schneider <jan@horde.org>
+ * @copyright 2009 Jan Wagner, Benedikt Hallinger
+ * @copyright 2010 The Horde Project
+ * @license   http://www.gnu.org/copyleft/lesser.html LGPL
  */
 class Horde_Ldap_Search implements Iterator
 {
     /**
-     * Search result identifier
+     * Search result identifier.
      *
-     * @access protected
      * @var resource
      */
     protected $_search;
 
     /**
-     * LDAP resource link
+     * LDAP resource link.
      *
-     * @access protected
      * @var resource
      */
     protected $_link;
 
     /**
-     * Horde_Ldap object
+     * Horde_Ldap object.
      *
-     * A reference of the Horde_Ldap object for passing to Horde_Ldap_Entry
+     * A reference of the Horde_Ldap object for passing to Horde_Ldap_Entry.
      *
-     * @access protected
-     * @var object Horde_Ldap
+     * @var Horde_Ldap
      */
     protected $_ldap;
 
     /**
-     * Result entry identifier
+     * Result entry identifier.
      *
-     * @access protected
      * @var resource
      */
-    protected $_entry = null;
+    protected $_entry;
 
     /**
-     * The errorcode the search got
+     * The errorcode from the search.
      *
-     * Some errorcodes might be of interest, but might not be best handled as errors.
-     * examples: 4 - LDAP_SIZELIMIT_EXCEEDED - indicates a huge search.
-     *               Incomplete results are returned. If you just want to check if there's anything in the search.
-     *               than this is a point to handle.
-     *           32 - no such object - search here returns a count of 0.
+     * Some errorcodes might be of interest that should not be considered
+     * errors, for example:
+     * - 4: LDAP_SIZELIMIT_EXCEEDED - indicates a huge search. Incomplete
+     *      results are returned. If you just want to check if there is
+     *      anything returned by the search at all, this could be catched.
+     * - 32: no such object - search here returns a count of 0.
      *
-     * @access protected
-     * @var int
+     * @var integer
      */
-    protected $_errorCode = 0; // if not set - sucess!
+    protected $_errorCode = 0;
 
     /**
-     * Cache for all entries already fetched from iterator interface
+     * Cache for all entries already fetched from iterator interface.
      *
-     * @access protected
      * @var array
      */
     protected $_iteratorCache = array();
 
     /**
-     * What attributes we searched for
+     * Attributes we searched for.
      *
-     * The $attributes array contains the names of the searched attributes and gets
-     * passed from $Horde_Ldap->search() so the Horde_Ldap_Search object can tell
-     * what attributes was searched for ({@link searchedAttrs())
+     * This variable gets set from the constructor and can be retrieved through
+     * {@link searchedAttributes()}.
      *
-     * This variable gets set from the constructor and returned
-     * from {@link searchedAttrs()}
-     *
-     * @access protected
      * @var array
      */
     protected $_searchedAttrs = array();
 
     /**
-     * Cache variable for storing entries fetched internally
+     * Cache variable for storing entries fetched internally.
      *
-     * This currently is only used by {@link pop_entry()}
+     * This currently is only used by {@link pop_entry()}.
      *
-     * @access protected
      * @var array
      */
     protected $_entry_cache = false;
 
     /**
-     * Constructor
-     *
-     * @param resource           &$search    Search result identifier
-     * @param Horde_Ldap|resource &$ldap      Horde_Ldap object or just a LDAP-Link resource
-     * @param array              $attributes (optional) Array with searched attribute names. (see {@link $_searchedAttrs})
+     * Constructor.
      *
-     * @access public
+     * @param resource            $search     Search result identifier.
+     * @param Horde_Ldap|resource $ldap       Horde_Ldap object or a LDAP link
+     *                                        resource
+     * @param array               $attributes The searched attribute names,
+     *                                        see {@link $_searchedAttrs}.
      */
-    public function __construct(&$search, &$ldap, $attributes = array())
+    public function __construct($search, $ldap, $attributes = array())
     {
         $this->setSearch($search);
 
         if ($ldap instanceof Horde_Ldap) {
-            $this->_ldap =& $ldap;
+            $this->_ldap = $ldap;
             $this->setLink($this->_ldap->getLink());
         } else {
             $this->setLink($ldap);
@@ -140,158 +111,141 @@ class Horde_Ldap_Search implements Iterator
     }
 
     /**
-     * Returns an array of entry objects
+     * Destructor.
+     */
+    public function __destruct()
+    {
+        @ldap_free_result($this->_search);
+    }
+
+    /**
+     * Returns all entries from the search result.
      *
-     * @return array Array of entry objects.
+     * @return array  All entries.
+     * @throws Horde_Ldap_Exception
      */
     public function entries()
     {
         $entries = array();
-
         while ($entry = $this->shiftEntry()) {
             $entries[] = $entry;
         }
-
         return $entries;
     }
 
     /**
-     * Get the next entry in the searchresult.
+     * Get the next entry from the search result.
      *
-     * This will return a valid Horde_Ldap_Entry object or false, so
-     * you can use this method to easily iterate over the entries inside
-     * a while loop.
+     * This will return a valid Horde_Ldap_Entry object or false, so you can
+     * use this method to easily iterate over the entries inside a while loop.
      *
-     * @return Horde_Ldap_Entry|false  Reference to Horde_Ldap_Entry object or false
+     * @return Horde_Ldap_Entry|false  Reference to Horde_Ldap_Entry object or
+     *                                 false if no more entries exist.
+     * @throws Horde_Ldap_Exception
      */
-    public function &shiftEntry()
+    public function shiftEntry()
     {
-        if ($this->count() == 0 ) {
-            $false = false;
-            return $false;
+        if (!$this->count()) {
+            return false;
         }
 
         if (is_null($this->_entry)) {
             $this->_entry = @ldap_first_entry($this->_link, $this->_search);
             $entry = Horde_Ldap_Entry::createConnected($this->_ldap, $this->_entry);
-            if ($entry instanceof Horde_Ldap_Error) $entry = false;
         } else {
             if (!$this->_entry = @ldap_next_entry($this->_link, $this->_entry)) {
-                $false = false;
-                return $false;
+                return false;
             }
             $entry = Horde_Ldap_Entry::createConnected($this->_ldap, $this->_entry);
-            if ($entry instanceof Horde_Ldap_Error) $entry = false;
         }
-        return $entry;
-    }
 
-    /**
-     * Alias function of shiftEntry() for perl-ldap interface
-     *
-     * @see shiftEntry()
-     * @return Horde_Ldap_Entry|false
-     */
-    public function shift_entry()
-    {
-        $args = func_get_args();
-        return call_user_func_array(array( &$this, 'shiftEntry' ), $args);
+        return $entry;
     }
 
     /**
-     * Retrieve the next entry in the searchresult, but starting from last entry
+     * Retrieve the next entry in the search result, but starting from last
+     * entry.
      *
-     * This is the opposite to {@link shiftEntry()} and is also very useful
-     * to be used inside a while loop.
+     * This is the opposite to {@link shiftEntry()} and is also very useful to
+     * be used inside a while loop.
      *
      * @return Horde_Ldap_Entry|false
+     * @throws Horde_Ldap_Exception
      */
     public function popEntry()
     {
         if (false === $this->_entry_cache) {
-            // fetch entries into cache if not done so far
+            // Fetch entries into cache if not done so far.
             $this->_entry_cache = $this->entries();
         }
 
-        $return = array_pop($this->_entry_cache);
-        return (null === $return)? false : $return;
+        return count($this->_entry_cache) ? array_pop($this->_entry_cache) : false;
     }
 
     /**
-     * Alias function of popEntry() for perl-ldap interface
+     * Return entries sorted as array.
      *
-     * @see popEntry()
-     * @return Horde_Ldap_Entry|false
-     */
-    public function pop_entry()
-    {
-        $args = func_get_args();
-        return call_user_func_array(array( &$this, 'popEntry' ), $args);
-    }
-
-    /**
-     * Return entries sorted as array
+     * This returns a array with sorted entries and the values. Sorting is done
+     * with PHPs {@link array_multisort()}.
      *
-     * This returns a array with sorted entries and the values.
-     * Sorting is done with PHPs {@link array_multisort()}.
-     * This method relies on {@link as_struct()} to fetch the raw data of the entries.
+     * This method relies on {@link as_struct()} to fetch the raw data of the
+     * entries.
      *
      * Please note that attribute names are case sensitive!
      *
      * Usage example:
      * <code>
-     *   // to sort entries first by location, then by surename, but descending:
-     *   $entries = $search->sorted_as_struct(array('locality','sn'), SORT_DESC);
+     *   // To sort entries first by location, then by surname, but descending:
+     *   $entries = $search->sorted_as_struct(array('locality', 'sn'), SORT_DESC);
      * </code>
      *
-     * @param array $attrs Array of attribute names to sort; order from left to right.
-     * @param int   $order Ordering direction, either constant SORT_ASC or SORT_DESC
+     * @todo what about server side sorting as specified in
+     *       http://www.ietf.org/rfc/rfc2891.txt?
+     * @todo Nuke evil eval().
      *
-     * @return array|Horde_Ldap_Error   Array with sorted entries or error
-     * @todo what about server side sorting as specified in http://www.ietf.org/rfc/rfc2891.txt?
+     * @param array   $attrs Attribute names as sort criteria.
+     * @param integer $order Ordering direction, either constant SORT_ASC or
+     *                       SORT_DESC
+     *
+     * @return array Sorted entries.
+     * @throws Horde_Ldap_Exception
      */
-    public function sorted_as_struct($attrs = array('cn'), $order = SORT_ASC)
+    public function sorted_as_struct(array $attrs = array('cn'),
+                                     $order = SORT_ASC)
     {
-        /*
-         * Old Code, suitable and fast for single valued sorting
-         * This code should be used if we know that single valued sorting is desired,
-         * but we need some method to get that knowledge...
-         */
+        /* Old Code, suitable and fast for single valued sorting. This code
+         * should be used if we know that single valued sorting is desired, but
+         * we need some method to get that knowledge... */
         /*
         $attrs = array_reverse($attrs);
         foreach ($attrs as $attribute) {
-            if (!ldap_sort($this->_link, $this->_search, $attribute)){
-                $this->raiseError("Sorting failed for Attribute " . $attribute);
+            if (!ldap_sort($this->_link, $this->_search, $attribute)) {
+                throw new Horde_Ldap_Exception('Sorting failed for attribute ' . $attribute);
             }
         }
 
         $results = ldap_get_entries($this->_link, $this->_search);
 
-        unset($results['count']); //for tidier output
+        unset($results['count']);
         if ($order) {
             return array_reverse($results);
-        } else {
-            return $results;
-        }*/
-
-        /*
-         * New code: complete "client side" sorting
-         */
-        // first some parameterchecks
-        if (!is_array($attrs)) {
-            return PEAR::raiseError("Sorting failed: Parameterlist must be an array!");
         }
+        return $results;
+        */
+
+        /* New code: complete "client side" sorting */
+        // First some parameterchecks.
         if ($order != SORT_ASC && $order != SORT_DESC) {
-            return PEAR::raiseError("Sorting failed: sorting direction not understood! (neither constant SORT_ASC nor SORT_DESC)");
+            throw new Horde_Ldap_Exception('Sorting failed: sorting direction not understood! (neither constant SORT_ASC nor SORT_DESC)');
         }
 
-        // fetch the entries data
+        // Fetch the entries data.
         $entries = $this->as_struct();
 
-        // now sort each entries attribute values
-        // this is neccessary because later we can only sort by one value,
-        // so we need the highest or lowest attribute now, depending on the
-        // selected ordering for that specific attribute
+        // Now sort each entries attribute values.
+        // This is neccessary because later we can only sort by one value, so
+        // we need the highest or lowest attribute now, depending on the
+        // selected ordering for that specific attribute.
         foreach ($entries as $dn => $entry) {
             foreach ($entry as $attr_name => $attr_values) {
                 sort($entries[$dn][$attr_name]);
@@ -301,19 +255,20 @@ class Horde_Ldap_Search implements Iterator
             }
         }
 
-        // reformat entrys array for later use with array_multisort()
-        $to_sort = array(); // <- will be a numeric array similar to ldap_get_entries
+        // Reformat entries array for later use with
+        // array_multisort(). $to_sort will be a numeric array similar to
+        // ldap_get_entries().
+        $to_sort = array();
         foreach ($entries as $dn => $entry_attr) {
-            $row       = array();
-            $row['dn'] = $dn;
+            $row = array('dn' => $dn);
             foreach ($entry_attr as $attr_name => $attr_values) {
                 $row[$attr_name] = $attr_values;
             }
             $to_sort[] = $row;
         }
 
-        // Build columns for array_multisort()
-        // each requested attribute is one row
+        // Build columns for array_multisort(). Each requested attribute is one
+        // row.
         $columns = array();
         foreach ($attrs as $attr_name) {
             foreach ($to_sort as $key => $row) {
@@ -321,86 +276,81 @@ class Horde_Ldap_Search implements Iterator
             }
         }
 
-        // sort the colums with array_multisort, if there is something
-        // to sort and if we have requested sort columns
+        // Sort the colums with array_multisort() if there is something to sort
+        // and if we have requested sort columns.
         if (!empty($to_sort) && !empty($columns)) {
             $sort_params = '';
             foreach ($attrs as $attr_name) {
-                $sort_params .= '$columns[\''.$attr_name.'\'], '.$order.', ';
+                $sort_params .= '$columns[\'' . $attr_name . '\'], ' . $order . ', ';
             }
-            eval("array_multisort($sort_params \$to_sort);"); // perform sorting
+            eval("array_multisort($sort_params \$to_sort);");
         }
 
         return $to_sort;
     }
 
     /**
-     * Return entries sorted as objects
+     * Returns entries sorted as objects.
      *
-     * This returns a array with sorted Horde_Ldap_Entry objects.
-     * The sorting is actually done with {@link sorted_as_struct()}.
+     * This returns a array with sorted Horde_Ldap_Entry objects. The sorting
+     * is actually done with {@link sorted_as_struct()}.
      *
      * Please note that attribute names are case sensitive!
-     * Also note, that it is (depending on server capabilitys) possible to let
-     * the server sort your results. This happens through search controls
-     * and is described in detail at {@link http://www.ietf.org/rfc/rfc2891.txt}
+     *
+     * Also note that it is (depending on server capabilities) possible to let
+     * the server sort your results. This happens through search controls and
+     * is described in detail at {@link http://www.ietf.org/rfc/rfc2891.txt}
      *
      * Usage example:
      * <code>
-     *   // to sort entries first by location, then by surename, but descending:
-     *   $entries = $search->sorted(array('locality','sn'), SORT_DESC);
+     *   // To sort entries first by location, then by surname, but descending:
+     *   $entries = $search->sorted(array('locality', 'sn'), SORT_DESC);
      * </code>
      *
-     * @param array $attrs Array of sort attributes to sort; order from left to right.
-     * @param int   $order Ordering direction, either constant SORT_ASC or SORT_DESC
+     * @todo Entry object construction could be faster. Maybe we could use one
+     *       of the factories instead of fetching the entry again.
+     *
+     * @param array   $attrs Attribute names as sort criteria.
+     * @param integer $order Ordering direction, either constant SORT_ASC or
+     *                       SORT_DESC
      *
-     * @return array|Horde_Ldap_Error   Array with sorted Horde_Ldap_Entries or error
-     * @todo Entry object construction could be faster. Maybe we could use one of the factorys instead of fetching the entry again
+     * @return array Sorted entries.
+     * @throws Horde_Ldap_Exception
      */
     public function sorted($attrs = array('cn'), $order = SORT_ASC)
     {
         $return = array();
         $sorted = $this->sorted_as_struct($attrs, $order);
-        if (PEAR::isError($sorted)) {
-            return $sorted;
-        }
         foreach ($sorted as $key => $row) {
-            $entry = $this->_ldap->getEntry($row['dn'], $this->searchedAttrs());
-            if (!PEAR::isError($entry)) {
-                array_push($return, $entry);
-            } else {
-                return $entry;
-            }
+            $entry = $this->_ldap->getEntry($row['dn'], $this->searchedAttributes());
+            array_push($return, $entry);
         }
         return $return;
     }
 
     /**
-     * Return entries as array
+     * Returns entries as array.
      *
-     * This method returns the entries and the selected attributes values as
-     * array.
      * The first array level contains all found entries where the keys are the
-     * DNs of the entries. The second level arrays contian the entries attributes
-     * such that the keys is the lowercased name of the attribute and the values
-     * are stored in another indexed array. Note that the attribute values are stored
-     * in an array even if there is no or just one value.
+     * DNs of the entries. The second level arrays contian the entries
+     * attributes such that the keys is the lowercased name of the attribute
+     * and the values are stored in another indexed array. Note that the
+     * attribute values are stored in an array even if there is no or just one
+     * value.
      *
      * The array has the following structure:
      * <code>
-     * $return = array(
-     *           'cn=foo,dc=example,dc=com' => array(
-     *                                                'sn'       => array('foo'),
-     *                                                'multival' => array('val1', 'val2', 'valN')
-     *                                             )
-     *           'cn=bar,dc=example,dc=com' => array(
-     *                                                'sn'       => array('bar'),
-     *                                                'multival' => array('val1', 'valN')
-     *                                             )
-     *           )
+     * array(
+     *     'cn=foo,dc=example,dc=com' => array(
+     *         'sn'       => array('foo'),
+     *         'multival' => array('val1', 'val2', 'valN')),
+     *     'cn=bar,dc=example,dc=com' => array(
+     *         'sn'       => array('bar'),
+     *         'multival' => array('val1', 'valN')))
      * </code>
      *
-     * @return array      associative result array as described above
+     * @return array Associative result array as described above.
+     * @throws Horde_Ldap_Exception
      */
     public function as_struct()
     {
@@ -422,39 +372,34 @@ class Horde_Ldap_Search implements Iterator
     }
 
     /**
-     * Set the search objects resource link
+     * Sets the search objects resource link
      *
-     * @param resource &$search Search result identifier
-     *
-     * @access public
-     * @return void
+     * @param resource $search Search result identifier.
      */
-    public function setSearch(&$search)
+    public function setSearch($search)
     {
         $this->_search = $search;
     }
 
     /**
-     * Set the ldap ressource link
-     *
-     * @param resource &$link Link identifier
+     * Sets the LDAP resource link.
      *
-     * @access public
-     * @return void
+     * @param resource $link LDAP link identifier.
      */
-    public function setLink(&$link)
+    public function setLink($link)
     {
         $this->_link = $link;
     }
 
     /**
-     * Returns the number of entries in the searchresult
+     * Returns the number of entries in the search result.
      *
-     * @return int Number of entries in search.
+     * @return integer Number of found entries.
      */
     public function count()
     {
-        // this catches the situation where OL returned errno 32 = no such object!
+        // This catches the situation where OL returned errno 32 = no such
+        // object!
         if (!$this->_search) {
             return 0;
         }
@@ -462,9 +407,9 @@ class Horde_Ldap_Search implements Iterator
     }
 
     /**
-     * Get the errorcode the object got in its search.
+     * Returns the errorcode from the search.
      *
-     * @return int The ldap error number.
+     * @return integer The LDAP error number.
      */
     public function getErrorCode()
     {
@@ -472,55 +417,32 @@ class Horde_Ldap_Search implements Iterator
     }
 
     /**
-     * Destructor
+     * Returns the attribute names this search selected.
      *
-     * @access protected
-     */
-    public function _Horde_Ldap_Search()
-    {
-        @ldap_free_result($this->_search);
-    }
-
-    /**
-     * Closes search result
-     *
-     * @return void
-     */
-    public function done()
-    {
-        $this->_Horde_Ldap_Search();
-    }
-
-    /**
-     * Return the attribute names this search selected
+     * @see $_searchedAttrs
      *
      * @return array
-     * @see $_searchedAttrs
-     * @access protected
      */
-    protected function searchedAttrs()
+    protected function searchedAttributes()
     {
         return $this->_searchedAttrs;
     }
 
     /**
-     * Tells if this search exceeds a sizelimit
+     * Returns wheter this search exceeded a sizelimit.
      *
-     * @return boolean
+     * @return boolean  True if the size limit was exceeded.
      */
     public function sizeLimitExceeded()
     {
-        return ($this->getErrorCode() == 4);
+        return $this->getErrorCode() == 4;
     }
 
+    /* SPL Iterator interface methods. This interface allows to use
+     * Horde_Ldap_Search objects directly inside a foreach loop. */
 
-    /*
-     * SPL Iterator interface methods.
-     * This interface allows to use Horde_Ldap_Search
-     * objects directly inside a foreach loop!
-     */
     /**
-     * SPL Iterator interface: Return the current element.
+     * SPL Iterator interface: Returns the current element.
      *
      * The SPL Iterator interface allows you to fetch entries inside
      * a foreach() loop: <code>foreach ($search as $dn => $entry) { ...</code>
@@ -528,12 +450,14 @@ class Horde_Ldap_Search implements Iterator
      * Of course, you may call {@link current()}, {@link key()}, {@link next()},
      * {@link rewind()} and {@link valid()} yourself.
      *
-     * If the search throwed an error, it returns false.
-     * False is also returned, if the end is reached
-     * In case no call to next() was made, we will issue one,
-     * thus returning the first entry.
+     * If the search throwed an error, it returns false. False is also
+     * returned, if the end is reached.
+     *
+     * In case no call to next() was made, we will issue one, thus returning
+     * the first entry.
      *
      * @return Horde_Ldap_Entry|false
+     * @throws Horde_Ldap_Exception
      */
     public function current()
     {
@@ -542,70 +466,69 @@ class Horde_Ldap_Search implements Iterator
             reset($this->_iteratorCache);
         }
         $entry = current($this->_iteratorCache);
-        return ($entry instanceof Horde_Ldap_Entry)? $entry : false;
+        return $entry instanceof Horde_Ldap_Entry ? $entry : false;
     }
 
     /**
-     * SPL Iterator interface: Return the identifying key (DN) of the current entry.
+     * SPL Iterator interface: Returns the identifying key (DN) of the current
+     * entry.
      *
      * @see current()
-     * @return string|false DN of the current entry; false in case no entry is returned by current()
+     * @return string|false DN of the current entry; false in case no entry is
+     *                      returned by current().
      */
     public function key()
     {
         $entry = $this->current();
-        return ($entry instanceof Horde_Ldap_Entry)? $entry->dn() :false;
+        return $entry instanceof Horde_Ldap_Entry ? $entry->dn() :false;
     }
 
     /**
-     * SPL Iterator interface: Move forward to next entry.
+     * SPL Iterator interface: Moves forward to next entry.
      *
-     * After a call to {@link next()}, {@link current()} will return
-     * the next entry in the result set.
+     * After a call to {@link next()}, {@link current()} will return the next
+     * entry in the result set.
      *
      * @see current()
-     * @return void
+     * @throws Horde_Ldap_Exception
      */
     public function next()
     {
-        // fetch next entry.
-        // if we have no entrys anymore, we add false (which is
-        // returned by shiftEntry()) so current() will complain.
+        // Fetch next entry. If we have no entries anymore, we add false (which
+        // is returned by shiftEntry()) so current() will complain.
         if (count($this->_iteratorCache) - 1 <= $this->count()) {
             $this->_iteratorCache[] = $this->shiftEntry();
         }
 
-        // move on array pointer to current element.
-        // even if we have added all entries, this will
-        // ensure proper operation in case we rewind()
+        // Move array pointer to current element.  Even if we have added all
+        // entries, this will ensure proper operation in case we rewind().
         next($this->_iteratorCache);
     }
 
     /**
-     * SPL Iterator interface:  Check if there is a current element after calls to {@link rewind()} or {@link next()}.
+     * SPL Iterator interface: Checks if there is a current element after calls
+     * to {@link rewind()} or {@link next()}.
      *
      * Used to check if we've iterated to the end of the collection.
      *
      * @see current()
-     * @return boolean FALSE if there's nothing more to iterate over
+     * @return boolean False if there's nothing more to iterate over.
      */
     public function valid()
     {
-        return ($this->current() instanceof Horde_Ldap_Entry);
+        return $this->current() instanceof Horde_Ldap_Entry;
     }
 
     /**
-     * SPL Iterator interface: Rewind the Iterator to the first element.
+     * SPL Iterator interface: Rewinds the Iterator to the first element.
      *
-     * After rewinding, {@link current()} will return the first entry in the result set.
+     * After rewinding, {@link current()} will return the first entry in the
+     * result set.
      *
      * @see current()
-     * @return void
      */
     public function rewind()
     {
         reset($this->_iteratorCache);
     }
 }
-
-?>
index 5639ca3..716a688 100644 (file)
    <pearinstaller>
     <min>1.5.0</min>
    </pearinstaller>
+   <package>
+    <name>Exception</name>
+    <channel>pear.horde.org</channel>
+   </package>
+   <package>
+    <name>Util</name>
+    <channel>pear.horde.org</channel>
+   </package>
   </required>
  </dependencies>
  <phprelease>