/[drupal]/contributions/modules/ldap_addressbook/LDAPDirectory.inc
ViewVC logotype

Contents of /contributions/modules/ldap_addressbook/LDAPDirectory.inc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (show annotations) (download) (as text)
Tue Mar 28 20:15:19 2006 UTC (3 years, 8 months ago) by rabello
Branch: MAIN
CVS Tags: DRUPAL-4-7--1-0, HEAD
Branch point for: DRUPAL-5, DRUPAL-4-7
File MIME type: text/x-php
Import of revamped ldap_addressbook module, compatible with dp-47+
1 <?php //Dear emacs, please make this buffer -*- php -*-
2
3 // $Id$
4
5 /**
6 * @file
7 * An abstraction that represents a directory (actually the equivalent of a
8 * Distinguished Name, or DN) in a LDAP server.
9 *
10 * Copyright (C) 2006 Andre dos Anjos
11 *
12 * This file is part of the ldap_addresbook module for Drupal.
13 *
14 * The ldap_addressbook module is free software; you can redistribute it
15 * and/or modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of the License,
17 * or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful, but WITHOUT
20 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
22 * more details.
23 *
24 * You should have received a copy of the GNU General Public License along with
25 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
26 * Place, Suite 330, Boston, MA 02111-1307 USA
27 **/
28
29 require_once('Format.inc');
30
31 /**
32 * This abstraction represents an LDAP user.
33 */
34 class DirUser {
35 var $dn; //The DN of the user in the LDAP database
36 var $passwd; //The password for this user
37
38 /**
39 * Constructor
40 *
41 * @param $dn The DN of the user in an LDAP database
42 * @param $passwd That user's password
43 */
44 function DirUser($dn, $passwd) {
45 $this->dn = $dn;
46 $this->passwd = $passwd;
47 }
48
49 }
50
51 /**
52 * This abstraction represents a directory sitting in an LDAP server. It allows
53 * the user to search, add, modify and browse the LDAP server. It is
54 * drupal-aware and will output messages directly to drupal in case of
55 * problems.
56 */
57 class LDAPDirectory {
58 var $host; //The host where this directory is located at
59 var $port; //The port number on the host that the server is bound to
60 var $dir; //The DN name of directory in the LDAP server
61 var $proto; //The protocol version to use for communication
62
63 /**
64 * Constructor
65 *
66 * @param $host The host where this directory is located at
67 * @param $port The port number on the host that the server is bound to
68 * @param $dir The DN name of directory in the LDAP server
69 * @param $proto The protocol version to use
70 */
71 function LDAPDirectory($host, $port, $dir, $proto) {
72 $this->host = $host;
73 $this->port = (int)$port;
74 $this->dir = $dir;
75 $this->proto = (int)$proto;
76 if ($this->proto != 2 and $this->proto != 3) {
77 drupal_set_message
78 (t("Protocol version can only be 2 or 3. I cannot use '$proto'"),
79 'error');
80 }
81 }
82
83 /**
84 * Tests the connection to the LDAP server. Returns true if everything goes
85 * fine or false otherwise.
86 *
87 * @see ldap_connect()
88 */
89 function _test_connection() {
90 $connection = ldap_connect($this->host, $this->port);
91 if (!$connection) return FALSE;
92 ldap_close($connection);
93 return TRUE;
94 }
95
96 /**
97 * Connects and binds to the LDAP server, using the given user or anonymously
98 * if no user is given.
99 *
100 * @param $user The user with which to bind to the LDAP server, or FALSE, in
101 * which case I'll try to bind anonymously.
102 *
103 * @return The connection, if every thing goes fine otherwise FALSE
104 *
105 * @see ldap_connect()
106 * @see ldap_bind()
107 * @see DirUser
108 */
109 function _connect($user=FALSE) {
110 $connection = ldap_connect($this->host, $this->port);
111 if (!$connection) {
112 drupal_set_message
113 (t("Cannot connect to LDAP server at ldap://$this->host:$this->port"),
114 'error');
115 return FALSE;
116 }
117
118 if (!ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION,
119 $this->proto)) {
120 drupal_set_message(t("Cannot set the LDAP protocol to version $this->prot"), 'error');
121 $this->_disconnect($connection);
122 return FALSE;
123 }
124
125 if (!$user) { //go annonymously
126 $bind = ldap_bind($connection);
127 if (!$bind) {
128 drupal_set_message(t("Cannot bind to the LDAP server (ldap://$this->host:$this->port) anonymously"), 'error');
129 $this->_disconnect($connection);
130 return FALSE;
131 }
132 }
133 else { //bind with the user
134 $bind = ldap_bind($connection, $user->dn, $user->passwd);
135 if (!$bind) {
136 drupal_set_message(t("Cannot bind to the LDAP server (ldap://$this->host:$this->port) as user (DN) '$user->dn'"), 'error');
137 $this->_disconnect($connection);
138 return FALSE;
139 }
140 }
141
142 //if you get here, it is safe to return a connection
143 return $connection;
144 }
145
146 /**
147 * Disconnection is the easiest to implement:)
148 *
149 * @see ldap_unbind()
150 */
151 function _disconnect($connection) {
152 //ldap_unbind() is said to be more "correct" than ldap_close()
153 if ($connection) ldap_unbind($connection);
154 }
155
156 /**
157 * Add a new entry to this directory
158 *
159 * @param $dn The distinguished name of the entry to add
160 * @param $info The card information for the new entry, as expected by the
161 * PHP standard function ldap_add()
162 * @param $user The user with writing permissions to do this task. A value
163 * of FALSE will make me attempt to do it anonymously.
164 *
165 * @return <tt>TRUE</tt> if the operation is successful or <tt>FALSE</tt>
166 * otherwise.
167 *
168 * @see ldap_add()
169 * @see DirUser
170 */
171 function add($dn, $info, $user=FALSE) {
172 $connection = $this->_connect($user);
173 if (!$connection) return FALSE;
174 $result = ldap_add($connection, $dn, $info);
175 $this->_disconnect($connection);
176
177 if (!$result) {
178 //could not perform the addition
179 drupal_set_message
180 (t("I could not add the LDAP addressbook entry '$dn'."), 'error');
181 return FALSE;
182 }
183
184 return TRUE;
185 }
186
187 /**
188 * Add a new contact to this directory
189 *
190 * @param $info The card information for the new entry, as expected by the
191 * PHP standard function ldap_add(), excluding the 'cn' entry that will be
192 * used to create the distinguished name.
193 * @param $user The user with writing permissions to do this task. A value
194 * of FALSE will make me attempt to do it anonymously.
195 *
196 * @return <tt>TRUE</tt> if the operation is successful or <tt>FALSE</tt>
197 * otherwise.
198 *
199 * @see ldap_add()
200 * @see DirUser
201 */
202 function add_person($info, $user=FALSE) {
203
204 //check for the givenName and sn
205 if (!array_key_exists('givenname', $info)) {
206 drupal_set_message
207 (t("To add an entry, I need the attribute ")._lat('givenname'),
208 'error');
209 return FALSE;
210 }
211 if (!array_key_exists('sn', $info)) {
212 drupal_set_message
213 (t("To add an entry, I need the attribute ")._lat('sn'), 'error');
214 return FALSE;
215 }
216
217 //build the DN
218 $cn = $info['givenname'].' '.$info['sn'];
219 $info['cn'] = $cn;
220 $dn = "cn=$cn,$this->dir";
221 //makes sure we get the right ObjectClass
222 $info['ObjectClass'] = array('top', 'inetOrgPerson');
223 return $this->add($dn, $info, $user);
224 }
225
226 /**
227 * This will remove an entry from this directory.
228 *
229 * @param $user The user with writing permissions to do this task. A value
230 * of FALSE will make me attempt to do it anonymously.
231 * @param $cn The CN value of the entry you want to remove
232 *
233 * @return <tt>TRUE</tt> if the operation is successful or <tt>FALSE</tt>
234 * otherwise.
235 *
236 * @see ldap_delete()
237 * @see DirUser
238 */
239 function delete ($cn, $user=FALSE) {
240 //build the DN
241 $dn = "cn=$cn,$this->dir";
242 $connection = $this->_connect($user);
243 if (!$connection) return FALSE;
244 $result = ldap_delete($connection, $dn);
245 $this->_disconnect($connection);
246
247 if (!$result) {
248 //could not perform the deletion
249 drupal_set_message
250 (t("I could not delete the LDAP addressbook entry '$cn'."), 'error');
251 return FALSE;
252 }
253
254 return TRUE;
255 }
256
257 /**
258 * This will modify an entry in this directory.
259 *
260 * @param $info The card information for the new entry, as expected by the
261 * PHP standard function ldap_add(), excluding the 'cn' entry.
262 * @param $user The user with writing permissions to do this task. A value
263 * of FALSE will make me attempt to do it anonymously.
264 *
265 * @return <tt>TRUE</tt> if the operation is successful or <tt>FALSE</tt>
266 * otherwise.
267 *
268 * @see ldap_modify()
269 * @see DirUser
270 */
271 function modify ($info, $user=FALSE) {
272
273 //check for the givenName and sn
274 //trigger_error(implode(',',array_keys($info)));
275 if (!array_key_exists('givenname', $info)) {
276 drupal_set_message
277 (t("To modify an entry, I need the attribute ")._lat('givenname'),
278 'error');
279 return FALSE;
280 }
281 if (!array_key_exists('sn', $info)) {
282 drupal_set_message
283 (t("To modify an entry, I need the attribute ")._lat('sn'), 'error');
284 return FALSE;
285 }
286
287 $cn = $info['givenname'].' '.$info['sn'];
288
289 $connection = $this->_connect($user);
290 if (!$connection) return FALSE;
291
292 //check if we still have cn = givenName + sn
293 if ($info['cn'] != $cn) {
294 $oldcn = $info['cn'];
295 drupal_set_message(t("Replacing entry $oldcn by $cn"));
296 $info = $this->get_one($oldcn, $user);
297 foreach ($info as $key => $field) $info[$key] = $field;
298 $info['cn'] = $cn;
299 $retval = TRUE;
300 if (! $this->delete($oldcn, $user)) $retval = FALSE;
301 if (! $this->add_person($info, $user)) $retval = FALSE;
302 $this->_disconnect($connection);
303 return $retval;
304 }
305
306 //build the DN
307 $dn = "cn=$cn,$this->dir";
308 $result = ldap_modify($connection, $dn, $info);
309 $this->_disconnect($connection);
310
311 if (!$result) {
312 //could not perform the addition
313 drupal_set_message
314 (t("I could not modify the LDAP addressbook entry '$cn'."), 'error');
315 return FALSE;
316 }
317
318 drupal_set_message(t("Successfuly changed LDAP addressbook entry $cn"));
319 return TRUE;
320 }
321
322 /**
323 * Implements a modified (binary-safe) function to return the entries, so it
324 * correctly return things like jpeg photos and other binary entries.
325 *
326 * @param $connection The LDAP connection, properly bound
327 * @param $search_result The results after ldap_search() has been called.
328 *
329 * @return An array that contains the entries organized as in the
330 * result. Every entry is an array with the LDAP field properties. No
331 * "count" fields are available at this version of the result array
332 */
333 function _format_entries($connection, $search_result) {
334 $i=0;
335 $retval = array();
336 for ($entry=ldap_first_entry($connection, $search_result);
337 $entry != FALSE;
338 $entry=ldap_next_entry($connection, $entry)) {
339 $attributes = ldap_get_attributes($connection, $entry);
340 $j = 0;
341 for($j; $j<$attributes['count']; $j++) {
342 $values = ldap_get_values_len($connection, $entry, $attributes[$j]);
343 $retval[$i][strtolower($attributes[$j])] = $values;
344 }
345 $i++;
346 }
347 return $retval;
348 }
349
350 /**
351 * Do a search in the current directory for all entries.
352 *
353 * @param $filter The filter should conform to the string representation for
354 * search filters as defined in RFC 2254. If this variable is not provided,
355 * the default filter (objectClass=*) is used instead.
356 * @param $user The user with reading permissions to do this task. A value
357 * of FALSE will make me attempt to do it anonymously.
358 * @param $sort The sorting criteria to apply, in reverse order, as an
359 * array. The keys here are checked against $fields bellow, if that is set,
360 * so don't worry too much.
361 * @param $fields An array containing the LDAP fields you want to
362 * retrieve. The default is to retrive all the available fields for every
363 * entry.
364 * @param $sub If the scope of the search should be sub(tree). Otherwise, if
365 * unset or FALSE, the search will be realized only in the current
366 * directory. Not on subdirectories.
367 *
368 * @return An array where every entry is the CN value of the LDAP entry and
369 * the contents of every entry is an array with the entries fields. An empty
370 * array means the search has not found any matches. A value of FALSE as
371 * return value indicates there were problems.
372 */
373 function search_any($filter='', $user=FALSE, $sort=array('cn'),
374 $fields=NULL, $sub=FALSE) {
375 if (empty($filter)) $filter='(objectClass=*)';
376
377 $connection = $this->_connect($user);
378 if (!$connection) return FALSE;
379
380 //set the scope
381 $result = FALSE;
382 if ($sub)
383 $result = ldap_search($connection, $this->dir, $filter, $fields);
384 else
385 $result = ldap_list($connection, $this->dir, $filter, $fields);
386
387 if (!$result) {
388 drupal_set_message(t('Cannot search the LDAP directory '.$this->dir),
389 'error');
390 $this->_disconnect($connection);
391 return FALSE;
392 }
393
394 //the sorting in reverse order
395 foreach ($sort as $s) {
396 if (is_null($fields)) ldap_sort($connection, $result, $s);
397 else if (in_array($s, $fields)) ldap_sort($connection, $result, $s);
398 }
399
400 //get into a PHPified version of the answer
401 $info = $this->_format_entries($connection, $result);
402
403 $this->_disconnect($connection);
404 return $info;
405 }
406
407 /**
408 * Do a search in the current directory for all entries of the Person
409 * type. The search is always only for the current directory, not includding
410 * subdirectories.
411 *
412 * @param $filter The filter should conform to the string representation for
413 * search filters as defined in RFC 2254. If not provided, the default
414 * filter, (objectClass=Person), is used. If provided, it is added as an
415 * logical AND clause to (objectClass=Person).
416 * @param $user The user with reading permissions to do this task. A value
417 * of FALSE will make me attempt to do it anonymously.
418 * @param $sort The sorting criteria to apply, in reverse order, as an
419 * array. The keys here are checked against $fields bellow, if that is set,
420 * so don't worry too much.
421 * @param $fields An array containing the LDAP fields you want to
422 * retrieve. The default is to retrive all the available fields for every
423 * entry.
424 *
425 * @return An array where every entry is the CN value of the LDAP entry and
426 * the contents of every entry is an array with the entries fields. An empty
427 * array means the search has not found any matches. A value of FALSE as
428 * return value indicates there were problems.
429 */
430 function search_person($filter='', $user=FALSE, $sort=array('cn'),
431 $fields=NULL) {
432 if (empty($filter)) $filter='(objectClass=Person)';
433 else $filter="(&(objectClass=Person)$filter)";
434 return $this->search_any($filter, $user, $sort, $fields, FALSE);
435 }
436
437 /**
438 * Returns an array with the entry's properties or FALSE in the case there
439 * are no entries with the assigned CN.
440 *
441 * @param $cn The CN entry of the contact you are searching for.
442 * @param $user The user with reading permissions to do this task. A value
443 * of FALSE will make me attempt to do it anonymously.
444 * @param $fields An array containing the LDAP fields you want to
445 * retrieve. The default is to retrive all the available fields for every
446 * entry.
447 *
448 * @return An array where every entry is the CN value of the LDAP entry and
449 * the contents of every entry is an array with the entries fields. An empty
450 * array means the search has not found any matches. A value of FALSE as
451 * return value indicates there were problems.
452 */
453 function get_one($cn, $user=FALSE, $fields=NULL) {
454 $result = $this->search_person("(cn=$cn)", $user, array(), $fields);
455 if (count($result) != 1) return FALSE;
456 return $result[0];
457 }
458
459 /**
460 * This function will check if a directory exists and either return TRUE
461 * or FALSE
462 *
463 * @param $rdn The reduced distinguished name of subdirectory to find
464 */
465 function is_dir($dn, $user=FALSE) {
466 $connection = $this->_connect($user);
467 $base = explode(',',$dn);
468 $search_dir = explode('=', $base[0]);
469 unset($base[0]);
470 $base = implode(',',$base);
471 if (!$connection) return FALSE;
472 $result = ldap_list($connection, $base, '(objectClass=organizationalUnit)');
473 if (!$result) {
474 drupal_set_message(t("I could not check directory in LDAP server"),
475 'eror');
476 $this->_disconnect($connection);
477 return FALSE;
478 }
479 $info = $this->_format_entries($connection, $result);
480 foreach ($info as $i) {
481 if ($i[trim($search_dir[0])][0] == trim($search_dir[1])) return TRUE;
482 }
483 return FALSE;
484 }
485
486 }
487
488 /**
489 * This class extends the LDAPDirectory class above by fusioning it with the
490 * Drupal preference system. The outcome is that when you create an instance
491 * of this class, all configuration options do not need to be specified.
492 */
493 class DrupalDirectory extends LDAPDirectory {
494
495 /**
496 * The constructor, gets the variables from Drupal and builds the underlying
497 * LDAPDirectory.
498 */
499 function DrupalDirectory ($dir='') {
500 if (empty($dir))
501 $dir = variable_get('ldap_addressbook_base',
502 'ou=addressbook,dc=example,dc=com');
503 parent::LDAPDirectory(variable_get('ldap_addressbook_host', 'localhost'),
504 variable_get('ldap_addressbook_port', '389'),
505 $dir, variable_get('ldap_addressbook_version', '3'));
506 }
507
508 /**
509 * Returns the user
510 */
511 function user() {
512 $user = new DirUser(variable_get('ldap_addressbook_user',
513 'cn=Manager,dc=example,dc=com'),
514 variable_get('ldap_addressbook_user_pass', ''));
515 return $user;
516 }
517
518 /**
519 * Returns if we should be doing anonymous reading or not
520 */
521 function read_anonymously() {
522 return (bool)variable_get('ldap_addressbook_anonymous', '1');
523 }
524
525 /**
526 * Returns the reader user or FALSE in case I have to read anonymously
527 */
528 function _reader() {
529 if ($this->read_anonymously()) return FALSE;
530 return $this->user();
531 }
532
533 /**
534 * Returns the fields of interest in your addresbook
535 */
536 function fields() {
537 $default_fields = array('jpegphoto', 'givenname', 'cn', 'sn',
538 'mail', 'homepostaladdress', 'postaladdress',
539 'postalcode', 'telephonenumber', 'homephone',
540 'mobile', 'o', 'labeleduri', 'title');
541 $retval = strtolower(variable_get('ldap_addressbook_fields',
542 implode(' ', $default_fields)));
543 return explode(' ', $retval);
544 }
545
546 /**
547 * Returns the main person filter
548 */
549 function person_filter() {
550 return variable_get('ldap_addressbook_person_filter',
551 '(objectClass=Person)');
552 }
553
554 /**
555 * Returns the user addressbook template
556 */
557 function userbook_template() {
558 return variable_get('ldap_addressbook_private_template',
559 'ou=%s,ou=addressbook,dc=example,dc=com');
560 }
561
562 /**
563 * The password hashing strategy.
564 */
565 function password_hash() {
566 return variable_get('ldap_addressbook_password_hash',
567 'clear');
568 }
569
570 /**
571 * Returns the subdirectory filter
572 */
573 function subdir_filter() {
574 return variable_get('ldap_addressbook_subdir_filter',
575 '(objectClass=organizationalUnit)');
576 }
577
578 /**
579 * Returns the fields of interest in your addresbook when you want to
580 * compute summary entries (more compact addressbook cards).
581 */
582 function summary_fields() {
583 $default_summary = array('jpegphoto', 'cn', 'mail', 'telephonenumber',
584 'mobile', 'labeleduri');
585 $retval = strtolower(variable_get('ldap_addressbook_summary',
586 implode(' ', $default_summary)));
587 return explode(' ', $retval);
588 }
589
590 /**
591 * Returns the maximum jpeg size you can have in the addressbook.
592 */
593 function maximum_jpeg_size() {
594 return (int)variable_get('ldap_addressbook_jpeg_size', 200);
595 }
596
597 /**
598 * Returns the path that I should use for storing temporary files
599 */
600 function tmp_path() {
601 return variable_get('ldap_addressbook_tmp',
602 file_directory_path().'/tmp');
603 }
604
605 /**
606 * Returns this module name
607 */
608 function module_name() { return 'ldap_addressbook'; }
609
610 /**
611 * @see LDAPDirectory::add()
612 */
613 function add($info, $privacy) {
614 if ($privacy != 'global' && $privacy != 'private') {
615 drupal_set_message(t('Privacy attribute, for addition, can only assume values "global" or "private"'), 'error');
616 return FALSE;
617 }
618 else if ($privacy == 'global') return parent::add_person($info, $this->user());
619 else {
620 $user_dn = $this->private_book();
621 if (!$user_dn) {
622 drupal_set_message(t('Cannot access private addressbook for addition'), 'error');
623 return FALSE;
624 }
625 $user_dir = new LDAPDirectory
626 (variable_get('ldap_addressbook_host', 'localhost'),
627 variable_get('ldap_addressbook_port', '389'), $user_dn,
628 variable_get('ldap_addressbook_version', '3'));
629 return $user_dir->add_person($info, $this->user());
630 }
631 }
632
633 /**
634 * @see LDAPDirectory::delete()
635 */
636 function delete($cn, $privacy) {
637 if ($privacy != 'global' && $privacy != 'private') {
638 drupal_set_message(t('Privacy attribute, for deletion, can only assume values "global" or "private"'), 'error');
639 return FALSE;
640 }
641 else if ($privacy == 'global') return parent::delete($cn, $this->user());
642 else {
643 $user_dn = $this->private_book();
644 if (!$user_dn) return FALSE;
645 $user_dir = new LDAPDirectory
646 (variable_get('ldap_addressbook_host', 'localhost'),
647 variable_get('ldap_addressbook_port', '389'), $user_dn,
648 variable_get('ldap_addressbook_version', '3'));
649 return $user_dir->delete($cn, $this->user());
650 }
651 }
652
653 /**
654 * @see LDAPDirectory::modify()
655 */
656 function modify ($info) {
657 return parent::modify($info, $this->user());
658 }
659
660 /**
661 * @see LDAPDirectory::search() <- problem with recursion
662 *
663 * @param $privacy Defines the scope of the search. A value of "global" will
664 * only search the global addressbook. A value of "private" will only search
665 * the user's addressbook if there is any. A value of "all" will search both
666 * addressbooks.
667 */
668 function search($filter='', $sort=array('cn'),
669 $fields=NULL, $privacy="all") {
670 $info = array('global' => array(),
671 'private' => array());
672
673 if ($privacy == 'global' || $privacy == 'all')
674 $info['global'] =
675 parent::search_person($filter, $this->_reader(), $sort, $fields);
676
677 if ($privacy == 'private' || $privacy == 'all') {
678 $user_dn = $this->private_book();
679 if ($user_dn) {
680 $user_dir = new LDAPDirectory
681 (variable_get('ldap_addressbook_host', 'localhost'),
682 variable_get('ldap_addressbook_port', '389'), $user_dn,
683 variable_get('ldap_addressbook_version', '3'));
684 $info['private'] =
685 $user_dir->search_person($filter, $this->_reader(),
686 $sort, $fields);
687 }
688 else {
689 if ($privacy == 'private') {
690 //if the user is search explicetly for a private addressbook...
691 drupal_set_message(t('You do <b>not</b> seem to have a private addressbook I can search at. Ask the LDAP addressbook administrator to create one for you.'), 'error');
692 return FALSE;
693 }
694 }
695 }
696 return $info;
697 }
698
699 /**
700 * Checks if the current user can use/have a private addressbook available.
701 */
702 function private_book() {
703 if (!user_access('Have private LDAP addressbook')) return FALSE;
704 global $user; //get the current user's name
705 $user_dn = sprintf($this->userbook_template(), $user->name);
706 $check = parent::is_dir($user_dn, $this->_reader());
707 if ($check) return $user_dn;
708 return FALSE;
709 }
710
711 /**
712 * @see LDAPDirectory::get_one()
713 */
714 function get_one($privacy, $cn) {
715 if ($privacy == 'global')
716 return parent::get_one($cn, $this->_reader(), $this->fields());
717 else if ($privacy == 'private') {
718 if (user_access('Have private LDAP addressbook')) {
719 global $user; //get the current user's name
720 $user_dn = sprintf($this->userbook_template(), $user->name);
721 if (parent::is_dir($user_dn, $this->_reader())) {
722 $user_dir = new LDAPDirectory
723 (variable_get('ldap_addressbook_host', 'localhost'),
724 variable_get('ldap_addressbook_port', '389'), $user_dn,
725 variable_get('ldap_addressbook_version', '3'));
726 return $user_dir->get_one($cn, $this->_reader(), $this->fields());
727 }
728 }
729 else {
730 drupal_access_denied(); //?
731 return FALSE;
732 }
733 }
734 else {
735 drupal_set_message(t("Cannot accept privacy '$privacy' to get a single entry in the LDAP addressbook. Check the cause of error or submit a bug report!"), 'error');
736 }
737 drupal_access_denied(); //?
738 }
739
740 }
741
742 /**
743 * A hashing system for preparing hashed password to be used with LDAP. This
744 * function source code was copied from the phpLDAPAdmin project.
745 *
746 * @param $secret The value to hash, not previously encripted
747 * @param $algo The algorithm to use. Must be one of crypt, ext_des, md5crypt,
748 * blowfish, md5, sha, smd5, ssha, or clear.
749 *
750 * @return The hashed valued, ready to be used with LDAP, if the algorithm is
751 * supported, or FALSE otherwise.
752 */
753
754 function _lab_hash( $secret, $algo ) {
755 $algo = strtolower( $algo );
756
757 $hash = '';
758 switch ( $algo ) {
759
760 case 'crypt':
761 $hash = '{CRYPT}' . crypt( $secret, random_salt(2) );
762 break;
763
764 case 'ext_des':
765 // extended des crypt. see OpenBSD crypt man page.
766 if ( ! defined( 'CRYPT_EXT_DES' ) || CRYPT_EXT_DES == 0 ) {
767 drupal_set_message(t("Your PHP installation does not contain support for the hashing algorithm '$algo'"), 'error');
768 return FALSE;
769 }
770 $hash = '{CRYPT}' . crypt( $secret, '_' . random_salt(8) );
771 break;
772
773 case 'md5crypt':
774 if( ! defined( 'CRYPT_MD5' ) || CRYPT_MD5 == 0 ) {
775 drupal_set_message(t("Your PHP installation does not contain support for the hashing algorithm '$algo'"), 'error');
776 return FALSE;
777 }
778 $hash = '{CRYPT}' . crypt( $secret , '$1$' . random_salt(9) );
779 break;
780
781 case 'blowfish':
782 if( ! defined( 'CRYPT_BLOWFISH' ) || CRYPT_BLOWFISH == 0 ) {
783 drupal_set_message(t("Your PHP installation does not contain support for the hashing algorithm '$algo'"), 'error');
784 return FALSE;
785 }
786 // hardcoded to second blowfish version and set number of rounds
787 $hash = '{CRYPT}' . crypt( $secret , '$2a$12$' . random_salt(13) );
788 break;
789
790 case 'md5':
791 $hash = '{MD5}' . base64_encode( pack( 'H*' , md5($secret) ) );
792 break;
793
794 case 'sha':
795 if( function_exists('sha1') ) {
796 // use php 4.3.0+ sha1 function, if it is available.
797 $hash = '{SHA}' . base64_encode( pack( 'H*' , sha1($secret) ) );
798
799 } else if ( function_exists( 'mhash' ) ) {
800 $hash = '{SHA}' . base64_encode( mhash( MHASH_SHA1, $secret) );
801
802 } else {
803 drupal_set_message(t("Your PHP installation does not contain support for the hashing algorithm '$algo'"), 'error');
804 return FALSE;
805 }
806 break;
807
808 case 'ssha':
809 if(function_exists( 'mhash' ) && function_exists('mhash_keygen_s2k')) {
810 mt_srand( (double) microtime() * 1000000 );
811 $salt = mhash_keygen_s2k(MHASH_SHA1, $secret,
812 substr(pack("h*", md5(mt_rand())), 0, 8), 4);
813 $hash = "{SSHA}".base64_encode(mhash(MHASH_SHA1, $secret.$salt).$salt);
814
815 } else {
816 drupal_set_message(t("Your PHP installation does not contain support for the hashing algorithm '$algo'"), 'error');
817 return FALSE;
818 }
819 break;
820
821 case 'smd5':
822 if(function_exists( 'mhash' ) && function_exists('mhash_keygen_s2k')) {
823 mt_srand( (double) microtime() * 1000000 );
824 $salt = mhash_keygen_s2k(MHASH_MD5, $secret,
825 substr(pack("h*", md5(mt_rand())), 0, 8), 4);
826 $hash = "{SMD5}".base64_encode(mhash(MHASH_MD5, $secret.$salt).$salt);
827
828 } else {
829 drupal_set_message(t("Your PHP installation does not contain support for the hashing algorithm '$algo'"), 'error');
830 return FALSE;
831 }
832 break;
833
834 case 'clear':
835 default:
836 $hash = $secret;
837 }
838
839 return $hash;
840 }
841
842 ?>

  ViewVC Help
Powered by ViewVC 1.1.2