summaryrefslogtreecommitdiffstats
path: root/library/Icinga/Protocol/Ldap/LdapUtils.php
blob: 9c9ae10113b54c00172a3ee5de1114b448247fe2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<?php
/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */

namespace Icinga\Protocol\Ldap;

/**
 * This class provides useful LDAP-related functions
 *
 * @copyright  Copyright (c) 2013 Icinga-Web Team <info@icinga.com>
 * @author     Icinga-Web Team <info@icinga.com>
 * @package    Icinga\Protocol\Ldap
 * @license    http://www.gnu.org/copyleft/gpl.html GNU General Public License
 */
class LdapUtils
{
    /**
     * Extends PHPs ldap_explode_dn() function
     *
     * UTF-8 chars like German umlauts would otherwise be escaped and shown
     * as backslash-prefixed hexcode-sequenzes.
     *
     * @param  string  $dn        DN
     * @param  boolean $with_type Returns 'type=value' when true and 'value' when false
     *
     * @return array
     */
    public static function explodeDN($dn, $with_type = true)
    {
        $res = ldap_explode_dn($dn, $with_type ? 0 : 1);

        foreach ($res as $k => $v) {
            $res[$k] = preg_replace_callback(
                '/\\\([0-9a-f]{2})/i',
                function ($m) {
                    return chr(hexdec($m[1]));
                },
                $v
            );
        }
        unset($res['count']);
        return $res;
    }

    /**
     * Implode unquoted RDNs to a DN
     *
     * TODO: throw away, this is not how it shall be done
     *
     * @param  array $parts DN-component
     *
     * @return string
     */
    public static function implodeDN($parts)
    {
        $str = '';
        foreach ($parts as $part) {
            if ($str !== '') {
                $str .= ',';
            }
            list($key, $val) = preg_split('~=~', $part, 2);
            $str .= $key . '=' . self::quoteForDN($val);
        }
        return $str;
    }

    /**
     * Test if supplied value looks like a DN
     *
     * @param  mixed $value
     *
     * @return bool
     */
    public static function isDn($value)
    {
        if (is_string($value)) {
            return ldap_dn2ufn($value) !== false;
        }
        return false;
    }

    /**
     * Quote a string that should be used in a DN
     *
     * Special characters will be escaped
     *
     * @param  string $str DN-component
     *
     * @return string
     */
    public static function quoteForDN($str)
    {
        return self::quoteChars(
            $str,
            array(
                ',',
                '=',
                '+',
                '<',
                '>',
                ';',
                '\\',
                '"',
                '#'
            )
        );
    }

    /**
     * Quote a string that should be used in an LDAP search
     *
     * Special characters will be escaped
     *
     * @param  string String to be escaped
     * @param bool $allow_wildcard
     * @return string
     */
    public static function quoteForSearch($str, $allow_wildcard = false)
    {
        if ($allow_wildcard) {
            return self::quoteChars($str, array('(', ')', '\\', chr(0)));
        }
        return self::quoteChars($str, array('*', '(', ')', '\\', chr(0)));
    }

    /**
     * Escape given characters in the given string
     *
     * Special characters will be escaped
     *
     * @param $str
     * @param $chars
     * @internal param String $string to be escaped
     * @return string
     */
    protected static function quoteChars($str, $chars)
    {
        $quotedChars = array();
        foreach ($chars as $k => $v) {
            // Temporarily prefixing with illegal '('
            $quotedChars[$k] = '(' . str_pad(dechex(ord($v)), 2, '0');
        }
        $str = str_replace($chars, $quotedChars, $str);
        // Replacing temporary '(' with '\\'. This is a workaround, as
        // str_replace behaves pretty strange with leading a backslash:
        $str = preg_replace('~\(~', '\\', $str);
        return $str;
    }
}