"Fossies" - the Fresh Open Source Software Archive 
Member "adLDAP-4.0.4/src/adLDAP.php" (13 Apr 2013, 31241 Bytes) of package /linux/www/old/adLDAP-4.0.4.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "adLDAP.php" see the
Fossies "Dox" file reference documentation.
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 * @author Scott Barnett, Richard Hyland
30 * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
31 * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
32 * @revision $Revision: 169 $
33 * @version 4.0.4
34 * @link http://adldap.sourceforge.net/
35 */
36
37 /**
38 * Main adLDAP class
39 *
40 * Can be initialised using $adldap = new adLDAP();
41 *
42 * Something to keep in mind is that Active Directory is a permissions
43 * based directory. If you bind as a domain user, you can't fetch as
44 * much information on other users as you could as a domain admin.
45 *
46 * Before asking questions, please read the Documentation at
47 * http://adldap.sourceforge.net/wiki/doku.php?id=api
48 */
49 require_once(dirname(__FILE__) . '/collections/adLDAPCollection.php');
50 require_once(dirname(__FILE__) . '/classes/adLDAPGroups.php');
51 require_once(dirname(__FILE__) . '/classes/adLDAPUsers.php');
52 require_once(dirname(__FILE__) . '/classes/adLDAPFolders.php');
53 require_once(dirname(__FILE__) . '/classes/adLDAPUtils.php');
54 require_once(dirname(__FILE__) . '/classes/adLDAPContacts.php');
55 require_once(dirname(__FILE__) . '/classes/adLDAPExchange.php');
56 require_once(dirname(__FILE__) . '/classes/adLDAPComputers.php');
57
58 class adLDAP {
59
60 /**
61 * Define the different types of account in AD
62 */
63 const ADLDAP_NORMAL_ACCOUNT = 805306368;
64 const ADLDAP_WORKSTATION_TRUST = 805306369;
65 const ADLDAP_INTERDOMAIN_TRUST = 805306370;
66 const ADLDAP_SECURITY_GLOBAL_GROUP = 268435456;
67 const ADLDAP_DISTRIBUTION_GROUP = 268435457;
68 const ADLDAP_SECURITY_LOCAL_GROUP = 536870912;
69 const ADLDAP_DISTRIBUTION_LOCAL_GROUP = 536870913;
70 const ADLDAP_FOLDER = 'OU';
71 const ADLDAP_CONTAINER = 'CN';
72
73 /**
74 * The default port for LDAP non-SSL connections
75 */
76 const ADLDAP_LDAP_PORT = '389';
77 /**
78 * The default port for LDAPS SSL connections
79 */
80 const ADLDAP_LDAPS_PORT = '636';
81
82 /**
83 * The account suffix for your domain, can be set when the class is invoked
84 *
85 * @var string
86 */
87 protected $accountSuffix = "@mydomain.local";
88
89 /**
90 * The base dn for your domain
91 *
92 * If this is set to null then adLDAP will attempt to obtain this automatically from the rootDSE
93 *
94 * @var string
95 */
96 protected $baseDn = "DC=mydomain,DC=local";
97
98 /**
99 * Port used to talk to the domain controllers.
100 *
101 * @var int
102 */
103 protected $adPort = self::ADLDAP_LDAP_PORT;
104
105 /**
106 * Array of domain controllers. Specifiy multiple controllers if you
107 * would like the class to balance the LDAP queries amongst multiple servers
108 *
109 * @var array
110 */
111 protected $domainControllers = array("dc01.mydomain.local");
112
113 /**
114 * Optional account with higher privileges for searching
115 * This should be set to a domain admin account
116 *
117 * @var string
118 * @var string
119 */
120 protected $adminUsername = NULL;
121 protected $adminPassword = NULL;
122
123 /**
124 * AD does not return the primary group. http://support.microsoft.com/?kbid=321360
125 * This tweak will resolve the real primary group.
126 * Setting to false will fudge "Domain Users" and is much faster. Keep in mind though that if
127 * someone's primary group is NOT domain users, this is obviously going to mess up the results
128 *
129 * @var bool
130 */
131 protected $realPrimaryGroup = true;
132
133 /**
134 * Use SSL (LDAPS), your server needs to be setup, please see
135 * http://adldap.sourceforge.net/wiki/doku.php?id=ldap_over_ssl
136 *
137 * @var bool
138 */
139 protected $useSSL = false;
140
141 /**
142 * Use TLS
143 * If you wish to use TLS you should ensure that $useSSL is set to false and vice-versa
144 *
145 * @var bool
146 */
147 protected $useTLS = false;
148
149 /**
150 * Use SSO
151 * To indicate to adLDAP to reuse password set by the brower through NTLM or Kerberos
152 *
153 * @var bool
154 */
155 protected $useSSO = false;
156
157 /**
158 * When querying group memberships, do it recursively
159 * eg. User Fred is a member of Group A, which is a member of Group B, which is a member of Group C
160 * user_ingroup("Fred","C") will returns true with this option turned on, false if turned off
161 *
162 * @var bool
163 */
164 protected $recursiveGroups = true;
165
166 // You should not need to edit anything below this line
167 //******************************************************************************************
168
169 /**
170 * Connection and bind default variables
171 *
172 * @var mixed
173 * @var mixed
174 */
175 protected $ldapConnection;
176 protected $ldapBind;
177
178 /**
179 * Get the active LDAP Connection
180 *
181 * @return resource
182 */
183 public function getLdapConnection() {
184 if ($this->ldapConnection) {
185 return $this->ldapConnection;
186 }
187 return false;
188 }
189
190 /**
191 * Get the bind status
192 *
193 * @return bool
194 */
195 public function getLdapBind() {
196 return $this->ldapBind;
197 }
198
199 /**
200 * Get the current base DN
201 *
202 * @return string
203 */
204 public function getBaseDn() {
205 return $this->baseDn;
206 }
207
208 /**
209 * The group class
210 *
211 * @var adLDAPGroups
212 */
213 protected $groupClass;
214
215 /**
216 * Get the group class interface
217 *
218 * @return adLDAPGroups
219 */
220 public function group() {
221 if (!$this->groupClass) {
222 $this->groupClass = new adLDAPGroups($this);
223 }
224 return $this->groupClass;
225 }
226
227 /**
228 * The user class
229 *
230 * @var adLDAPUsers
231 */
232 protected $userClass;
233
234 /**
235 * Get the userclass interface
236 *
237 * @return adLDAPUsers
238 */
239 public function user() {
240 if (!$this->userClass) {
241 $this->userClass = new adLDAPUsers($this);
242 }
243 return $this->userClass;
244 }
245
246 /**
247 * The folders class
248 *
249 * @var adLDAPFolders
250 */
251 protected $folderClass;
252
253 /**
254 * Get the folder class interface
255 *
256 * @return adLDAPFolders
257 */
258 public function folder() {
259 if (!$this->folderClass) {
260 $this->folderClass = new adLDAPFolders($this);
261 }
262 return $this->folderClass;
263 }
264
265 /**
266 * The utils class
267 *
268 * @var adLDAPUtils
269 */
270 protected $utilClass;
271
272 /**
273 * Get the utils class interface
274 *
275 * @return adLDAPUtils
276 */
277 public function utilities() {
278 if (!$this->utilClass) {
279 $this->utilClass = new adLDAPUtils($this);
280 }
281 return $this->utilClass;
282 }
283
284 /**
285 * The contacts class
286 *
287 * @var adLDAPContacts
288 */
289 protected $contactClass;
290
291 /**
292 * Get the contacts class interface
293 *
294 * @return adLDAPContacts
295 */
296 public function contact() {
297 if (!$this->contactClass) {
298 $this->contactClass = new adLDAPContacts($this);
299 }
300 return $this->contactClass;
301 }
302
303 /**
304 * The exchange class
305 *
306 * @var adLDAPExchange
307 */
308 protected $exchangeClass;
309
310 /**
311 * Get the exchange class interface
312 *
313 * @return adLDAPExchange
314 */
315 public function exchange() {
316 if (!$this->exchangeClass) {
317 $this->exchangeClass = new adLDAPExchange($this);
318 }
319 return $this->exchangeClass;
320 }
321
322 /**
323 * The computers class
324 *
325 * @var adLDAPComputers
326 */
327 protected $computersClass;
328
329 /**
330 * Get the computers class interface
331 *
332 * @return adLDAPComputers
333 */
334 public function computer() {
335 if (!$this->computerClass) {
336 $this->computerClass = new adLDAPComputers($this);
337 }
338 return $this->computerClass;
339 }
340
341 /**
342 * Getters and Setters
343 */
344
345 /**
346 * Set the account suffix
347 *
348 * @param string $accountSuffix
349 * @return void
350 */
351 public function setAccountSuffix($accountSuffix)
352 {
353 $this->accountSuffix = $accountSuffix;
354 }
355
356 /**
357 * Get the account suffix
358 *
359 * @return string
360 */
361 public function getAccountSuffix()
362 {
363 return $this->accountSuffix;
364 }
365
366 /**
367 * Set the domain controllers array
368 *
369 * @param array $domainControllers
370 * @return void
371 */
372 public function setDomainControllers(array $domainControllers)
373 {
374 $this->domainControllers = $domainControllers;
375 }
376
377 /**
378 * Get the list of domain controllers
379 *
380 * @return void
381 */
382 public function getDomainControllers()
383 {
384 return $this->domainControllers;
385 }
386
387 /**
388 * Sets the port number your domain controller communicates over
389 *
390 * @param int $adPort
391 */
392 public function setPort($adPort)
393 {
394 $this->adPort = $adPort;
395 }
396
397 /**
398 * Gets the port number your domain controller communicates over
399 *
400 * @return int
401 */
402 public function getPort()
403 {
404 return $this->adPort;
405 }
406
407 /**
408 * Set the username of an account with higher priviledges
409 *
410 * @param string $adminUsername
411 * @return void
412 */
413 public function setAdminUsername($adminUsername)
414 {
415 $this->adminUsername = $adminUsername;
416 }
417
418 /**
419 * Get the username of the account with higher priviledges
420 *
421 * This will throw an exception for security reasons
422 */
423 public function getAdminUsername()
424 {
425 throw new adLDAPException('For security reasons you cannot access the domain administrator account details');
426 }
427
428 /**
429 * Set the password of an account with higher priviledges
430 *
431 * @param string $adminPassword
432 * @return void
433 */
434 public function setAdminPassword($adminPassword)
435 {
436 $this->adminPassword = $adminPassword;
437 }
438
439 /**
440 * Get the password of the account with higher priviledges
441 *
442 * This will throw an exception for security reasons
443 */
444 public function getAdminPassword()
445 {
446 throw new adLDAPException('For security reasons you cannot access the domain administrator account details');
447 }
448
449 /**
450 * Set whether to detect the true primary group
451 *
452 * @param bool $realPrimaryGroup
453 * @return void
454 */
455 public function setRealPrimaryGroup($realPrimaryGroup)
456 {
457 $this->realPrimaryGroup = $realPrimaryGroup;
458 }
459
460 /**
461 * Get the real primary group setting
462 *
463 * @return bool
464 */
465 public function getRealPrimaryGroup()
466 {
467 return $this->realPrimaryGroup;
468 }
469
470 /**
471 * Set whether to use SSL
472 *
473 * @param bool $useSSL
474 * @return void
475 */
476 public function setUseSSL($useSSL)
477 {
478 $this->useSSL = $useSSL;
479 // Set the default port correctly
480 if($this->useSSL) {
481 $this->setPort(self::ADLDAP_LDAPS_PORT);
482 }
483 else {
484 $this->setPort(self::ADLDAP_LDAP_PORT);
485 }
486 }
487
488 /**
489 * Get the SSL setting
490 *
491 * @return bool
492 */
493 public function getUseSSL()
494 {
495 return $this->useSSL;
496 }
497
498 /**
499 * Set whether to use TLS
500 *
501 * @param bool $useTLS
502 * @return void
503 */
504 public function setUseTLS($useTLS)
505 {
506 $this->useTLS = $useTLS;
507 }
508
509 /**
510 * Get the TLS setting
511 *
512 * @return bool
513 */
514 public function getUseTLS()
515 {
516 return $this->useTLS;
517 }
518
519 /**
520 * Set whether to use SSO
521 * Requires ldap_sasl_bind support. Be sure --with-ldap-sasl is used when configuring PHP otherwise this function will be undefined.
522 *
523 * @param bool $useSSO
524 * @return void
525 */
526 public function setUseSSO($useSSO)
527 {
528 if ($useSSO === true && !$this->ldapSaslSupported()) {
529 throw new adLDAPException('No LDAP SASL support for PHP. See: http://www.php.net/ldap_sasl_bind');
530 }
531 $this->useSSO = $useSSO;
532 }
533
534 /**
535 * Get the SSO setting
536 *
537 * @return bool
538 */
539 public function getUseSSO()
540 {
541 return $this->useSSO;
542 }
543
544 /**
545 * Set whether to lookup recursive groups
546 *
547 * @param bool $recursiveGroups
548 * @return void
549 */
550 public function setRecursiveGroups($recursiveGroups)
551 {
552 $this->recursiveGroups = $recursiveGroups;
553 }
554
555 /**
556 * Get the recursive groups setting
557 *
558 * @return bool
559 */
560 public function getRecursiveGroups()
561 {
562 return $this->recursiveGroups;
563 }
564
565 /**
566 * Default Constructor
567 *
568 * Tries to bind to the AD domain over LDAP or LDAPs
569 *
570 * @param array $options Array of options to pass to the constructor
571 * @throws Exception - if unable to bind to Domain Controller
572 * @return bool
573 */
574 function __construct($options = array())
575 {
576 // You can specifically overide any of the default configuration options setup above
577 if (count($options)>0){
578 if (array_key_exists("account_suffix",$options)){ $this->accountSuffix = $options["account_suffix"]; }
579 if (array_key_exists("base_dn",$options)){ $this->baseDn = $options["base_dn"]; }
580 if (array_key_exists("domain_controllers",$options)){
581 if (!is_array($options["domain_controllers"])) {
582 throw new adLDAPException('[domain_controllers] option must be an array');
583 }
584 $this->domainControllers = $options["domain_controllers"];
585 }
586 if (array_key_exists("admin_username",$options)){ $this->adminUsername = $options["admin_username"]; }
587 if (array_key_exists("admin_password",$options)){ $this->adminPassword = $options["admin_password"]; }
588 if (array_key_exists("real_primarygroup",$options)){ $this->realPrimaryGroup = $options["real_primarygroup"]; }
589 if (array_key_exists("use_ssl",$options)){ $this->setUseSSL($options["use_ssl"]); }
590 if (array_key_exists("use_tls",$options)){ $this->useTLS = $options["use_tls"]; }
591 if (array_key_exists("recursive_groups",$options)){ $this->recursiveGroups = $options["recursive_groups"]; }
592 if (array_key_exists("ad_port",$options)){ $this->setPort($options["ad_port"]); }
593 if (array_key_exists("sso",$options)){
594 $this->setUseSSO($options["sso"]);
595 if (!$this->ldapSaslSupported()) {
596 $this->setUseSSO(false);
597 }
598 }
599 }
600
601 if ($this->ldapSupported() === false) {
602 throw new adLDAPException('No LDAP support for PHP. See: http://www.php.net/ldap');
603 }
604
605 return $this->connect();
606 }
607
608 /**
609 * Default Destructor
610 *
611 * Closes the LDAP connection
612 *
613 * @return void
614 */
615 function __destruct(){
616 $this->close();
617 }
618
619 /**
620 * Connects and Binds to the Domain Controller
621 *
622 * @return bool
623 */
624 public function connect()
625 {
626 // Connect to the AD/LDAP server as the username/password
627 $domainController = $this->randomController();
628 if ($this->useSSL) {
629 $this->ldapConnection = ldap_connect("ldaps://" . $domainController, $this->adPort);
630 } else {
631 $this->ldapConnection = ldap_connect($domainController, $this->adPort);
632 }
633
634 // Set some ldap options for talking to AD
635 ldap_set_option($this->ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3);
636 ldap_set_option($this->ldapConnection, LDAP_OPT_REFERRALS, 0);
637
638 if ($this->useTLS) {
639 ldap_start_tls($this->ldapConnection);
640 }
641
642 // Bind as a domain admin if they've set it up
643 if ($this->adminUsername !== NULL && $this->adminPassword !== NULL) {
644 $this->ldapBind = @ldap_bind($this->ldapConnection, $this->adminUsername . $this->accountSuffix, $this->adminPassword);
645 if (!$this->ldapBind) {
646 if ($this->useSSL && !$this->useTLS) {
647 // If you have problems troubleshooting, remove the @ character from the ldapldapBind command above to get the actual error message
648 throw new adLDAPException('Bind to Active Directory failed. Either the LDAPs connection failed or the login credentials are incorrect. AD said: ' . $this->getLastError());
649 }
650 else {
651 throw new adLDAPException('Bind to Active Directory failed. Check the login credentials and/or server details. AD said: ' . $this->getLastError());
652 }
653 }
654 }
655 if ($this->useSSO && $_SERVER['REMOTE_USER'] && $this->adminUsername === null && $_SERVER['KRB5CCNAME']) {
656 putenv("KRB5CCNAME=" . $_SERVER['KRB5CCNAME']);
657 $this->ldapBind = @ldap_sasl_bind($this->ldapConnection, NULL, NULL, "GSSAPI");
658 if (!$this->ldapBind){
659 throw new adLDAPException('Rebind to Active Directory failed. AD said: ' . $this->getLastError());
660 }
661 else {
662 return true;
663 }
664 }
665
666
667 if ($this->baseDn == NULL) {
668 $this->baseDn = $this->findBaseDn();
669 }
670
671 return true;
672 }
673
674 /**
675 * Closes the LDAP connection
676 *
677 * @return void
678 */
679 public function close() {
680 if ($this->ldapConnection) {
681 @ldap_close($this->ldapConnection);
682 }
683 }
684
685 /**
686 * Validate a user's login credentials
687 *
688 * @param string $username A user's AD username
689 * @param string $password A user's AD password
690 * @param bool optional $preventRebind
691 * @return bool
692 */
693 public function authenticate($username, $password, $preventRebind = false) {
694 // Prevent null binding
695 if ($username === NULL || $password === NULL) { return false; }
696 if (empty($username) || empty($password)) { return false; }
697
698 // Allow binding over SSO for Kerberos
699 if ($this->useSSO && $_SERVER['REMOTE_USER'] && $_SERVER['REMOTE_USER'] == $username && $this->adminUsername === NULL && $_SERVER['KRB5CCNAME']) {
700 putenv("KRB5CCNAME=" . $_SERVER['KRB5CCNAME']);
701 $this->ldapBind = @ldap_sasl_bind($this->ldapConnection, NULL, NULL, "GSSAPI");
702 if (!$this->ldapBind) {
703 throw new adLDAPException('Rebind to Active Directory failed. AD said: ' . $this->getLastError());
704 }
705 else {
706 return true;
707 }
708 }
709
710 // Bind as the user
711 $ret = true;
712 $this->ldapBind = @ldap_bind($this->ldapConnection, $username . $this->accountSuffix, $password);
713 if (!$this->ldapBind){
714 $ret = false;
715 }
716
717 // Cnce we've checked their details, kick back into admin mode if we have it
718 if ($this->adminUsername !== NULL && !$preventRebind) {
719 $this->ldapBind = @ldap_bind($this->ldapConnection, $this->adminUsername . $this->accountSuffix , $this->adminPassword);
720 if (!$this->ldapBind){
721 // This should never happen in theory
722 throw new adLDAPException('Rebind to Active Directory failed. AD said: ' . $this->getLastError());
723 }
724 }
725
726 return $ret;
727 }
728
729 /**
730 * Find the Base DN of your domain controller
731 *
732 * @return string
733 */
734 public function findBaseDn()
735 {
736 $namingContext = $this->getRootDse(array('defaultnamingcontext'));
737 return $namingContext[0]['defaultnamingcontext'][0];
738 }
739
740 /**
741 * Get the RootDSE properties from a domain controller
742 *
743 * @param array $attributes The attributes you wish to query e.g. defaultnamingcontext
744 * @return array
745 */
746 public function getRootDse($attributes = array("*", "+")) {
747 if (!$this->ldapBind){ return (false); }
748
749 $sr = @ldap_read($this->ldapConnection, NULL, 'objectClass=*', $attributes);
750 $entries = @ldap_get_entries($this->ldapConnection, $sr);
751 return $entries;
752 }
753
754 /**
755 * Get last error from Active Directory
756 *
757 * This function gets the last message from Active Directory
758 * This may indeed be a 'Success' message but if you get an unknown error
759 * it might be worth calling this function to see what errors were raised
760 *
761 * return string
762 */
763 public function getLastError() {
764 return @ldap_error($this->ldapConnection);
765 }
766
767 /**
768 * Detect LDAP support in php
769 *
770 * @return bool
771 */
772 protected function ldapSupported()
773 {
774 if (!function_exists('ldap_connect')) {
775 return false;
776 }
777 return true;
778 }
779
780 /**
781 * Detect ldap_sasl_bind support in PHP
782 *
783 * @return bool
784 */
785 protected function ldapSaslSupported()
786 {
787 if (!function_exists('ldap_sasl_bind')) {
788 return false;
789 }
790 return true;
791 }
792
793 /**
794 * Schema
795 *
796 * @param array $attributes Attributes to be queried
797 * @return array
798 */
799 public function adldap_schema($attributes){
800
801 // LDAP doesn't like NULL attributes, only set them if they have values
802 // If you wish to remove an attribute you should set it to a space
803 // TO DO: Adapt user_modify to use ldap_mod_delete to remove a NULL attribute
804 $mod=array();
805
806 // Check every attribute to see if it contains 8bit characters and then UTF8 encode them
807 array_walk($attributes, array($this, 'encode8bit'));
808
809 if ($attributes["address_city"]){ $mod["l"][0]=$attributes["address_city"]; }
810 if ($attributes["address_code"]){ $mod["postalCode"][0]=$attributes["address_code"]; }
811 //if ($attributes["address_country"]){ $mod["countryCode"][0]=$attributes["address_country"]; } // use country codes?
812 if ($attributes["address_country"]){ $mod["c"][0]=$attributes["address_country"]; }
813 if ($attributes["address_pobox"]){ $mod["postOfficeBox"][0]=$attributes["address_pobox"]; }
814 if ($attributes["address_state"]){ $mod["st"][0]=$attributes["address_state"]; }
815 if ($attributes["address_street"]){ $mod["streetAddress"][0]=$attributes["address_street"]; }
816 if ($attributes["company"]){ $mod["company"][0]=$attributes["company"]; }
817 if ($attributes["change_password"]){ $mod["pwdLastSet"][0]=0; }
818 if ($attributes["department"]){ $mod["department"][0]=$attributes["department"]; }
819 if ($attributes["description"]){ $mod["description"][0]=$attributes["description"]; }
820 if ($attributes["display_name"]){ $mod["displayName"][0]=$attributes["display_name"]; }
821 if ($attributes["email"]){ $mod["mail"][0]=$attributes["email"]; }
822 if ($attributes["expires"]){ $mod["accountExpires"][0]=$attributes["expires"]; } //unix epoch format?
823 if ($attributes["firstname"]){ $mod["givenName"][0]=$attributes["firstname"]; }
824 if ($attributes["home_directory"]){ $mod["homeDirectory"][0]=$attributes["home_directory"]; }
825 if ($attributes["home_drive"]){ $mod["homeDrive"][0]=$attributes["home_drive"]; }
826 if ($attributes["initials"]){ $mod["initials"][0]=$attributes["initials"]; }
827 if ($attributes["logon_name"]){ $mod["userPrincipalName"][0]=$attributes["logon_name"]; }
828 if ($attributes["manager"]){ $mod["manager"][0]=$attributes["manager"]; } //UNTESTED ***Use DistinguishedName***
829 if ($attributes["office"]){ $mod["physicalDeliveryOfficeName"][0]=$attributes["office"]; }
830 if ($attributes["password"]){ $mod["unicodePwd"][0]=$this->user()->encodePassword($attributes["password"]); }
831 if ($attributes["profile_path"]){ $mod["profilepath"][0]=$attributes["profile_path"]; }
832 if ($attributes["script_path"]){ $mod["scriptPath"][0]=$attributes["script_path"]; }
833 if ($attributes["surname"]){ $mod["sn"][0]=$attributes["surname"]; }
834 if ($attributes["title"]){ $mod["title"][0]=$attributes["title"]; }
835 if ($attributes["telephone"]){ $mod["telephoneNumber"][0]=$attributes["telephone"]; }
836 if ($attributes["mobile"]){ $mod["mobile"][0]=$attributes["mobile"]; }
837 if ($attributes["pager"]){ $mod["pager"][0]=$attributes["pager"]; }
838 if ($attributes["ipphone"]){ $mod["ipphone"][0]=$attributes["ipphone"]; }
839 if ($attributes["web_page"]){ $mod["wWWHomePage"][0]=$attributes["web_page"]; }
840 if ($attributes["fax"]){ $mod["facsimileTelephoneNumber"][0]=$attributes["fax"]; }
841 if ($attributes["enabled"]){ $mod["userAccountControl"][0]=$attributes["enabled"]; }
842 if ($attributes["homephone"]){ $mod["homephone"][0]=$attributes["homephone"]; }
843
844 // Distribution List specific schema
845 if ($attributes["group_sendpermission"]){ $mod["dlMemSubmitPerms"][0]=$attributes["group_sendpermission"]; }
846 if ($attributes["group_rejectpermission"]){ $mod["dlMemRejectPerms"][0]=$attributes["group_rejectpermission"]; }
847
848 // Exchange Schema
849 if ($attributes["exchange_homemdb"]){ $mod["homeMDB"][0]=$attributes["exchange_homemdb"]; }
850 if ($attributes["exchange_mailnickname"]){ $mod["mailNickname"][0]=$attributes["exchange_mailnickname"]; }
851 if ($attributes["exchange_proxyaddress"]){ $mod["proxyAddresses"][0]=$attributes["exchange_proxyaddress"]; }
852 if ($attributes["exchange_usedefaults"]){ $mod["mDBUseDefaults"][0]=$attributes["exchange_usedefaults"]; }
853 if ($attributes["exchange_policyexclude"]){ $mod["msExchPoliciesExcluded"][0]=$attributes["exchange_policyexclude"]; }
854 if ($attributes["exchange_policyinclude"]){ $mod["msExchPoliciesIncluded"][0]=$attributes["exchange_policyinclude"]; }
855 if ($attributes["exchange_addressbook"]){ $mod["showInAddressBook"][0]=$attributes["exchange_addressbook"]; }
856 if ($attributes["exchange_altrecipient"]){ $mod["altRecipient"][0]=$attributes["exchange_altrecipient"]; }
857 if ($attributes["exchange_deliverandredirect"]){ $mod["deliverAndRedirect"][0]=$attributes["exchange_deliverandredirect"]; }
858
859 // This schema is designed for contacts
860 if ($attributes["exchange_hidefromlists"]){ $mod["msExchHideFromAddressLists"][0]=$attributes["exchange_hidefromlists"]; }
861 if ($attributes["contact_email"]){ $mod["targetAddress"][0]=$attributes["contact_email"]; }
862
863 //echo ("<pre>"); print_r($mod);
864 /*
865 // modifying a name is a bit fiddly
866 if ($attributes["firstname"] && $attributes["surname"]){
867 $mod["cn"][0]=$attributes["firstname"]." ".$attributes["surname"];
868 $mod["displayname"][0]=$attributes["firstname"]." ".$attributes["surname"];
869 $mod["name"][0]=$attributes["firstname"]." ".$attributes["surname"];
870 }
871 */
872
873 if (count($mod)==0){ return (false); }
874 return ($mod);
875 }
876
877 /**
878 * Convert 8bit characters e.g. accented characters to UTF8 encoded characters
879 */
880 protected function encode8Bit(&$item, $key) {
881 $encode = false;
882 if (is_string($item)) {
883 for ($i=0; $i<strlen($item); $i++) {
884 if (ord($item[$i]) >> 7) {
885 $encode = true;
886 }
887 }
888 }
889 if ($encode === true && $key != 'password') {
890 $item = utf8_encode($item);
891 }
892 }
893
894 /**
895 * Select a random domain controller from your domain controller array
896 *
897 * @return string
898 */
899 protected function randomController()
900 {
901 mt_srand(doubleval(microtime()) * 100000000); // For older PHP versions
902 /*if (sizeof($this->domainControllers) > 1) {
903 $adController = $this->domainControllers[array_rand($this->domainControllers)];
904 // Test if the controller is responding to pings
905 $ping = $this->pingController($adController);
906 if ($ping === false) {
907 // Find the current key in the domain controllers array
908 $key = array_search($adController, $this->domainControllers);
909 // Remove it so that we don't end up in a recursive loop
910 unset($this->domainControllers[$key]);
911 // Select a new controller
912 return $this->randomController();
913 }
914 else {
915 return ($adController);
916 }
917 } */
918 return $this->domainControllers[array_rand($this->domainControllers)];
919 }
920
921 /**
922 * Test basic connectivity to controller
923 *
924 * @return bool
925 */
926 protected function pingController($host) {
927 $port = $this->adPort;
928 fsockopen($host, $port, $errno, $errstr, 10);
929 if ($errno > 0) {
930 return false;
931 }
932 return true;
933 }
934
935 }
936
937 /**
938 * adLDAP Exception Handler
939 *
940 * Exceptions of this type are thrown on bind failure or when SSL is required but not configured
941 * Example:
942 * try {
943 * $adldap = new adLDAP();
944 * }
945 * catch (adLDAPException $e) {
946 * echo $e;
947 * exit();
948 * }
949 */
950 class adLDAPException extends Exception {}
951
952 ?>