1<?php
2/**
3 * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
4 * Version 4.0.4
5 *
6 * PHP Version 5 with SSL and LDAP support
7 *
8 * Written by Scott Barnett, Richard Hyland
9 *   email: scott@wiggumworld.com, adldap@richardhyland.com
10 *   http://adldap.sourceforge.net/
11 *
12 * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
13 *
14 * We'd appreciate any improvements or additions to be submitted back
15 * to benefit the entire community :)
16 *
17 * This library is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Lesser General Public
19 * License as published by the Free Software Foundation; either
20 * version 2.1 of the License.
21 *
22 * This library is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25 * Lesser General Public License for more details.
26 *
27 * @category ToolsAndUtilities
28 * @package adLDAP
29 * @subpackage Utils
30 * @author Scott Barnett, Richard Hyland
31 * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
32 * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
33 * @revision $Revision: 97 $
34 * @version 4.0.4
35 * @link http://adldap.sourceforge.net/
36 */
37require_once(dirname(__FILE__) . '/../adLDAP.php');
38
39/**
40* UTILITY FUNCTIONS
41*/
42class adLDAPUtils {
43    const ADLDAP_VERSION = '4.0.4';
44
45    /**
46    * The current adLDAP connection via dependency injection
47    *
48    * @var adLDAP
49    */
50    protected $adldap;
51
52    public function __construct(adLDAP $adldap) {
53        $this->adldap = $adldap;
54    }
55
56
57    /**
58    * Take an LDAP query and return the nice names, without all the LDAP prefixes (eg. CN, DN)
59    *
60    * @param array $groups
61    * @return array
62    */
63    public function niceNames($groups)
64    {
65
66        $groupArray = array();
67        for ($i=0; $i<$groups["count"]; $i++){ // For each group
68            $line = $groups[$i];
69
70            if (strlen($line)>0) {
71                // More presumptions, they're all prefixed with CN=
72                // so we ditch the first three characters and the group
73                // name goes up to the first comma
74                $bits=explode(",", $line);
75                $groupArray[] = substr($bits[0], 3, (strlen($bits[0])-3));
76            }
77        }
78        return $groupArray;
79    }
80
81    /**
82    * Escape characters for use in an ldap_create function
83    *
84    * @param string $str
85    * @return string
86    */
87    public function escapeCharacters($str) {
88        $str = str_replace(",", "\,", $str);
89        return $str;
90    }
91
92    /**
93    * Escape strings for the use in LDAP filters
94    *
95    * DEVELOPERS SHOULD BE DOING PROPER FILTERING IF THEY'RE ACCEPTING USER INPUT
96    * Ported from Perl's Net::LDAP::Util escape_filter_value
97    *
98    * @param string $str The string the parse
99    * @author Port by Andreas Gohr <andi@splitbrain.org>
100    * @return string
101    */
102    public function ldapSlashes($str) {
103        // see https://github.com/adldap/adLDAP/issues/22
104        return preg_replace_callback(
105            '/([\x00-\x1F\*\(\)\\\\])/',
106            function ($matches) {
107                return "\\".join("", unpack("H2", $matches[1]));
108            },
109            $str
110        );
111    }
112    /**
113    * Converts a string GUID to a hexdecimal value so it can be queried
114    *
115    * @param string $strGUID A string representation of a GUID
116    * @return string
117    */
118    public function strGuidToHex($strGUID)
119    {
120        $strGUID = str_replace('-', '', $strGUID);
121
122        $octet_str = '\\' . substr($strGUID, 6, 2);
123        $octet_str .= '\\' . substr($strGUID, 4, 2);
124        $octet_str .= '\\' . substr($strGUID, 2, 2);
125        $octet_str .= '\\' . substr($strGUID, 0, 2);
126        $octet_str .= '\\' . substr($strGUID, 10, 2);
127        $octet_str .= '\\' . substr($strGUID, 8, 2);
128        $octet_str .= '\\' . substr($strGUID, 14, 2);
129        $octet_str .= '\\' . substr($strGUID, 12, 2);
130        //$octet_str .= '\\' . substr($strGUID, 16, strlen($strGUID));
131        for ($i=16; $i<=(strlen($strGUID)-2); $i++) {
132            if (($i % 2) == 0) {
133                $octet_str .= '\\' . substr($strGUID, $i, 2);
134            }
135        }
136
137        return $octet_str;
138    }
139
140    /**
141    * Convert a binary SID to a text SID
142    *
143    * @param string $binsid A Binary SID
144    * @return string
145    */
146     public function getTextSID($binsid) {
147        $hex_sid = bin2hex($binsid);
148        $rev = hexdec(substr($hex_sid, 0, 2));
149        $subcount = hexdec(substr($hex_sid, 2, 2));
150        $auth = hexdec(substr($hex_sid, 4, 12));
151        $result = "$rev-$auth";
152
153        for ($x=0;$x < $subcount; $x++) {
154            $subauth[$x] =
155                hexdec($this->littleEndian(substr($hex_sid, 16 + ($x * 8), 8)));
156                $result .= "-" . $subauth[$x];
157        }
158
159        // Cheat by tacking on the S-
160        return 'S-' . $result;
161     }
162
163    /**
164    * Converts a little-endian hex number to one that hexdec() can convert
165    *
166    * @param string $hex A hex code
167    * @return string
168    */
169     public function littleEndian($hex)
170     {
171        $result = '';
172        for ($x = strlen($hex) - 2; $x >= 0; $x = $x - 2) {
173            $result .= substr($hex, $x, 2);
174        }
175        return $result;
176     }
177
178     /**
179    * Converts a binary attribute to a string
180    *
181    * @param string $bin A binary LDAP attribute
182    * @return string
183    */
184    public function binaryToText($bin)
185    {
186        $hex_guid = bin2hex($bin);
187        $hex_guid_to_guid_str = '';
188        for($k = 1; $k <= 4; ++$k) {
189            $hex_guid_to_guid_str .= substr($hex_guid, 8 - 2 * $k, 2);
190        }
191        $hex_guid_to_guid_str .= '-';
192        for($k = 1; $k <= 2; ++$k) {
193            $hex_guid_to_guid_str .= substr($hex_guid, 12 - 2 * $k, 2);
194        }
195        $hex_guid_to_guid_str .= '-';
196        for($k = 1; $k <= 2; ++$k) {
197            $hex_guid_to_guid_str .= substr($hex_guid, 16 - 2 * $k, 2);
198        }
199        $hex_guid_to_guid_str .= '-' . substr($hex_guid, 16, 4);
200        $hex_guid_to_guid_str .= '-' . substr($hex_guid, 20);
201        return strtoupper($hex_guid_to_guid_str);
202    }
203
204    /**
205    * Converts a binary GUID to a string GUID
206    *
207    * @param string $binaryGuid The binary GUID attribute to convert
208    * @return string
209    */
210    public function decodeGuid($binaryGuid)
211    {
212        if ($binaryGuid === null){ return "Missing compulsory field [binaryGuid]"; }
213
214        $strGUID = $this->binaryToText($binaryGuid);
215        return $strGUID;
216    }
217
218    /**
219    * Convert a boolean value to a string
220    * You should never need to call this yourself
221    *
222    * @param bool $bool Boolean value
223    * @return string
224    */
225    public function boolToStr($bool)
226    {
227        return ($bool) ? 'TRUE' : 'FALSE';
228    }
229
230    /**
231    * Convert 8bit characters e.g. accented characters to UTF8 encoded characters
232    */
233    public function encode8Bit(&$item, $key) {
234        $encode = false;
235        if (is_string($item)) {
236            for ($i=0; $i<strlen($item); $i++) {
237                if (ord($item[$i]) >> 7) {
238                    $encode = true;
239                }
240            }
241        }
242        if ($encode === true && $key != 'password') {
243            $item = utf8_encode($item);
244        }
245    }
246
247    /**
248    * Get the current class version number
249    *
250    * @return string
251    */
252    public function getVersion() {
253        return self::ADLDAP_VERSION;
254    }
255
256    /**
257    * Round a Windows timestamp down to seconds and remove the seconds between 1601-01-01 and 1970-01-01
258    *
259    * @param long $windowsTime
260    * @return long $unixTime
261    */
262    public static function convertWindowsTimeToUnixTime($windowsTime) {
263      $unixTime = round($windowsTime / 10000000) - 11644477200;
264      return $unixTime;
265    }
266}
267
268?>
269