Cleanup
authorJan Schneider <jan@horde.org>
Wed, 15 Sep 2010 12:29:26 +0000 (14:29 +0200)
committerJan Schneider <jan@horde.org>
Fri, 17 Sep 2010 12:29:17 +0000 (14:29 +0200)
framework/Ldap/lib/Horde/Ldap/Util.php

index bd7a9c5..a222ef5 100644 (file)
 <?php
 /**
- * File containing the Horde_Ldap_Util interface class.
+ * Utility Class for Horde_Ldap
  *
- * PHP version 5
+ * This class servers some functionality to the other classes of Horde_Ldap but
+ * most of the methods can be used separately as well.
  *
- * @category  Net
- * @package   Horde_Ldap
+ * @category  Horde
+ * @package   Ldap
  * @author    Benedikt Hallinger <beni@php.net>
+ * @author    Jan Schneider <jan@horde.org>
+ * @copyright 2010 The Horde Project
  * @copyright 2009 Benedikt Hallinger
- * @license   http://www.gnu.org/licenses/lgpl-3.0.txt LGPLv3
- * @version   SVN: $Id: Util.php 286718 2009-08-03 07:30:49Z beni $
- * @link      http://pear.php.net/package/Horde_Ldap/
- */
-
-/**
- * Utility Class for Horde_Ldap
- *
- * This class servers some functionality to the other classes of Horde_Ldap but most of
- * the methods can be used separately as well.
- *
- * @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_Ldap2/
+ * @license   http://www.gnu.org/copyleft/lesser.html LGPL
  */
 class Horde_Ldap_Util
 {
     /**
      * Explodes the given DN into its elements
      *
-     * {@link http://www.ietf.org/rfc/rfc2253.txt RFC 2253} says, a Distinguished Name is a sequence
-     * of Relative Distinguished Names (RDNs), which themselves
-     * are sets of Attributes. For each RDN a array is constructed where the RDN part is stored.
-     *
-     * For example, the DN 'OU=Sales+CN=J. Smith,DC=example,DC=net' is exploded to:
-     * <kbd>array( [0] => array([0] => 'OU=Sales', [1] => 'CN=J. Smith'), [2] => 'DC=example', [3] => 'DC=net' )</kbd>
-     *
-     * [NOT IMPLEMENTED] DNs might also contain values, which are the bytes of the BER encoding of
-     * the X.500 AttributeValue rather than some LDAP string syntax. These values are hex-encoded
-     * and prefixed with a #. To distinguish such BER values, ldap_explode_dn uses references to
-     * the actual values, e.g. '1.3.6.1.4.1.1466.0=#04024869,DC=example,DC=com' is exploded to:
-     * [ { '1.3.6.1.4.1.1466.0' => "\004\002Hi" }, { 'DC' => 'example' }, { 'DC' => 'com' } ];
-     * See {@link http://www.vijaymukhi.com/vmis/berldap.htm} for more information on BER.
-     *
-     *  It also performs the following operations on the given DN:
-     *   - Unescape "\" followed by ",", "+", """, "\", "<", ">", ";", "#", "=", " ", or a hexpair
-     *     and strings beginning with "#".
-     *   - Removes the leading 'OID.' characters if the type is an OID instead of a name.
-     *   - If an RDN contains multiple parts, the parts are re-ordered so that the attribute type names are in alphabetical order.
-     *
-     * OPTIONS is a list of name/value pairs, valid options are:
-     *   casefold    Controls case folding of attribute types names.
+     * {@link http://www.ietf.org/rfc/rfc2253.txt RFC 2253} says, a
+     * Distinguished Name is a sequence of Relative Distinguished Names (RDNs),
+     * which themselves are sets of Attributes. For each RDN a array is
+     * constructed where the RDN part is stored.
+     *
+     * For example, the DN 'OU=Sales+CN=J. Smith,DC=example,DC=net' is exploded
+     * to:
+     * <code>
+     * array(array('OU=Sales', 'CN=J. Smith'),
+     *       'DC=example',
+     *       'DC=net')
+     * </code>
+     *
+     * [NOT IMPLEMENTED] DNs might also contain values, which are the bytes of
+     * the BER encoding of the X.500 AttributeValue rather than some LDAP
+     * string syntax. These values are hex-encoded and prefixed with a #. To
+     * distinguish such BER values, ldap_explode_dn uses references to the
+     * actual values, e.g. '1.3.6.1.4.1.1466.0=#04024869,DC=example,DC=com' is
+     * exploded to:
+     * <code>
+     * array(array('1.3.6.1.4.1.1466.0' => "\004\002Hi"),
+     *       array('DC' => 'example',
+     *       array('DC' => 'com'))
+     * <code>
+     * See {@link http://www.vijaymukhi.com/vmis/berldap.htm} for more
+     * information on BER.
+     *
+     * It also performs the following operations on the given DN:
+     * - Unescape "\" followed by ",", "+", """, "\", "<", ">", ";", "#", "=",
+     *   " ", or a hexpair and strings beginning with "#".
+     * - Removes the leading 'OID.' characters if the type is an OID instead of
+     *   a name.
+     * - If an RDN contains multiple parts, the parts are re-ordered so that
+     *   the attribute type names are in alphabetical order.
+     *
+     * $options is a list of name/value pairs, valid options are:
+     * - casefold:   Controls case folding of attribute types names.
      *               Attribute values are not affected by this option.
      *               The default is to uppercase. Valid values are:
-     *               lower        Lowercase attribute types names.
-     *               upper        Uppercase attribute type names. This is the default.
-     *               none         Do not change attribute type names.
-     *   reverse     If TRUE, the RDN sequence is reversed.
-     *   onlyvalues  If TRUE, then only attributes values are returned ('foo' instead of 'cn=foo')
-     *
-
-     * @param string $dn      The DN that should be exploded
-     * @param array  $options Options to use
+     *               - lower: Lowercase attribute types names.
+     *               - upper: Uppercase attribute type names. This is the
+     *                        default.
+     *               - none:  Do not change attribute type names.
+     * - reverse:    If true, the RDN sequence is reversed.
+     * - onlyvalues: If true, then only attributes values are returned ('foo'
+     *               instead of 'cn=foo')
      *
-     * @static
-     * @return array   Parts of the exploded DN
      * @todo implement BER
+     * @todo replace preg_replace() callbacks.
+     *
+     * @param string $dn      The DN that should be exploded.
+     * @param array  $options Options to use.
+     *
+     * @return array   Parts of the exploded DN.
      */
-    public static function ldap_explode_dn($dn, $options = array('casefold' => 'upper'))
+    public static function ldap_explode_dn($dn, array $options = array())
     {
-        if (!isset($options['onlyvalues'])) $options['onlyvalues']  = false;
-        if (!isset($options['reverse']))    $options['reverse']     = false;
-        if (!isset($options['casefold']))   $options['casefold']    = 'upper';
+        if (!isset($options['onlyvalues'])) {
+            $options['onlyvalues'] = false;
+        }
+        if (!isset($options['reverse'])) {
+            $options['reverse'] = false;
+        }
+        if (!isset($options['casefold'])) {
+            $options['casefold'] = 'upper';
+        }
 
-        // Escaping of DN and stripping of "OID."
+        // Escaping of DN and stripping of "OID.".
         $dn = self::canonical_dn($dn, array('casefold' => $options['casefold']));
 
-        // splitting the DN
+        // Splitting the DN.
         $dn_array = preg_split('/(?<=[^\\\\]),/', $dn);
 
-        // clear wrong splitting (possibly we have split too much)
-        // /!\ Not clear, if this is neccessary here
-        //$dn_array = self::correct_dn_splitting($dn_array, ',');
+        // Clear wrong splitting (possibly we have split too much).
+        // Not clear, if this is neccessary here:
+        //$dn_array = self::_correct_dn_splitting($dn_array, ',');
 
-        // construct subarrays for multivalued RDNs and unescape DN value
-        // also convert to output format and apply casefolding
+        // Construct subarrays for multivalued RDNs and unescape DN value, also
+        // convert to output format and apply casefolding.
         foreach ($dn_array as $key => $value) {
             $value_u = self::unescape_dn_value($value);
             $rdns    = self::split_rdn_multival($value_u[0]);
+            // TODO: nuke code duplication
             if (count($rdns) > 1) {
-                // MV RDN!
+                // Multivalued RDN!
                 foreach ($rdns as $subrdn_k => $subrdn_v) {
-                    // Casefolding
-                    if ($options['casefold'] == 'upper') $subrdn_v = preg_replace("/^(\w+=)/e", "''.strtoupper('\\1').''", $subrdn_v);
-                    if ($options['casefold'] == 'lower') $subrdn_v = preg_replace("/^(\w+=)/e", "''.strtolower('\\1').''", $subrdn_v);
+                    // Casefolding.
+                    if ($options['casefold'] == 'upper') {
+                        $subrdn_v = preg_replace('/^(\w+=)/e', "Horde_String::upper('\\1')", $subrdn_v);
+                    }
+                    if ($options['casefold'] == 'lower') {
+                        $subrdn_v = preg_replace('/^(\w+=)/e', "Horde_String::upper('\\1')", $subrdn_v);
+                    }
 
                     if ($options['onlyvalues']) {
                         preg_match('/(.+?)(?<!\\\\)=(.+)/', $subrdn_v, $matches);
@@ -110,11 +126,14 @@ class Horde_Ldap_Util
 
                 $dn_array[$key] = $rdns;
             } else {
-                // normal RDN
-
-                // Casefolding
-                if ($options['casefold'] == 'upper') $value = preg_replace("/^(\w+=)/e", "''.strtoupper('\\1').''", $value);
-                if ($options['casefold'] == 'lower') $value = preg_replace("/^(\w+=)/e", "''.strtolower('\\1').''", $value);
+                // Singlevalued RDN.
+                // Casefolding.
+                if ($options['casefold'] == 'upper') {
+                    $value = preg_replace('/^(\w+=)/e', "Horde_String::upper('\\1')", $value);
+                }
+                if ($options['casefold'] == 'lower') {
+                    $value = preg_replace('/^(\w+=)/e', "Horde_String::upper('\\1')", $value);
+                }
 
                 if ($options['onlyvalues']) {
                     preg_match('/(.+?)(?<!\\\\)=(.+)/', $value, $matches);
@@ -131,58 +150,48 @@ class Horde_Ldap_Util
 
         if ($options['reverse']) {
             return array_reverse($dn_array);
-        } else {
-            return $dn_array;
         }
+
+        return $dn_array;
     }
 
     /**
-     * Escapes a DN value according to RFC 2253
+     * Escapes DN values according to RFC 2253.
      *
-     * Escapes the given VALUES according to RFC 2253 so that they can be safely used in LDAP DNs.
-     * The characters ",", "+", """, "\", "<", ">", ";", "#", "=" with a special meaning in RFC 2252
-     * are preceeded by ba backslash. Control characters with an ASCII code < 32 are represented as \hexpair.
-     * Finally all leading and trailing spaces are converted to sequences of \20.
+     * Escapes the given VALUES according to RFC 2253 so that they can be
+     * safely used in LDAP DNs.  The characters ",", "+", """, "\", "<", ">",
+     * ";", "#", "=" with a special meaning in RFC 2252 are preceeded by ba
+     * backslash. Control characters with an ASCII code < 32 are represented as
+     * \hexpair.  Finally all leading and trailing spaces are converted to
+     * sequences of \20.
      *
-     * @param array $values An array containing the DN values that should be escaped
+     * @param string|array $values  DN values that should be escaped.
      *
-     * @static
-     * @return array The array $values, but escaped
+     * @return array  The escaped values.
      */
-    public static function escape_dn_value($values = array())
+    public static function escape_dn_value($values)
     {
-        // Parameter validation
+        // Parameter validation.
         if (!is_array($values)) {
             $values = array($values);
         }
 
         foreach ($values as $key => $val) {
-            // Escaping of filter meta characters
-            $val = str_replace('\\', '\\\\', $val);
-            $val = str_replace(',',    '\,', $val);
-            $val = str_replace('+',    '\+', $val);
-            $val = str_replace('"',    '\"', $val);
-            $val = str_replace('<',    '\<', $val);
-            $val = str_replace('>',    '\>', $val);
-            $val = str_replace(';',    '\;', $val);
-            $val = str_replace('#',    '\#', $val);
-            $val = str_replace('=',    '\=', $val);
-
-            // ASCII < 32 escaping
+            // Escaping of filter meta characters.
+            $val = addcslashes($val, '\\,+"<>;#=');
+
+            // ASCII < 32 escaping.
             $val = self::asc2hex32($val);
 
             // Convert all leading and trailing spaces to sequences of \20.
             if (preg_match('/^(\s*)(.+?)(\s*)$/', $val, $matches)) {
-                $val = $matches[2];
-                for ($i = 0; $i < strlen($matches[1]); $i++) {
-                    $val = '\20'.$val;
-                }
-                for ($i = 0; $i < strlen($matches[3]); $i++) {
-                    $val = $val.'\20';
-                }
+                $val = str_repeat('\20', strlen($matches[1])) . $matches[2] . str_repeat('\20', strlen($matches[3]));
             }
 
-            if (null === $val) $val = '\0';  // apply escaped "null" if string is empty
+            if (null === $val) {
+                // Apply escaped "null" if string is empty.
+                $val = '\0';
+            }
 
             $values[$key] = $val;
         }
@@ -191,36 +200,32 @@ class Horde_Ldap_Util
     }
 
     /**
-     * Undoes the conversion done by escape_dn_value().
+     * Unescapes DN values according to RFC 2253.
+     *
+     * Reverts the conversion done by escape_dn_value().
      *
-     * Any escape sequence starting with a baskslash - hexpair or special character -
-     * will be transformed back to the corresponding character.
+     * Any escape sequence starting with a baskslash - hexpair or special
+     * character - will be transformed back to the corresponding character.
      *
-     * @param array $values Array of DN Values
+     * @param array $values  DN values.
      *
-     * @return array Same as $values, but unescaped
-     * @static
+     * @return array  Unescaped DN values.
      */
-    public static function unescape_dn_value($values = array())
+    public static function unescape_dn_value($values)
     {
-        // Parameter validation
+        // Parameter validation.
         if (!is_array($values)) {
             $values = array($values);
         }
 
         foreach ($values as $key => $val) {
-            // strip slashes from special chars
-            $val = str_replace('\\\\', '\\', $val);
-            $val = str_replace('\,',    ',', $val);
-            $val = str_replace('\+',    '+', $val);
-            $val = str_replace('\"',    '"', $val);
-            $val = str_replace('\<',    '<', $val);
-            $val = str_replace('\>',    '>', $val);
-            $val = str_replace('\;',    ';', $val);
-            $val = str_replace('\#',    '#', $val);
-            $val = str_replace('\=',    '=', $val);
-
-            // Translate hex code into ascii
+            // Strip slashes from special chars.
+            $val = str_replace(
+                array('\\\\', '\,', '\+', '\"', '\<', '\>', '\;', '\#', '\='),
+                array('\\', ',', '+', '"', '<', '>', ';', '#', '='),
+                $val);
+
+            // Translate hex code into ascii.
             $values[$key] = self::hex2asc($val);
         }
 
@@ -228,77 +233,87 @@ class Horde_Ldap_Util
     }
 
     /**
-     * Returns the given DN in a canonical form
+     * Converts a DN into a canonical form.
      *
-     * Returns false if DN is not a valid Distinguished Name.
-     * DN can either be a string or an array
-     * as returned by ldap_explode_dn, which is useful when constructing a DN.
-     * The DN array may have be indexed (each array value is a OCL=VALUE pair)
-     * or associative (array key is OCL and value is VALUE).
+     * DN can either be a string or an array as returned by ldap_explode_dn(),
+     * which is useful when constructing a DN.  The DN array may have be
+     * indexed (each array value is a OCL=VALUE pair) or associative (array key
+     * is OCL and value is VALUE).
      *
      * It performs the following operations on the given DN:
-     *     - Removes the leading 'OID.' characters if the type is an OID instead of a name.
-     *     - Escapes all RFC 2253 special characters (",", "+", """, "\", "<", ">", ";", "#", "="), slashes ("/"), and any other character where the ASCII code is < 32 as \hexpair.
-     *     - Converts all leading and trailing spaces in values to be \20.
-     *     - If an RDN contains multiple parts, the parts are re-ordered so that the attribute type names are in alphabetical order.
-     *
-     * OPTIONS is a list of name/value pairs, valid options are:
-     *     casefold    Controls case folding of attribute type names.
-     *                 Attribute values are not affected by this option. The default is to uppercase.
-     *                 Valid values are:
-     *                 lower        Lowercase attribute type names.
-     *                 upper        Uppercase attribute type names. This is the default.
-     *                 none         Do not change attribute type names.
-     *     [NOT IMPLEMENTED] mbcescape   If TRUE, characters that are encoded as a multi-octet UTF-8 sequence will be escaped as \(hexpair){2,*}.
-     *     reverse     If TRUE, the RDN sequence is reversed.
-     *     separator   Separator to use between RDNs. Defaults to comma (',').
-     *
-     * Note: The empty string "" is a valid DN, so be sure not to do a "$can_dn == false" test,
-     *       because an empty string evaluates to false. Use the "===" operator instead.
-     *
-     * @param array|string $dn      The DN
-     * @param array        $options Options to use
-     *
-     * @static
-     * @return false|string The canonical DN or FALSE
-     * @todo implement option mbcescape
+     * - Removes the leading 'OID.' characters if the type is an OID instead of
+     *   a name.
+     * - Escapes all RFC 2253 special characters (",", "+", """, "\", "<", ">",
+     *   ";", "#", "="), slashes ("/"), and any other character where the ASCII
+     *   code is < 32 as \hexpair.
+     * - Converts all leading and trailing spaces in values to be \20.
+     * - If an RDN contains multiple parts, the parts are re-ordered so that
+     *   the attribute type names are in alphabetical order.
+     *
+     * $options is a list of name/value pairs, valid options are:
+
+     * - casefold:  Controls case folding of attribute type names. Attribute
+     *              values are not affected by this option. The default is to
+     *              uppercase. Valid values are:
+     *              - lower: Lowercase attribute type names.
+     *              - upper: Uppercase attribute type names.
+     *              - none:  Do not change attribute type names.
+     * - reverse:   If true, the RDN sequence is reversed.
+     * - separator: Separator to use between RDNs. Defaults to comma (',').
+     *
+     * The empty string "" is a valid DN, so be sure not to do a "$can_dn ==
+     * false" test, because an empty string evaluates to false. Use the "==="
+     * operator instead.
+     *
+     * @param array|string $dn      The DN.
+     * @param array        $options Options to use.
+     *
+     * @return boolean|string The canonical DN or false if the DN is not valid.
      */
-    public static function canonical_dn($dn, $options = array('casefold' => 'upper', 'separator' => ','))
+    public static function canonical_dn($dn, $options = array())
     {
-        if ($dn === '') return $dn;  // empty DN is valid!
-
-        // options check
-        if (!isset($options['reverse'])) {
-            $options['reverse'] = false;
-        } else {
-            $options['reverse'] = true;
+        if ($dn === '') {
+            // Empty DN is valid.
+            return $dn;
         }
-        if (!isset($options['casefold']))  $options['casefold'] = 'upper';
-        if (!isset($options['separator'])) $options['separator'] = ',';
 
+        // Options check.
+        $options['reverse'] = !empty($options['reverse']);
+        if (!isset($options['casefold'])) {
+            $options['casefold'] = 'upper';
+        }
+        if (!isset($options['separator'])) {
+            $options['separator'] = ',';
+        }
 
         if (!is_array($dn)) {
-            // It is not clear to me if the perl implementation splits by the user defined
-            // separator or if it just uses this separator to construct the new DN
-            $dn = preg_split('/(?<=[^\\\\])'.$options['separator'].'/', $dn);
+            // It is not clear to me if the perl implementation splits by the
+            // user defined separator or if it just uses this separator to
+            // construct the new DN.
+            $dn = preg_split('/(?<=[^\\\\])' . $options['separator'] . '/', $dn);
 
-            // clear wrong splitting (possibly we have split too much)
-            $dn = self::correct_dn_splitting($dn, $options['separator']);
+            // Clear wrong splitting (possibly we have split too much).
+            $dn = self::_correct_dn_splitting($dn, $options['separator']);
         } else {
-            // Is array, check, if the array is indexed or associative
+            // Is array, check if the array is indexed or associative.
             $assoc = false;
             foreach ($dn as $dn_key => $dn_part) {
                 if (!is_int($dn_key)) {
                     $assoc = true;
+                    break;
                 }
             }
-            // convert to indexed, if associative array detected
+
+            // Convert to indexed, if associative array detected.
             if ($assoc) {
                 $newdn = array();
                 foreach ($dn as $dn_key => $dn_part) {
                     if (is_array($dn_part)) {
-                        ksort($dn_part, SORT_STRING); // we assume here, that the rdn parts are also associative
-                        $newdn[] = $dn_part;  // copy array as-is, so we can resolve it later
+                        // We assume here that the RDN parts are also
+                        // associative.
+                        ksort($dn_part, SORT_STRING);
+                        // Copy array as-is, so we can resolve it later.
+                        $newdn[] = $dn_part;
                     } else {
                         $newdn[] = $dn_key.'='.$dn_part;
                     }
@@ -307,99 +322,116 @@ class Horde_Ldap_Util
             }
         }
 
-        // Escaping and casefolding
+        // Escaping and casefolding.
         foreach ($dn as $pos => $dnval) {
             if (is_array($dnval)) {
-                // subarray detected, this means very surely, that we had
-                // a multivalued dn part, which must be resolved
+                // Subarray detected, this means most probably that we had a
+                // multivalued DN part, which must be resolved.
                 $dnval_new = '';
                 foreach ($dnval as $subkey => $subval) {
-                    // build RDN part
+                    // Build RDN part.
                     if (!is_int($subkey)) {
-                        $subval = $subkey.'='.$subval;
+                        $subval = $subkey . '=' . $subval;
                     }
                     $subval_processed = self::canonical_dn($subval);
-                    if (false === $subval_processed) return false;
-                    $dnval_new .= $subval_processed.'+';
+                    if (false === $subval_processed) {
+                        return false;
+                    }
+                    $dnval_new .= $subval_processed . '+';
                 }
-                $dn[$pos] = substr($dnval_new, 0, -1); // store RDN part, strip last plus
+                // Store RDN part, strip last plus.
+                $dn[$pos] = substr($dnval_new, 0, -1);
             } else {
-                // try to split multivalued RDNS into array
+                // Try to split multivalued RDNs into array.
                 $rdns = self::split_rdn_multival($dnval);
                 if (count($rdns) > 1) {
-                    // Multivalued RDN was detected!
-                    // The RDN value is expected to be correctly split by split_rdn_multival().
-                    // It's time to sort the RDN and build the DN!
+                    // Multivalued RDN was detected. The RDN value is expected
+                    // to be correctly split by split_rdn_multival(). It's time
+                    // to sort the RDN and build the DN.
                     $rdn_string = '';
-                    sort($rdns, SORT_STRING); // Sort RDN keys alphabetically
+                    // Sort RDN keys alphabetically.
+                    sort($rdns, SORT_STRING);
                     foreach ($rdns as $rdn) {
                         $subval_processed = self::canonical_dn($rdn);
-                        if (false === $subval_processed) return false;
-                        $rdn_string .= $subval_processed.'+';
+                        if (false === $subval_processed) {
+                            return false;
+                        }
+                        $rdn_string .= $subval_processed . '+';
                     }
 
-                    $dn[$pos] = substr($rdn_string, 0, -1); // store RDN part, strip last plus
-
+                    // Store RDN part, strip last plus.
+                    $dn[$pos] = substr($rdn_string, 0, -1);
                 } else {
-                    // no multivalued RDN!
-                    // split at first unescaped "="
+                    // No multivalued RDN. Split at first unescaped "=".
                     $dn_comp = preg_split('/(?<=[^\\\\])=/', $rdns[0], 2);
-                    $ocl     = ltrim($dn_comp[0]);  // trim left whitespaces 'cause of "cn=foo, l=bar" syntax (whitespace after comma)
-                    $val     = $dn_comp[1];
+                    // Trim left whitespaces because of "cn=foo, l=bar" syntax
+                    // (whitespace after comma).
+                    $ocl = ltrim($dn_comp[0]);
+                    $val = $dn_comp[1];
 
-                    // strip 'OID.', otherwise apply casefolding and escaping
-                    if (substr(strtolower($ocl), 0, 4) == 'oid.') {
+                    // Strip 'OID.', otherwise apply casefolding and escaping.
+                    if (substr(Horde_String::lower($ocl), 0, 4) == 'oid.') {
                         $ocl = substr($ocl, 4);
                     } else {
-                        if ($options['casefold'] == 'upper') $ocl = strtoupper($ocl);
-                        if ($options['casefold'] == 'lower') $ocl = strtolower($ocl);
+                        if ($options['casefold'] == 'upper') {
+                            $ocl = strtoupper($ocl);
+                        }
+                        if ($options['casefold'] == 'lower') {
+                            $ocl = strtolower($ocl);
+                        }
                         $ocl = self::escape_dn_value(array($ocl));
                         $ocl = $ocl[0];
                     }
 
-                    // escaping of dn-value
+                    // Escaping of DN value.
                     $val = self::escape_dn_value(array($val));
                     $val = str_replace('/', '\/', $val[0]);
 
-                    $dn[$pos] = $ocl.'='.$val;
+                    $dn[$pos] = $ocl . '=' . $val;
                 }
             }
         }
 
-        if ($options['reverse']) $dn = array_reverse($dn);
+        if ($options['reverse']) {
+            $dn = array_reverse($dn);
+        }
+
         return implode($options['separator'], $dn);
     }
 
     /**
-     * Escapes the given VALUES according to RFC 2254 so that they can be safely used in LDAP filters.
+     * Escapes the given values according to RFC 2254 so that they can be
+     * safely used in LDAP filters.
      *
-     * Any control characters with an ACII code < 32 as well as the characters with special meaning in
-     * LDAP filters "*", "(", ")", and "\" (the backslash) are converted into the representation of a
-     * backslash followed by two hex digits representing the hexadecimal value of the character.
+     * Any control characters with an ACII code < 32 as well as the characters
+     * with special meaning in LDAP filters "*", "(", ")", and "\" (the
+     * backslash) are converted into the representation of a backslash followed
+     * by two hex digits representing the hexadecimal value of the character.
      *
-     * @param array $values Array of values to escape
+     * @param array $values Values to escape.
      *
-     * @static
-     * @return array Array $values, but escaped
+     * @return array Escaped values.
      */
-    public static function escape_filter_value($values = array())
+    public static function escape_filter_value($values)
     {
-        // Parameter validation
+        // Parameter validation.
         if (!is_array($values)) {
             $values = array($values);
         }
 
         foreach ($values as $key => $val) {
-            // Escaping of filter meta characters
-            $val = str_replace('\\', '\5c', $val);
-            $val = str_replace('*',  '\2a', $val);
-            $val = str_replace('(',  '\28', $val);
-            $val = str_replace(')',  '\29', $val);
+            // Escaping of filter meta characters.
+            $val = str_replace(array('\\', '*', '(', ')'),
+                               array('\5c', '\2a', '\28', '\29'),
+                               $val);
 
-            // ASCII < 32 escaping
+            // ASCII < 32 escaping.
             $val = self::asc2hex32($val);
 
-            if (null === $val) $val = '\0';  // apply escaped "null" if string is empty
+            if (null === $val) {
+                // Apply escaped "null" if string is empty.
+                $val = '\0';
+            }
 
             $values[$key] = $val;
         }
@@ -408,24 +440,26 @@ class Horde_Ldap_Util
     }
 
     /**
-     * Undoes the conversion done by {@link escape_filter_value()}.
+     * Unescapes the given values according to RFC 2254.
      *
-     * Converts any sequences of a backslash followed by two hex digits into the corresponding character.
+     * Reverses the conversion done by {@link escape_filter_value()}.
      *
-     * @param array $values Array of values to escape
+     * Converts any sequences of a backslash followed by two hex digits into
+     * the corresponding character.
      *
-     * @static
-     * @return array Array $values, but unescaped
+     * @param array $values Values to unescape.
+     *
+     * @return array Unescaped values.
      */
     public static function unescape_filter_value($values = array())
     {
-        // Parameter validation
+        // Parameter validation.
         if (!is_array($values)) {
             $values = array($values);
         }
 
         foreach ($values as $key => $value) {
-            // Translate hex code into ascii
+            // Translate hex code into ascii.
             $values[$key] = self::hex2asc($value);
         }
 
@@ -433,12 +467,11 @@ class Horde_Ldap_Util
     }
 
     /**
-     * Converts all ASCII chars < 32 to "\HEX"
+     * Converts all ASCII chars < 32 to "\HEX".
      *
-     * @param string $string String to convert
+     * @param string $string String to convert.
      *
-     * @static
-     * @return string
+     * @return string Hexadecimal representation of $string.
      */
     public static function asc2hex32($string)
     {
@@ -446,72 +479,77 @@ class Horde_Ldap_Util
             $char = substr($string, $i, 1);
             if (ord($char) < 32) {
                 $hex = dechex(ord($char));
-                if (strlen($hex) == 1) $hex = '0'.$hex;
-                $string = str_replace($char, '\\'.$hex, $string);
+                if (strlen($hex) == 1) {
+                    $hex = '0' . $hex;
+                }
+                $string = str_replace($char, '\\' . $hex, $string);
             }
         }
         return $string;
     }
 
     /**
-     * Converts all Hex expressions ("\HEX") to their original ASCII characters
-     *
-     * @param string $string String to convert
+     * Converts all hexadecimal expressions ("\HEX") to their original ASCII
+     * characters.
      *
-     * @static
      * @author beni@php.net, heavily based on work from DavidSmith@byu.net
-     * @return string
+     *
+     * @param string $string String to convert.
+     *
+     * @return string ASCII representation of $string.
      */
     public static function hex2asc($string)
     {
-        $string = preg_replace("/\\\([0-9A-Fa-f]{2})/e", "''.chr(hexdec('\\1')).''", $string);
-        return $string;
+        return preg_replace('/\\\([0-9A-Fa-f]{2})/e', "chr(hexdec('\\1'))", $string);
     }
 
     /**
-     * Split an multivalued RDN value into an Array
+     * Splits a multivalued RDN value into an array.
      *
-     * A RDN can contain multiple values, spearated by a plus sign.
-     * This function returns each separate ocl=value pair of the RDN part.
+     * A RDN can contain multiple values, spearated by a plus sign. This method
+     * returns each separate ocl=value pair of the RDN part.
      *
-     * If no multivalued RDN is detected, an array containing only
-     * the original rdn part is returned.
+     * If no multivalued RDN is detected, an array containing only the original
+     * RDN part is returned.
      *
      * For example, the multivalued RDN 'OU=Sales+CN=J. Smith' is exploded to:
      * <kbd>array([0] => 'OU=Sales', [1] => 'CN=J. Smith')</kbd>
      *
-     * The method trys to be smart if it encounters unescaped "+" characters, but may fail,
-     * so ensure escaped "+"es in attr names and attr values.
+     * The method tries to be smart if it encounters unescaped "+" characters,
+     * but may fail, so better ensure escaped "+" in attribute names and
+     * values.
      *
-     * [BUG] If you have a multivalued RDN with unescaped plus characters
-     *       and there is a unescaped plus sign at the end of an value followed by an
-     *       attribute name containing an unescaped plus, then you will get wrong splitting:
+     * [BUG] If you have a multivalued RDN with unescaped plus characters and
+     *       there is a unescaped plus sign at the end of an value followed by
+     *       an attribute name containing an unescaped plus, then you will get
+     *       wrong splitting:
      *         $rdn = 'OU=Sales+C+N=J. Smith';
      *       returns:
      *         array('OU=Sales+C', 'N=J. Smith');
-     *       The "C+" is treaten as value of the first pair instead as attr name of the second pair.
-     *       To prevent this, escape correctly.
+     *       The "C+" is treaten as the value of the first pair instead of as
+     *       the attribute name of the second pair. To prevent this, escape
+     *       correctly.
      *
-     * @param string $rdn Part of an (multivalued) escaped RDN (eg. ou=foo OR ou=foo+cn=bar)
+     * @param string $rdn Part of a (multivalued) escaped RDN (e.g. ou=foo or
+     *                    ou=foo+cn=bar)
      *
-     * @static
-     * @return array Array with the components of the multivalued RDN or Error
+     * @return array The components of the multivalued RDN.
      */
     public static function split_rdn_multival($rdn)
     {
         $rdns = preg_split('/(?<!\\\\)\+/', $rdn);
-        $rdns = self::correct_dn_splitting($rdns, '+');
+        $rdns = self::_correct_dn_splitting($rdns, '+');
         return array_values($rdns);
     }
 
     /**
-     * Splits a attribute=value syntax into an array
+     * Splits a attribute=value syntax into an array.
      *
      * The split will occur at the first unescaped '=' character.
      *
-     * @param string $attr Attribute and Value Syntax
+     * @param string $attr An attribute-value string.
      *
-     * @return array Indexed array: 0=attribute name, 1=attribute value
+     * @return array Indexed array: 0=attribute name, 1=attribute value.
      */
     public static function split_attribute_string($attr)
     {
@@ -519,32 +557,37 @@ class Horde_Ldap_Util
     }
 
     /**
-     * Corrects splitting of dn parts
+     * Corrects splitting of DN parts.
      *
-     * @param array $dn        Raw DN array
-     * @param array $separator Separator that was used when splitting
+     * @param array $dn        Raw DN array.
+     * @param array $separator Separator that was used when splitting.
      *
-     * @return array Corrected array
-     * @access protected
+     * @return array Corrected array.
      */
-    protected static function correct_dn_splitting($dn = array(), $separator = ',')
+    protected static function _correct_dn_splitting($dn = array(),
+                                                    $separator = ',')
     {
         foreach ($dn as $key => $dn_value) {
-            $dn_value = $dn[$key]; // refresh value (foreach caches!)
-            // if the dn_value is not in attr=value format, then we had an
-            // unescaped separator character inside the attr name or the value.
-            // We assume, that it was the attribute value.
-            // [TODO] To solve this, we might ask the schema. Keep in mind, that UTIL class
-            //        must remain independent from the other classes or connections.
+            // Refresh value (foreach caches!)
+            $dn_value = $dn[$key];
+            // If $dn_value is not in attr=value format, we had an unescaped
+            // separator character inside the attr name or the value. We assume
+            // that it was the attribute value.
+
+            // TODO: To solve this, we might ask the schema. The
+            //       Horde_Ldap_Util class must remain independent from the
+            //       other classes or connections though.
             if (!preg_match('/.+(?<!\\\\)=.+/', $dn_value)) {
                 unset($dn[$key]);
-                if (array_key_exists($key-1, $dn)) {
-                    $dn[$key-1] = $dn[$key-1].$separator.$dn_value; // append to previous attr value
+                if (array_key_exists($key - 1, $dn)) {
+                    // Append to previous attribute value.
+                    $dn[$key - 1] = $dn[$key - 1] . $separator . $dn_value;
                 } else {
-                    $dn[$key+1] = $dn_value.$separator.$dn[$key+1]; // first element: prepend to next attr name
+                    // First element: prepend to next attribute name.
+                    $dn[$key + 1] = $dn_value . $separator . $dn[$key + 1];
                 }
             }
         }
         return array_values($dn);
     }
-}
\ No newline at end of file
+}