comparison program/lib/Roundcube/rcube_ldap_generic.php @ 0:4681f974d28b

vanilla 1.3.3 distro, I hope
author Charlie Root
date Thu, 04 Jan 2018 15:52:31 -0500
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4681f974d28b
1 <?php
2
3 /**
4 +-----------------------------------------------------------------------+
5 | Roundcube/rcube_ldap_generic.php |
6 | |
7 | This file is part of the Roundcube Webmail client |
8 | Copyright (C) 2006-2014, The Roundcube Dev Team |
9 | Copyright (C) 2012-2015, Kolab Systems AG |
10 | |
11 | Licensed under the GNU General Public License version 3 or |
12 | any later version with exceptions for skins & plugins. |
13 | See the README file for a full license statement. |
14 | |
15 | PURPOSE: |
16 | Provide basic functionality for accessing LDAP directories |
17 | |
18 +-----------------------------------------------------------------------+
19 | Author: Thomas Bruederli <roundcube@gmail.com> |
20 | Aleksander Machniak <machniak@kolabsys.com> |
21 +-----------------------------------------------------------------------+
22 */
23
24 /**
25 * Model class to access an LDAP directories
26 *
27 * @package Framework
28 * @subpackage LDAP
29 */
30 class rcube_ldap_generic extends Net_LDAP3
31 {
32 /** private properties */
33 protected $cache = null;
34 protected $attributes = array('dn');
35 protected $error;
36
37 function __construct($config = null)
38 {
39 parent::__construct($config);
40
41 $this->config_set('log_hook', array($this, 'log'));
42 }
43
44 /**
45 * Establish a connection to the LDAP server
46 */
47 public function connect($host = null)
48 {
49 // Net_LDAP3 does not support IDNA yet
50 // also parse_host() here is very Roundcube specific
51 $host = rcube_utils::parse_host($host, $this->config['mail_domain']);
52 $host = rcube_utils::idn_to_ascii($host);
53
54 return parent::connect($host);
55 }
56
57 /**
58 * Get a specific LDAP entry, identified by its DN
59 *
60 * @param string $dn Record identifier
61 * @param array $attributes Attributes to return
62 *
63 * @return array Hash array
64 */
65 function get_entry($dn, $attributes = array())
66 {
67 return parent::get_entry($dn, !empty($attributes) ? $attributes : $this->attributes);
68 }
69
70 /**
71 * Prints debug/error info to the log
72 */
73 public function log($level, $msg)
74 {
75 $msg = implode("\n", $msg);
76
77 switch ($level) {
78 case LOG_DEBUG:
79 case LOG_INFO:
80 case LOG_NOTICE:
81 if ($this->config['debug']) {
82 rcube::write_log('ldap', $msg);
83 }
84 break;
85
86 case LOG_EMERGE:
87 case LOG_ALERT:
88 case LOG_CRIT:
89 rcube::raise_error($msg, true, true);
90 break;
91
92 case LOG_ERR:
93 case LOG_WARNING:
94 $this->error = $msg;
95 rcube::raise_error($msg, true, false);
96 break;
97 }
98 }
99
100 /**
101 * Returns the last LDAP error occurred
102 *
103 * @return mixed Error message string or null if no error occurred
104 */
105 function get_error()
106 {
107 return $this->error;
108 }
109
110 /**
111 * @deprecated
112 */
113 public function set_debug($dbg = true)
114 {
115 $this->config['debug'] = (bool) $dbg;
116 }
117
118 /**
119 * @deprecated
120 */
121 public function set_cache($cache_engine)
122 {
123 $this->config['cache'] = $cache_engine;
124 }
125
126 /**
127 * @deprecated
128 */
129 public static function scope2func($scope, &$ns_function = null)
130 {
131 return self::scope_to_function($scope, $ns_function);
132 }
133
134 /**
135 * @deprecated
136 */
137 public function set_config($opt, $val = null)
138 {
139 $this->config_set($opt, $val);
140 }
141
142 /**
143 * @deprecated
144 */
145 public function add($dn, $entry)
146 {
147 return $this->add_entry($dn, $entry);
148 }
149
150 /**
151 * @deprecated
152 */
153 public function delete($dn)
154 {
155 return $this->delete_entry($dn);
156 }
157
158 /**
159 * Wrapper for ldap_mod_replace()
160 *
161 * @see ldap_mod_replace()
162 */
163 public function mod_replace($dn, $entry)
164 {
165 $this->_debug("C: Replace $dn: ".print_r($entry, true));
166
167 if (!ldap_mod_replace($this->conn, $dn, $entry)) {
168 $this->_error("ldap_mod_replace() failed with " . ldap_error($this->conn));
169 return false;
170 }
171
172 $this->_debug("S: OK");
173 return true;
174 }
175
176 /**
177 * Wrapper for ldap_mod_add()
178 *
179 * @see ldap_mod_add()
180 */
181 public function mod_add($dn, $entry)
182 {
183 $this->_debug("C: Add $dn: ".print_r($entry, true));
184
185 if (!ldap_mod_add($this->conn, $dn, $entry)) {
186 $this->_error("ldap_mod_add() failed with " . ldap_error($this->conn));
187 return false;
188 }
189
190 $this->_debug("S: OK");
191 return true;
192 }
193
194 /**
195 * Wrapper for ldap_mod_del()
196 *
197 * @see ldap_mod_del()
198 */
199 public function mod_del($dn, $entry)
200 {
201 $this->_debug("C: Delete $dn: ".print_r($entry, true));
202
203 if (!ldap_mod_del($this->conn, $dn, $entry)) {
204 $this->_error("ldap_mod_del() failed with " . ldap_error($this->conn));
205 return false;
206 }
207
208 $this->_debug("S: OK");
209 return true;
210 }
211
212 /**
213 * Wrapper for ldap_rename()
214 *
215 * @see ldap_rename()
216 */
217 public function rename($dn, $newrdn, $newparent = null, $deleteoldrdn = true)
218 {
219 $this->_debug("C: Rename $dn to $newrdn");
220
221 if (!ldap_rename($this->conn, $dn, $newrdn, $newparent, $deleteoldrdn)) {
222 $this->_error("ldap_rename() failed with " . ldap_error($this->conn));
223 return false;
224 }
225
226 $this->_debug("S: OK");
227 return true;
228 }
229
230 /**
231 * Wrapper for ldap_list() + ldap_get_entries()
232 *
233 * @see ldap_list()
234 * @see ldap_get_entries()
235 */
236 public function list_entries($dn, $filter, $attributes = array('dn'))
237 {
238 $list = array();
239 $this->_debug("C: List $dn [{$filter}]");
240
241 if ($result = ldap_list($this->conn, $dn, $filter, $attributes)) {
242 $list = ldap_get_entries($this->conn, $result);
243
244 if ($list === false) {
245 $this->_error("ldap_get_entries() failed with " . ldap_error($this->conn));
246 return array();
247 }
248
249 $count = $list['count'];
250 unset($list['count']);
251
252 $this->_debug("S: $count record(s)");
253 }
254 else {
255 $this->_error("ldap_list() failed with " . ldap_error($this->conn));
256 }
257
258 return $list;
259 }
260
261 /**
262 * Wrapper for ldap_read() + ldap_get_entries()
263 *
264 * @see ldap_read()
265 * @see ldap_get_entries()
266 */
267 public function read_entries($dn, $filter, $attributes = null)
268 {
269 $this->_debug("C: Read $dn [{$filter}]");
270
271 if ($this->conn && $dn) {
272 $result = @ldap_read($this->conn, $dn, $filter, $attributes, 0, (int)$this->config['sizelimit'], (int)$this->config['timelimit']);
273 if ($result === false) {
274 $this->_error("ldap_read() failed with " . ldap_error($this->conn));
275 return false;
276 }
277
278 $this->_debug("S: OK");
279 return ldap_get_entries($this->conn, $result);
280 }
281
282 return false;
283 }
284
285 /**
286 * Turn an LDAP entry into a regular PHP array with attributes as keys.
287 *
288 * @param array $entry Attributes array as retrieved from ldap_get_attributes() or ldap_get_entries()
289 * @param bool $flat Convert one-element-array values into strings (not implemented)
290 *
291 * @return array Hash array with attributes as keys
292 */
293 public static function normalize_entry($entry, $flat = false)
294 {
295 if (!isset($entry['count'])) {
296 return $entry;
297 }
298
299 $rec = array();
300
301 for ($i=0; $i < $entry['count']; $i++) {
302 $attr = $entry[$i];
303 if ($entry[$attr]['count'] == 1) {
304 switch ($attr) {
305 case 'objectclass':
306 $rec[$attr] = array(strtolower($entry[$attr][0]));
307 break;
308 default:
309 $rec[$attr] = $entry[$attr][0];
310 break;
311 }
312 }
313 else {
314 for ($j=0; $j < $entry[$attr]['count']; $j++) {
315 $rec[$attr][$j] = $entry[$attr][$j];
316 }
317 }
318 }
319
320 return $rec;
321 }
322
323 /**
324 * Compose an LDAP filter string matching all words from the search string
325 * in the given list of attributes.
326 *
327 * @param string $value Search value
328 * @param mixed $attrs List of LDAP attributes to search
329 * @param int $mode Matching mode:
330 * 0 - partial (*abc*),
331 * 1 - strict (=),
332 * 2 - prefix (abc*)
333 * @return string LDAP filter
334 */
335 public static function fulltext_search_filter($value, $attributes, $mode = 1)
336 {
337 if (empty($attributes)) {
338 $attributes = array('cn');
339 }
340
341 $groups = array();
342 $value = str_replace('*', '', $value);
343 $words = $mode == 0 ? rcube_utils::tokenize_string($value, 1) : array($value);
344
345 // set wildcards
346 $wp = $ws = '';
347 if ($mode != 1) {
348 $ws = '*';
349 $wp = !$mode ? '*' : '';
350 }
351
352 // search each word in all listed attributes
353 foreach ($words as $word) {
354 $parts = array();
355 foreach ($attributes as $attr) {
356 $parts[] = "($attr=$wp" . self::quote_string($word) . "$ws)";
357 }
358 $groups[] = '(|' . join('', $parts) . ')';
359 }
360
361 return count($groups) > 1 ? '(&' . join('', $groups) . ')' : join('', $groups);
362 }
363 }
364
365 // for backward compat.
366 class rcube_ldap_result extends Net_LDAP3_Result {}