Converts a DN string into an array of RDNs.

This will also decode hex characters into their true
UTF-8 representation embedded inside the DN as well.

@param string $dn
@param bool   $removeAttributePrefixes

@return array|false
505716
public static function explodeDn($dn, $removeAttributePrefixes = true)
    {
        $dn = ldap_explode_dn($dn, ($removeAttributePrefixes ? 1 : 0));

        if (is_array($dn) && array_key_exists('count', $dn)) {
            foreach ($dn as $rdn => $value) {
                $dn[$rdn] = self::unescape($value);
            }
        }

        return $dn;
    }
993953
private function decodeHost($hostname)
    {
        if (preg_match('/^[\\x00-\\x7F]*$/', $hostname)) {
            return $hostname;
        } elseif ($this->mode !== self::MODE_IDNA2003) {
            throw new \InvalidArgumentException("Invalid hostname '$hostname'");
        }

        $hostname = idn_to_ascii($hostname);

        if ($hostname === false) {
            throw new \InvalidArgumentException("Invalid hostname '$hostname'");
        }

        return $hostname;
    }
67166
public function listing($dn, $filter, array $attributes)
    {
        if ($this->suppressErrors) {
            return @ldap_list($this->getConnection(), $dn, $filter, $attributes);
        }

        return ldap_list($this->getConnection(), $dn, $filter, $attributes);
    }
188059
protected function cleanupEncoding(array $toDecode)
    {
        $decodedParams = [];
        foreach ($toDecode as $key => $value) {
            $decodedValue = \is_array($value) ? $this->cleanupEncoding($value) : (mb_check_encoding($value, 'UTF-8') ? $value : utf8_encode($value));
            $decodedParams[mb_check_encoding($key, 'UTF-8') ? $key : utf8_encode($key)] = $decodedValue;
        }

        return $decodedParams;
    }
322388
private function decodeNode(\DOMNode $node)
    {
        $nodeName = $node->nodeName;

        $nodeType = substr($nodeName, 5);

        if (self::DATATYPE_OBJECT === $nodeType) {
            return $this->decodeObjectNode($node);
        }

        if (self::DATATYPE_ARRAY === $nodeType) {
            return $this->decodeArrayNode($node);
        }

        if (self::DATATYPE_BOOLEAN === $nodeType) {
            return $this->decodeBooleanNode($node);
        }

        if (self::DATATYPE_STRING === $nodeType) {
            return $this->decodeStringNode($node);
        }

        if (self::DATATYPE_NUMBER === $nodeType) {
            return $this->decodeNumberNode($node);
        }

        if (self::DATATYPE_NULL === $nodeType) {
            return null;
        }

        throw DeserializerRuntimeException::createNotParsable($this->getContentType());
    }
599023
protected function extractCNFromDN($dn)
    {

        // explode the DN
        $splitArray = explode(',', $dn);
        $keyValue = array();

        // iterate over all elements
        foreach ($splitArray as $value) {
            $tempArray  = explode('=', $value);
            $keyValue[$tempArray[0]] = array();
            $keyValue[$tempArray[0]][] = $tempArray[1];
        }

        // return the CN
        return $keyValue[LdapLoginmodule::CN];
    }
1155238
protected function convertNamesToLdap(array $attributes)
    {
        return !$this->schema ? $attributes : (new AttributeNameResolver($this->schema))->toLdap($attributes);
    }
731057
private function extractSuffix($hostname)
    {
        // If hostname has leading dot, it's invalid.
        // If hostname is a single label domain makes, it's invalid.

        if (Str::startsWith($hostname, '.') || Str::strpos($hostname, '.') === false) {
            return null;
        }

        // If domain is in punycode, it will be converted to IDN.

        $isPunycoded = Str::strpos($hostname, 'xn--') !== false;

        if ($isPunycoded) {
            $hostname = $this->idn->toUTF8($hostname);
        }

        // URI producers should use names that conform to the DNS syntax, even when use of DNS is not immediately
        // apparent, and should limit these names to no more than 255 characters in length.
        //
        // @see https://tools.ietf.org/html/rfc3986
        // @see http://blogs.msdn.com/b/oldnewthing/archive/2012/04/12/10292868.aspx

        if (Str::length($hostname) > 253) {
            return null;
        }

        // The DNS itself places only one restriction on the particular labels that can be used to identify resource
        // records. That one restriction relates to the length of the label and the full name. The length of any one
        // label is limited to between 1 and 63 octets. A full domain name is limited to 255 octets (including the
        // separators).
        //
        // @see http://tools.ietf.org/html/rfc2181

        try {
            $asciiHostname = $this->idn->toASCII($hostname);
        } catch (OutOfBoundsException $e) {
            return null;
        }

        if (0 === preg_match(self::HOSTNAME_PATTERN, $asciiHostname)) {
            return null;
        }

        $suffix = $this->parseSuffix($hostname);

        if (null === $suffix) {
            if (!($this->extractionMode & static::MODE_ALLOW_NOT_EXISTING_SUFFIXES)) {
                return null;
            }

            $suffix = Str::substr($hostname, Str::strrpos($hostname, '.') + 1);
        }

        // If domain is punycoded, suffix will be converted to punycode.

        return $isPunycoded ? $this->idn->toASCII($suffix) : $suffix;
    }
