/** * 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. * * 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') * * @static * @author beni@php.net * @param string $dn The DN that should be exploded * @param array $options Options to use * @return array Parts of the exploded DN * @todo implement BER */ function ldap_explode_dn($dn, $options = array('casefold' => 'upper')) { $options['onlyvalues'] == true ? $options['onlyvalues'] = 1 : ($options['onlyvalues'] = 0); !isset($options['reverse']) ? $options['reverse'] = false : ($options['reverse'] = true); if (!isset($options['casefold'])) { $options['casefold'] = 'upper'; } // Escaping of DN and stripping of "OID." $dn = Net_LDAP_Util::canonical_dn($dn); // splitting the DN $dn_array = preg_split('/(?<=[^\\\\]),/', $dn); // 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 = Net_LDAP_Util::unescape_dn_value($value); $rdns = Net_LDAP_Util::split_rdn_multival($value_u[0]); if (count($rdns) > 1) { // MV 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); } if ($options['onlyvalues']) { preg_match('/(.+?)(?<!\\\\)=(.+)/', $subrdn_v, $matches); $rdn_ocl = $matches[1]; $rdn_val = $matches[2]; $unescaped = Net_LDAP_Util::unescape_dn_value($rdn_val); $rdns[$subrdn_k] = $unescaped[0]; } else { $unescaped = Net_LDAP_Util::unescape_dn_value($subrdn_v); $rdns[$subrdn_k] = $unescaped[0]; } } $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); } if ($options['onlyvalues']) { preg_match('/(.+?)(?<!\\\\)=(.+)/', $value, $matches); $dn_ocl = $matches[1]; $dn_val = $matches[2]; $unescaped = Net_LDAP_Util::unescape_dn_value($dn_val); $dn_array[$key] = $unescaped[0]; } else { $unescaped = Net_LDAP_Util::unescape_dn_value($value); $dn_array[$key] = $unescaped[0]; } } } if ($options['reverse']) { return array_reverse($dn_array); } else { return $dn_array; } }