193304
static function dn_decode($str)
    {
        $str = str_pad(strtr($str, '-_', '+/'), strlen($str) % 4, '=', STR_PAD_RIGHT);
        return base64_decode($str);
    }
35480
public static function extractDsn($dsn)
    {
        // Parse DSN to array
        $dsn = str_replace(';', "\n", $dsn);

        $values = [];

        foreach (explode("\n", $dsn) as $value) {
            [$k, $v] = explode('=', trim($value));

            $values[$k] = $v;
        }

        return $values;
    }
809475
public static function stripTagsAndAtts($content, $allowedTags = '', $allowedAtts = '')
    {
        if (isset($allowedTags) && is_array($allowedTags)) {
            $content = strip_tags($content, implode($allowedTags));
        } else {
            $content = strip_tags($content);
        }

        //Strip attributes
        $atts = \Municipio\Helper\Html::getHtmlAttributes($content);

        if ($atts && !empty($atts)) {
            if (isset($allowedAtts) && is_array($allowedAtts)) {
                foreach ($allowedAtts as $attribute) {
                    unset($atts[$attribute]);
                }
            }

            foreach ($atts as $att) {
                $content = str_replace($att, "", $content);
            }
        }

        return $content;
    }
481601
function removeAttribute($id, $disposition = self::ATTR_ALL)
    {
        $attributes = &$this->_subArray($this->currentCert, 'certificationRequestInfo/attributes');

        if (!is_array($attributes)) {
            return false;
        }

        $result = false;
        foreach ($attributes as $key => $attribute) {
            if ($attribute['type'] == $id) {
                $n = count($attribute['value']);
                switch (true) {
                    case $disposition == self::ATTR_APPEND:
                    case $disposition == self::ATTR_REPLACE:
                        return false;
                    case $disposition >= $n:
                        $disposition -= $n;
                        break;
                    case $disposition == self::ATTR_ALL:
                    case $n == 1:
                        unset($attributes[$key]);
                        $result = true;
                        break;
                    default:
                        unset($attributes[$key]['value'][$disposition]);
                        $attributes[$key]['value'] = array_values($attributes[$key]['value']);
                        $result = true;
                        break;
                }
                if ($result && $disposition != self::ATTR_ALL) {
                    break;
                }
            }
        }

        $attributes = array_values($attributes);
        return $result;
    }
458914
final public static function parseAttributes($attributes, $ignore = array()) {
        if (!is_array($attributes)) {
            return $attributes;
        }
        $return = "";
        foreach ($attributes as $attr => $value) {
            if (in_array($attr, $ignore))
                continue;
            $return .= $attr . '="' . $value . '" ';
        }

        return $return;
    }
373010
protected function decodeValues(&$values)
    {
        if (is_array($values)) {
            foreach ($values as &$value) {
                $value = $this->decodeValues($value);
            }
            return $values;
        } elseif (is_string($values)) {
            return html_entity_decode($values, ENT_COMPAT, 'UTF-8');
        }
        return $values;
    }
609375
public function list_entries($dn, $filter, $attributes = array('dn'))
    {
        $list = array();
        $this->_debug("C: List $dn [{$filter}]");

        if ($result = ldap_list($this->conn, $dn, $filter, $attributes)) {
            $list = ldap_get_entries($this->conn, $result);

            if ($list === false) {
                $this->_error("ldap_get_entries() failed with " . ldap_error($this->conn));
                return array();
            }

            $count = $list['count'];
            unset($list['count']);

            $this->_debug("S: $count record(s)");
        }
        else {
            $this->_error("ldap_list() failed with " . ldap_error($this->conn));
        }

        return $list;
    }
896745
function getDN($format = FILE_X509_DN_ARRAY, $dn = NULL)
    {
        if (!isset($dn)) {
            $dn = isset($this->currentCert['tbsCertList']) ? $this->currentCert['tbsCertList']['issuer'] : $this->dn;
        }

        switch ((int) $format) {
            case FILE_X509_DN_ARRAY:
                return $dn;
            case FILE_X509_DN_ASN1:
                $asn1 = new File_ASN1();
                $asn1->loadOIDs($this->oids);
                $filters = array();
                $filters['rdnSequence']['value'] = array('type' => FILE_ASN1_TYPE_UTF8_STRING);
                $asn1->loadFilters($filters);
                return $asn1->encodeDER($dn, $this->Name);
            case FILE_X509_DN_OPENSSL:
                $dn = $this->getDN(FILE_X509_DN_STRING, $dn);
                if ($dn === false) {
                    return false;
                }
                $attrs = preg_split('#((?:^|, *|/)[a-z][a-z0-9]*=)#i', $dn, -1, PREG_SPLIT_DELIM_CAPTURE);
                $dn = array();
                for ($i = 1; $i < count($attrs); $i += 2) {
                    $prop = trim($attrs[$i], ', =/');
                    $value = $attrs[$i + 1];
                    if (!isset($dn[$prop])) {
                        $dn[$prop] = $value;
                    } else {
                        $dn[$prop] = array_merge((array) $dn[$prop], array($value));
                    }
                }
                return $dn;
            case FILE_X509_DN_CANON:
                //  No SEQUENCE around RDNs and all string values normalized as
                // trimmed lowercase UTF-8 with all spacing  as one blank.
                $asn1 = new File_ASN1();
                $asn1->loadOIDs($this->oids);
                $filters = array();
                $filters['value'] = array('type' => FILE_ASN1_TYPE_UTF8_STRING);
                $asn1->loadFilters($filters);
                $result = '';
                foreach ($dn['rdnSequence'] as $rdn) {
                    foreach ($rdn as &$attr) {
                        if (is_array($attr['value'])) {
                            foreach ($attr['value'] as $type => $v) {
                                $type = array_search($type, $asn1->ANYmap, true);
                                if ($type !== false && isset($asn1->stringTypeSize[$type])) {
                                    $v = $asn1->convert($v, $type);
                                    if ($v !== false) {
                                        $v = preg_replace('/\s+/', ' ', $v);
                                        $attr['value'] = strtolower(trim($v));
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    $result .= $asn1->encodeDER($rdn, $this->RelativeDistinguishedName);
                }
                return $result;
            case FILE_X509_DN_HASH:
                $dn = $this->getDN(FILE_X509_DN_CANON, $dn);
                if (!class_exists('Crypt_Hash')) {
                    require_once('Crypt/Hash.php');
                }
                $hash = new Crypt_Hash('sha1');
                $hash = $hash->hash($dn);
                extract(unpack('Vhash', $hash));
                return strtolower(bin2hex(pack('N', $hash)));
        }

        // Defaut is to return a string.
        $start = true;
        $output = '';
        $asn1 = new File_ASN1();
        foreach ($dn['rdnSequence'] as $field) {
            $prop = $field[0]['type'];
            $value = $field[0]['value'];

            $delim = ', ';
            switch ($prop) {
                case 'id-at-countryName':
                    $desc = 'C=';
                    break;
                case 'id-at-stateOrProvinceName':
                    $desc = 'ST=';
                    break;
                case 'id-at-organizationName':
                    $desc = 'O=';
                    break;
                case 'id-at-organizationalUnitName':
                    $desc = 'OU=';
                    break;
                case 'id-at-commonName':
                    $desc = 'CN=';
                    break;
                case 'id-at-localityName':
                    $desc = 'L=';
                    break;
                case 'id-at-surname':
                    $desc = 'SN=';
                    break;
                case 'id-at-uniqueIdentifier':
                    $delim = '/';
                    $desc = 'x500UniqueIdentifier=';
                    break;
                default:
                    $delim = '/';
                    $desc = preg_replace('#.+-([^-]+)$#', '$1',  $prop) . '=';
            }

            if (!$start) {
                $output.= $delim;
            }
            if (is_array($value)) {
                foreach ($value as $type => $v) {
                    $type = array_search($type, $asn1->ANYmap, true);
                    if ($type !== false && isset($asn1->stringTypeSize[$type])) {
                        $v = $asn1->convert($v, $type);
                        if ($v !== false) {
                            $value = $v;
                            break;
                        }
                    }
                }
                if (is_array($value)) {
                    $value = array_pop($value); // Always strip data type.
                }
            }
            $output.= $desc . $value;
            $start = false;
        }

        return $output;
    }
1346365
public static function substituteAttributes(array $attributes, $uri)
    {
        foreach ($attributes as $key => $value) {
            if ($value instanceof RouteBindable)
                $value = $value->getWildcardValue();

            $uri = str_replace(['{'.$key.'?}', '{'.$key.'}'], $value, $uri);
        }

        // delete empty optional arguments that are not in the $attributes array
        return preg_replace('/\/{[^)]+\?}/', '', $uri);
    }