· 10 years ago · Apr 27, 2016, 07:30 PM
1<?php
2/**
3 * wpDirAuth: WordPress Directory Authentication (LDAP/LDAPS).
4 *
5 * Works with most LDAP enabled directory services, such as OpenLDAP,
6 * Apache Directory, Microsoft Active Directory, Novell eDirectory,
7 * Sun Java System Directory Server, etc.
8 *
9 * Please note that wpDirAuth will start in safe mode if it detects that
10 * another plugin is in conflict, by detecting if the wp_authenticate and
11 * wp_setcookie functions have already been overwritten. It cannot,
12 * on the other hand, detect plugins that might want to overwrite these
13 * functions after wpDirAuth has been loaded.
14 *
15 * Originally forked from a patched version of wpLDAP.
16 *
17 * @package wpDirAuth
18 * @version 1.7.15
19 * @see http://wpdirauth.gilzow.com/
20 * @license GPL <http://www.gnu.org/licenses/gpl.html>
21 *
22 * Copyrights are listed in chronological order, by contributions.
23 *
24 * wpDirAuth: WordPress Directory Authentication, original author
25 * Copyright (c) 2007 Stephane Daury - http://stephane.daury.org/
26 *
27 * wpDirAuth and wpLDAP Patch Contributions
28 * Copyright (c) 2007 PKR Internet, LLC - http://www.pkrinternet.com/
29 *
30 * wpDirAuth Patch Contributions
31 * Copyright (c) 2007 Todd Beverly
32 *
33 * wpLDAP: WordPress LDAP Authentication
34 * Copyright (c) 2007 Ashay Suresh Manjure - http://ashay.org/
35 *
36 * wpDirAuth Patch Contribution and current maintainer
37 * Copyright (c) 2010, 2011, 2012 Paul Gilzow - http://gilzow.com/
38 *
39 * wpDirAuth is free software: you can redistribute it and/or modify it
40 * under the terms of the GNU General Public License as published by the
41 * Free Software Foundation.
42 *
43 * wpDirAuth is distributed in the hope that it will be useful,
44 * but WITHOUT ANY WARRANTY; without even the implied warranty of
45 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46 * GNU General Public License for more details.
47 *
48 * You should have received a copy of the GNU General Public License
49 * along with this program. If not, see http://www.gnu.org/licenses/.
50 *
51 * @todo Always stay on top of security and user input validation while
52 * staying backwards compatible enough until PHP4 support is dropped in
53 * WP (serious patches welcomed, please see code). Note that we do
54 * heavily rely on WP's admin ACL scheme, by necessity.
55 */
56
57/*
58PLUGIN META INFO FOR WORDPRESS LISTINGS
59Plugin Name: wpDirAuth
60Plugin URI: http://wpdirauth.gilzow.com/
61Description: WordPress Directory Authentication (LDAP/LDAPS).
62 Works with most LDAP enabled directory services, such as OpenLDAP,
63 Apache Directory, Microsoft Active Directory, Novell eDirectory,
64 Sun Java System Directory Server, etc.
65 Originally revived and upgraded from a patched version of wpLDAP.
66Version: 1.7.15
67Author: Paul Gilzow
68Author URI: http://gilzow.com/
69*/
70
71/**
72 * wpDirAuth version.
73 */
74define('WPDIRAUTH_VERSION', '1.7.15');
75
76/**
77 * wpDirAuth signature.
78 */
79define('WPDIRAUTH_SIGNATURE', '<a href="http://wordpress.org/extend/plugins/wpdirauth/">wpDirAuth</a> '.WPDIRAUTH_VERSION);
80
81/**
82 * Default LDAP field to search against when locating the user's profile.
83 */
84define('WPDIRAUTH_DEFAULT_FILTER', 'samAccountName');
85
86/**
87 * Default login screen message.
88 */
89define('WPDIRAUTH_DEFAULT_LOGINSCREENMSG', '%s members can login directly using their institutional password.');
90
91/**
92 * Default password change message.
93 */
94define('WPDIRAUTH_DEFAULT_CHANGEPASSMSG', 'To change a %s password, please refer to the official institutional password policy.');
95
96/**
97 * Allowed HTML (messages)
98 */
99define('WPDIRAUTH_ALLOWED_TAGS', '<a><strong><em><p><ul><ol><li>');
100
101define('WPDIRAUTH_ERROR_TITLE',__('<strong>Directory Authentication Error</strong>: '));
102
103define('WPDIRAUTH_LDAP_RETURN_KEYS',serialize(array('sn', 'givenname', 'mail')));
104
105define('WPDIRAUTH_EMAIL_NEWUSER_NOTIFY','You have been added to the site %s as %s %s. You may login to the site using your institution\'s %s (%s) and password at the following address: %s');
106
107/**
108 *My fail-safe method for determing if we are running in multisite mode
109 */
110define('WPDIRAUTH_MULTISITE',(defined('WP_ALLOW_MULTISITE') && WP_ALLOW_MULTISITE && function_exists('switch_to_blog')) ? TRUE : FALSE);
111
112/**
113 *List of option keys we store in wp_sitemeta/wp_options
114 */
115define('WPDIRAUTH_OPTIONS', serialize(array(
116 'dirAuthEnable',
117 'dirAuthRequiresSsl',
118 'dirAuthTOS',
119 'dirAuthUseGroups',
120 'dirAuthEnableSsl',
121 'dirAuthControllers',
122 'dirAuthBaseDn',
123 'dirAuthPreBindUser',
124 'dirAuthAccountSuffix',
125 'dirAuthFilter',
126 'dirAuthInstitution',
127 'dirAuthGroups',
128 'dirAuthMarketingSSOID',
129 'dirAuthLoginScreenMsg',
130 'dirAuthChangePassMsg'
131)));
132
133
134if (function_exists('wp_authenticate') || function_exists('wp_setcookie') || !function_exists('ldap_connect')) {
135 /**
136 * SAFE MODE
137 */
138
139 /**
140 * SAFE MODE: wpDirAuth plugin configuration panel.
141 * Processes and outputs the wpDirAuth configuration form, with a conflict message.
142 *
143 * @return void
144 */
145 function wpDirAuth_safeConflictMessage()
146 {
147 $wpDARef = WPDIRAUTH_SIGNATURE;
148
149 if (!function_exists('ldap_connect')) {
150 $message = <<<________EOS
151 <h3>Sorry, but your PHP install does not seem to have access to the LDAP features.</h3>
152 <p>
153 <br />wpDirAuth is now running in safe mode.'
154 </p>
155 <p>
156 Quote from the <a href="http://php.net/ldap#ldap.installation">PHP manual LDAP section</a>:
157 <blockquote>
158 LDAP support in PHP is not enabled by default. You will need to use the
159 --with-ldap[=DIR] configuration option when compiling PHP to enable LDAP
160 support. DIR is the LDAP base install directory. To enable SASL support,
161 be sure --with-ldap-sasl[=DIR] is used, and that sasl.h exists on the system.
162 </blockquote>
163 </p>
164________EOS;
165 }
166 else {
167 $message = <<<________EOS
168 <h3>Sorry, but another plugin seems to be conflicting with wpDirAuth.</h3>
169 <p>
170 <br />wpDirAuth is now running in safe mode as to not impair the other plugin's operations.'
171 </p>
172 <p>
173 The wp_authenticate and wp_setcookie WordPress
174 <a href="http://codex.wordpress.org/Pluggable_Functions">pluggable functions</a>
175 have already been redefined, and wpDirAuth cannot provide directory authentication
176 without having access to these functions.
177 </p>
178 <p>
179 Please disable any WP plugins that deal with authentication in order to use wpDirAuth.
180 Unfortunately, we cannot provide you with more info as to which plugin is in conflict.
181 </p>
182________EOS;
183 }
184
185 echo <<<________EOS
186 <div class="wrap">
187 <h2>Directory Authentication Options: Plugin Conflict</h2>
188 $message
189 <p>$wpDARef</p>
190 </div>
191________EOS;
192 }
193
194
195 /**
196 * SAFE MODE: Adds the `Directory Auth.` menu entry in the Wordpress Admin section.
197 * Also activates the wpDirAuth config panel, with a conflict message, as a callback function.
198 *
199 * @uses wpDirAuth_safeConflictMessage
200 */
201 function wpDirAuth_safeAddMenu()
202 {
203 if (function_exists('add_options_page')) {
204 add_options_page(
205 'Directory Authentication Options: Plugin Conflict',
206 '!! Directory Auth. !!',
207 'manage_options',
208 basename(__FILE__),
209 'wpDirAuth_safeConflictMessage'
210 );
211 }
212 }
213
214
215 /**
216 * SAFE MODE: Add custom WordPress actions.
217 *
218 * @uses wpDirAuth_safeAddMenu
219 */
220 if (function_exists('add_action')) {
221 add_action('admin_menu', 'wpDirAuth_safeAddMenu');
222 }
223}
224else {
225 /**
226 * STANDARD MODE
227 */
228
229 /**
230 * Cookie marker.
231 * Generates a random string to be used as salt for the password
232 * hash cookie checks in wp_setcookie and wp_authenticate
233 *
234 * @return string 55 chars-long salty goodness (md5 + uniqid)
235 */
236 function wpDirAuth_makeCookieMarker()
237 {
238 $cookieMarker = md5(
239 $_SERVER['SERVER_SIGNATURE']
240 .$_SERVER['HTTP_USER_AGENT']
241 .$_SERVER['REMOTE_ADDR']
242 ).uniqid(microtime(),true);
243 update_site_option("dirAuthCookieMarker",$cookieMarker);
244 return $cookieMarker;
245 }
246
247
248 /**
249 * LDAP bind test
250 * Tries two different documented method of php-based ldap binding.
251 * Note: passing params by reference, no need for copies (unlike in
252 * wpDirAuth_auth where it is desirable).
253 *
254 * @param object &$connection LDAP connection
255 * @param string &$username LDAP username
256 * @param string &$password LDAP password
257 * @param string $baseDn
258 * @return boolean Binding status
259 * */
260 function wpDirAuth_bindTest(&$connection, &$username, &$password,$baseDn)
261 {
262 //$password = strtr($password, array("\'"=>"'"));
263 /**
264 * Why stripslashes on the password? Because wordpress.
265 * @see: https://codex.wordpress.org/Function_Reference/stripslashes_deep#Good_Coding_Practice
266 */
267 $password = stripslashes_deep($password);
268 if ( ($isBound = @ldap_bind($connection, $username, $password)) === false ) {
269 // @see http://weblogs.valsania.it/andreav/2008/07/24/wpdirauth-14-patch/
270 $isBound = @ldap_bind($connection,"uid=$username,$baseDn", $password);
271 }
272 return $isBound;
273 }
274
275 /**
276 * put your comment there...
277 *
278 * @param string $dc name of domain controller to connect to
279 * @param integer $enableSsl ssl config option
280 * @return resource
281 */
282 function wpDirAuth_establishConnection($dc,$enableSsl){
283 /**
284 * Only setup protocol value if ldaps is required to help with older AD
285 * @see http://groups.google.com/group/wpdirauth-support/browse_thread/thread/7b744c7ad66a4829
286 */
287 $protocol = ($enableSsl) ? 'ldaps://' : '';
288
289 /**
290 * Scan for and use alternate server port, but only if ssl is disabled.
291 * @see Parameters constraint at http://ca.php.net/ldap_connect
292 */
293
294 if (strstr($dc, ':')) list($dc, $port) = explode(':', $dc);
295
296 switch($enableSsl){
297 case 1:
298 $connection = ldap_connect($protocol.$dc);
299 break;
300 case 2:
301 case 0:
302 default:
303 if(isset($port)){
304 $connection = ldap_connect($dc,$port);
305 } else {
306 $connection = ldap_connect($dc);
307 }
308 break;
309
310 }
311
312 /**
313 * Copes with W2K3/AD issue.
314 * @see http://bugs.php.net/bug.php?id=30670
315 */
316 if (@ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, 3)) {
317 @ldap_set_option($connection, LDAP_OPT_REFERRALS, 0);
318 }
319
320 //they want to start TLS
321 if($enableSsl == 2){
322 if(!ldap_start_tls($connection)){
323 return new WP_Error('tls_failed_to_start',__('wpDirAuth error: tls failed to start'));
324 }
325 }
326
327 return $connection;
328 }
329
330 /**
331 * put your comment there...
332 *
333 * @param array $controllers list of domain controllers to connect to
334 * @return mixed array of shuffled controllers or WP_Error
335 */
336 function wpDirAuth_shuffleControllers($controllers){
337 if (count($controllers) > 1) {
338 // shuffle the domain controllers for pseudo load balancing and fault tolerance.
339 shuffle($controllers);
340 } elseif (count($controllers) == 0) {
341 return new WP_Error('no_controllers',__(' wpDirAuth config error: no domain controllers specified.'));
342 }
343
344 return $controllers;
345 }
346
347 /**
348 * Custom LDAP authentication module.
349 * The returned keys are in the same format used by WP for
350 * the wp_insert_user and wp_update_user functions.
351 *
352 * @param string $username LDAP username
353 * @param string $password LDAP password
354 * @return WP_Error object OR array Directory email, last_name and first_name
355 *
356 * @uses WPDIRAUTH_DEFAULT_FILTER
357 * @uses WPDIRAUTH_ERROR_TITLE
358 * @uses wpDirAuth_bindTest
359 * @uses wpDirAuth_retrieveUserDetails
360 * @uses wpDirAuth_shuffleControllers
361 * @uses wpDirAuth_establishConnection
362 */
363 function wpDirAuth_auth($username, $password)
364 {
365 global $error, $pwd;
366
367 $errorTitle = WPDIRAUTH_ERROR_TITLE;
368 $isInDirectory = false;
369 $results = false;
370 $controllers = explode(',', get_site_option('dirAuthControllers'));
371 $baseDn = get_site_option('dirAuthBaseDn');
372 $preBindUser = get_site_option('dirAuthPreBindUser');
373 $preBindPassword = get_site_option('dirAuthPreBindPassword');
374 $accountSuffix = get_site_option('dirAuthAccountSuffix');
375 $filter = get_site_option('dirAuthFilter');
376 $enableSsl = get_site_option('dirAuthEnableSsl');
377 $boolUseGroups = get_site_option('dirAuthUseGroups');
378
379 if($boolUseGroups == 1){
380 $strAuthGroups = get_site_option('dirAuthGroups');
381 }
382
383 $returnKeys = unserialize(WPDIRAUTH_LDAP_RETURN_KEYS);
384
385 $isBound = $isPreBound = $isLoggedIn = false;
386
387 if ($accountSuffix) $username .= $accountSuffix;
388
389 if (!$filter) $filter = WPDIRAUTH_DEFAULT_FILTER;
390
391 $filterQuery = "($filter=$username)";
392
393 $filterQuery = apply_filters('wpdirauth_filterquery',$filterQuery,$filter,$username);
394
395 $controllers = wpDirAuth_shuffleControllers($controllers);
396
397 if(is_wp_error($controllers)){
398 return $controllers;
399 }
400
401 /**
402 * Bit of hack until I can rewrite this auth piece and only return once.
403 * We need to let other plugins have the opportunity to fail an authentication before we attempt our authentication.
404 * specifically, brute force checkers, captcha's, etc.
405 */
406 $mxdAlreadyFailed = apply_filters('authenticate',null,$username,$password);
407
408 if(is_wp_error($mxdAlreadyFailed)){
409 return $mxdAlreadyFailed;
410 }
411
412 // Connection pool loop - Haha, PooL LooP
413 foreach ($controllers as $dc) {
414
415 $connection = wpDirAuth_establishConnection($dc,$enableSsl);
416
417 if(is_wp_error($connection)){
418 return $connection;
419 }
420
421 if ($preBindUser && $preBindPassword) {
422 /**
423 * Use case 1: Servers requiring pre-binding with admin defined
424 * credentials to search for the user's full DN before attempting
425 * to login.
426 * @see http://dev.wp-plugins.org/ticket/681
427 */
428 if ( $isPreBound = wpDirAuth_bindTest($connection, $preBindUser, $preBindPassword,$baseDn) === true ) {
429 if ( ($results = @ldap_search($connection, $baseDn, $filterQuery, $returnKeys)) !== false ) {
430 if ( ($userDn = @ldap_get_dn($connection, ldap_first_entry($connection, $results))) !== false ) {
431 if ( ($isBound = wpDirAuth_bindTest($connection, $userDn, $password,$baseDn)) === true ) {
432 $isLoggedIn = true; // valid server, valid login, move on
433 break; // valid server, valid login, move on
434 }
435 }
436 }
437 }
438 }
439 elseif ( ($isBound = wpDirAuth_bindTest($connection, $username, $password,$baseDn)) === true ) {
440 /**
441 * Use case 2: Servers that will not let you bind anonymously
442 * but will let the end user bind directly.
443 * @see http://groups.google.com/group/wpdirauth-support/browse_thread/thread/8fd16c05266fc832
444 */
445 $isLoggedIn = true;
446 break; // valid server, valid login, move on
447 }
448 elseif ( ($isBound = @ldap_bind($connection)) === true ) {
449 /**
450 * Use case 3: Servers that might require a full user DN to
451 * actually login and therefore let you bind anonymously first .
452 * Try ldap_search + ldap_get_dn before attempting a login.
453 * @see http://wordpress.org/support/topic/129814?replies=34#post-603644
454 */
455 if ( ($results = @ldap_search($connection, $baseDn, $filterQuery, $returnKeys)) !== false ) {
456 if ( ($userDn = @ldap_get_dn($connection, ldap_first_entry($connection, $results))) !== false ) {
457 $isInDirectory = true; // account exists in directory
458 if ( ($isBound = wpDirAuth_bindTest($connection, $userDn, $password,$baseDn)) === true ) {
459 $isLoggedIn = true; // valid server, valid login, move on
460 break; // valid server, valid login, move on
461 }
462 }
463 }
464 }
465 }
466
467 if ( ($preBindUser && $preBindPassword) && ( ! $isPreBound ) ) {
468 return new WP_Error ('no_directory_or_prebinding', $errorTitle
469 . __(' wpDirAuth config error: No directory server available for authentication, OR pre-binding credentials denied.'));
470 }
471 elseif ( ( $isInDirectory ) && ( ! $isBound ) ) {
472 return new WP_Error ('could_not_bind_as_user', $errorTitle
473 . __(' Incorrect password.'));
474 }
475 elseif ( ! $isBound && ! $isPreBound ) {
476 return new WP_Error ('no_directory_available', $errorTitle
477 . __(' wpDirAuth config error: No directory server available for authentication.'));
478 }
479 elseif ( ! $isLoggedIn) {
480 /**
481 * @desc wp-hack was echo'ing out $username verbatim which allowed a XSS vulnerability. Encoded $username before echoing'
482 */
483 return new WP_Error ('could_not_authenticate', $errorTitle
484 . __(' Could not authenticate user. Please check your credentials.')
485 . " [" . htmlentities($username,ENT_QUOTES,'UTF-8') . "]");
486
487
488 }
489 else {
490 if($boolUseGroups == 1){
491 //the user is authenticated, but we want to make sure they are a member of the groups given
492 /**
493 * We need to get the DN's for each Authentication Group CN that was given to us.
494 */
495 $aryAuthGroupsDN = array();
496 $aryAuthGroups = explode(',',$strAuthGroups);
497 $aryAttribs = array('distinguishedname');
498 foreach($aryAuthGroups as $strAuthGroup){
499 $strAuthGroup = 'cn='.$strAuthGroup;
500 $rscLDAPSearch = ldap_search($connection,$baseDn,$strAuthGroup,$aryAttribs);
501 $arySearchResults = ldap_get_entries($connection,$rscLDAPSearch);
502 if(isset($arySearchResults[0]['dn'])){
503 $aryAuthGroupsDN[] = $arySearchResults[0]['dn'];
504 }
505 }
506
507 if(count($aryAuthGroupsDN) == 0){
508 return new WP_Error('no_auth_groups_found',$errorTitle.__('No Authentication Groups found based on given group CN'));
509 }
510
511
512 $strFilterQuery = '(&'.$filterQuery.'(|';
513 foreach($aryAuthGroupsDN as $strAuthGroupDN){
514 $strFilterQuery .= '(memberOf='.$strAuthGroupDN.')';
515 }
516 $strFilterQuery .= '))';
517 if(($rscLDAPSearchGroupMember = ldap_search($connection,$baseDn,$strFilterQuery)) !== false){
518 $arySearchResultsMember = ldap_get_entries($connection,$rscLDAPSearchGroupMember);
519 if($arySearchResultsMember['count'] !== 1){
520 return new WP_Error('not_member_of_auth_group',$errorTitle
521 . __('User authenticated but is not a member of an Authentication Group(s)'));
522 }
523 }
524
525 }
526
527
528 /**
529 * Search for profile, if still needed.
530 * $result is set to false by default. reset to a resource or false again in lines 403-437
531 * wpDirAuth_retrieveUserDetails() now checks the value of $results before continuing
532 */
533
534 return wpDirAuth_retrieveUserDetails($connection,$baseDn,$filterQuery,$results);
535
536 }
537 }
538
539
540 /**
541 * Runs stripslashes, html_entity_decode, then strip_tags with
542 * allowed html if requested.
543 *
544 * No input sashimi for us (hopefully).
545 *
546 * @param string $value Value to `sanitize`
547 * @param boolean $allowed Set to true for WPDIRAUTH_ALLOWED_TAGS
548 * @return string Cleaner value.
549 *
550 * @uses WPDIRAUTH_ALLOWED_TAGS
551 */
552 function wpDirAuth_sanitize($value, $allowed = false)
553 {
554 $allowed = ($allowed) ? WPDIRAUTH_ALLOWED_TAGS : '';
555 return strip_tags(html_entity_decode(stripslashes($value)), $allowed);
556 }
557
558
559 /**
560 * wpDirAuth plugin configuration panel.
561 * Processes and outputs the wpDirAuth configuration form.
562 *
563 * @return void
564 *
565 * @uses WPDIRAUTH_DEFAULT_FILTER
566 * @uses WPDIRAUTH_DEFAULT_LOGINSCREENMSG
567 * @uses WPDIRAUTH_DEFAULT_CHANGEPASSMSG
568 * @uses WPDIRAUTH_ALLOWED_TAGS
569 * @uses wpDirAuth_makeCookieMarker
570 * @uses wpDirAuth_sanitize
571 */
572 function wpDirAuth_optionsPanel()
573 {
574 global $userdata;
575
576 $wpDARef = WPDIRAUTH_SIGNATURE;
577 $allowedHTML = htmlentities(WPDIRAUTH_ALLOWED_TAGS);
578
579 $curUserIsDirUser = get_user_meta($userdata->ID, 'wpDirAuthFlag',true);
580
581 if ($curUserIsDirUser) {
582 echo <<<____________EOS
583 <div class="wrap">
584 <h2>Directory Authentication Options</h2>
585 <p>
586 Because any changes made to directory authentication
587 options can adversly affect your session when logged in
588 as a directory user, you must be logged in as a
589 WordPress-only administrator user to update these settings.
590 </p>
591 <p>
592 If such a user no longer exists in the database, please
593 <a href="./users.php#add-new-user">create a new one</a>
594 using the appropriate WordPress admin tool.
595 </p>
596 <p>$wpDARef</p>
597 </div>
598____________EOS;
599 return;
600 }
601
602 if ($_POST) {
603 $enableSsl = 0; //default
604 $boolUseGroups = 0; //default
605 // Booleans
606 $enable = intval($_POST['dirAuthEnable']) == 1 ? 1 : 0;
607 $requireSsl = intval($_POST['dirAuthRequireSsl']) == 1 ? 1 : 0;
608 $TOS = intval($_POST['dirAuthTOS']) == 1 ? 1 : 0;
609 $boolAutoRegister = intval($_POST['dirAuthAutoRegistration'])== 1 ? 1 : 0;
610 _wpdirauth_log($boolAutoRegister,'value for autoregister passed via POST',false,array('line'=>__LINE__,'file'=>__FILE__));
611 //integers
612 if(intval($_POST['dirAuthEnableSsl']) == 1 || intval($_POST['dirAuthEnableSsl']) == 2){
613 $enableSsl = intval($_POST['dirAuthEnableSsl']);
614 }
615
616
617 // Strings, no HTML
618 $controllers = wpDirAuth_sanitize($_POST['dirAuthControllers']);
619 $baseDn = wpDirAuth_sanitize($_POST['dirAuthBaseDn']);
620 $preBindUser = wpDirAuth_sanitize($_POST['dirAuthPreBindUser']);
621 $preBindPassword = wpDirAuth_sanitize($_POST['dirAuthPreBindPassword']);
622 $preBindPassCheck = wpDirAuth_sanitize($_POST['dirAuthPreBindPassCheck']);
623 $accountSuffix = wpDirAuth_sanitize($_POST['dirAuthAccountSuffix']);
624 $filter = wpDirAuth_sanitize($_POST['dirAuthFilter']);
625 $institution = wpDirAuth_sanitize($_POST['dirAuthInstitution']);
626 $strAuthGroups = wpDirAuth_sanitize($_POST['dirAuthGroups']);
627 $strMarketingSSOID= wpDirAuth_sanitize(($_POST['dirAuthMarketingSSOID']));
628
629 if($strAuthGroups != ''){
630 $boolUseGroups = 1;
631 if(1 == $boolAutoRegister){
632 //they are using authgroups, but they also want us to autoregister. sorry, cant do that.
633 $boolAutoRegister = 0;
634 }
635 }
636
637 // Have to be allowed to contain some HTML
638 $loginScreenMsg = wpDirAuth_sanitize($_POST['dirAuthLoginScreenMsg'], true);
639 $changePassMsg = wpDirAuth_sanitize($_POST['dirAuthChangePassMsg'], true);
640
641 _wpdirauth_log($boolAutoRegister,'auto register before saving',false,array('line'=>__LINE__,'file'=>__FILE__));
642 update_site_option('dirAuthEnable', $enable);
643 update_site_option('dirAuthEnableSsl', $enableSsl);
644 update_site_option('dirAuthRequireSsl', $requireSsl);
645 update_site_option('dirAuthAutoRegister', $boolAutoRegister);
646 update_site_option('dirAuthControllers', $controllers);
647 update_site_option('dirAuthBaseDn', $baseDn);
648 update_site_option('dirAuthPreBindUser', $preBindUser);
649 update_site_option('dirAuthAccountSuffix', $accountSuffix);
650 update_site_option('dirAuthFilter', $filter);
651 update_site_option('dirAuthInstitution', $institution);
652 update_site_option('dirAuthLoginScreenMsg', $loginScreenMsg);
653 update_site_option('dirAuthChangePassMsg', $changePassMsg);
654 update_site_option('dirAuthTOS', $TOS);
655 update_site_option('dirAuthUseGroups', $boolUseGroups);
656 update_site_option('dirAuthGroups', $strAuthGroups);
657 update_site_option('dirAuthMarketingSSOID', $strMarketingSSOID);
658
659
660 // Only store/override the value if a new one is being sent a bind user is set.
661 if ( $preBindUser && $preBindPassword && ($preBindPassCheck == $preBindPassword) )
662 update_site_option('dirAuthPreBindPassword', $preBindPassword);
663
664 // Clear the stored password if the Bind DN is null
665 elseif ( ! $preBindUser)
666 update_site_option('dirAuthPreBindPassword', '');
667
668 if (get_site_option('dirAuthEnable') && !get_site_option('dirAuthCookieMarker'))
669 wpDirAuth_makeCookieMarker();
670
671 echo '<div id="message" class="updated fade"><p>Your new settings were saved successfully.</p></div>';
672
673 // Be sure to clear $preBindPassword, not to be displayed onscreen or in source
674 unset($preBindPassword);
675 } else {
676 // Booleans
677 $enable = intval(get_site_option('dirAuthEnable')) == 1 ? 1 : 0;
678 $requireSsl = intval(get_site_option('dirAuthRequireSsl')) == 1 ? 1 : 0;
679 $TOS = intval(get_site_option('dirAuthTOS')) == 1 ? 1 : 0;
680 $boolUseGroups = intval(get_site_option('dirAuthUseGroups')) == 1 ? 1 : 0;
681 $boolAutoRegister= intval(get_site_option('dirAuthAutoRegister'))== 1 ? 1 : 0;
682
683 //integers
684 $enableSsl = intval(get_site_option('dirAuthEnableSsl',0));
685
686 // Strings, no HTML
687 $controllers = wpDirAuth_sanitize(get_site_option('dirAuthControllers'));
688 $baseDn = wpDirAuth_sanitize(get_site_option('dirAuthBaseDn'));
689 $preBindUser = wpDirAuth_sanitize(get_site_option('dirAuthPreBindUser'));
690 $accountSuffix = wpDirAuth_sanitize(get_site_option('dirAuthAccountSuffix'));
691 $filter = wpDirAuth_sanitize(get_site_option('dirAuthFilter'));
692 $institution = wpDirAuth_sanitize(get_site_option('dirAuthInstitution'));
693 $strAuthGroups = wpDirAuth_sanitize((get_site_option('dirAuthGroups')));
694 $strMarketingSSOID = wpDirAuth_sanitize((get_site_option('dirAuthMarketingSSOID')));
695
696 // Have to be allowed to contain some HTML
697 $loginScreenMsg = wpDirAuth_sanitize(get_site_option('dirAuthLoginScreenMsg'), true);
698 $changePassMsg = wpDirAuth_sanitize(get_site_option('dirAuthChangePassMsg'), true);
699 }
700
701 $controllers = htmlspecialchars($controllers);
702 $baseDn = htmlspecialchars($baseDn);
703 $preBindUser = htmlspecialchars($preBindUser);
704 $accountSuffix = htmlspecialchars($accountSuffix);
705 $filter = htmlspecialchars($filter);
706 $institution = htmlspecialchars($institution);
707 $loginScreenMsg = htmlspecialchars($loginScreenMsg);
708 $changePassMsg = htmlspecialchars($changePassMsg);
709 $strAuthGroups = htmlspecialchars($strAuthGroups);
710
711 $tEnable = $fEnable = $tWpSsl = $fWpSsl = $tTOS = $fTOS = '';
712
713 if ($enable) {
714 $tEnable = "checked";
715 }
716 else {
717 $fEnable = "checked";
718 }
719
720 $defaultFilter = WPDIRAUTH_DEFAULT_FILTER;
721 if (!$filter) {
722 $filter = $defaultFilter;
723 }
724
725 if (!$institution) {
726 $institution = '[YOUR INSTITUTION]';
727 }
728
729 if (!$loginScreenMsg) {
730 $loginScreenMsg = sprintf(WPDIRAUTH_DEFAULT_LOGINSCREENMSG, $institution);
731 }
732
733 if (!$changePassMsg) {
734 $changePassMsg = sprintf(WPDIRAUTH_DEFAULT_CHANGEPASSMSG, $institution);
735 }
736
737 /**
738 * If they are using authentication groups we will not automaticaly register authed users that dont already have an account
739 */
740 if('' != $strAuthGroups && $boolAutoRegister == 1){
741 $boolAutoRegister = 0;
742 }
743
744 /*
745 if ($enableSsl) {
746 $tSsl = "checked";
747 }
748 else {
749 $fSsl = "checked";
750 }
751 */
752 $strNoSSL ='';
753 $strSSL = '';
754 $strTLS = '';
755 $strOptionSelected = 'selected="selected"';
756 switch($enableSsl){
757 case 1:
758 $strSSL = $strOptionSelected;
759 break;
760 case 2:
761 $strTLS = $strOptionSelected;
762 break;
763 case 0:
764 default:
765 $strNoSSL = $strOptionSelected;
766 break;
767
768 }
769
770 if ($requireSsl) {
771 $tWpSsl = "checked";
772 }
773 else {
774 $fWpSsl = "checked";
775 }
776
777 if ($TOS) {
778 $tTOS = "checked";
779 }
780 else {
781 $fTOS = "checked";
782 }
783
784 $strYesAutoRegister = '';
785 $strNoAutoRegister = '';
786 if($boolAutoRegister){
787 $strYesAutoRegister = 'checked';
788 } else {
789 $strNoAutoRegister = 'checked';
790 }
791
792 /**
793 * @todo seems like we should loop through these yes/nos are something...
794 */
795
796 $wpDAV = WPDIRAUTH_VERSION;
797
798 echo <<<________EOS
799 <div class="wrap">
800 <h2>Directory Authentication Options</h2>
801 <form method="post" id="dir_auth_options">
802 <p class="submit"><input type="submit" name="dirAuthOptionsSave" value="Update Options »" /></p>
803 <fieldset class="options">
804 <legend>WordPress Settings</legend>
805 <ul>
806 <li>
807 <label for="dirAuthEnable"><strong>Enable Directory Authentication?</strong></label>
808 <br />
809 <input type="radio" name="dirAuthEnable" value="1" $tEnable /> Yes
810 <input type="radio" name="dirAuthEnable" value="0" $fEnable /> No
811 <br />
812 <strong>Note 1</strong>: Users created in WordPress are not affected by your directory authentication settings.
813 <br />
814 <strong>Note 2</strong>: You will still be able to login with standard WP users if the LDAP server(s) go offline.
815 </li>
816 <li>
817 <label for="dirAuthRequireSsl"><strong>Require SSL Login?</strong></label>
818 <br />
819 <input type="radio" name="dirAuthRequireSsl" value="1" $tWpSsl/> Yes
820 <input type="radio" name="dirAuthRequireSsl" value="0" $fWpSsl/> No
821 <br />
822 <em>Force the WordPress login screen to require encryption (SSL, https:// URL)?</em>
823 </li>
824 <li>
825 <label for="dirAuthAutoRegistration"><strong>Automatically Register Authenticated Users?</strong></label>
826 <p style="max-width:800px; font-style: italic; margin: 0 0 5px 0;">If a user authenticates successfully, but does not already have an account for the site, should wpDirAuth automatically create a new user
827 account for the authenticated user, and assign them to the lowest possible role? Note that this setting has no affect if you are using
828 <a href="#dirAuthGroups">Authentication Groups</a>.</p>
829 <input type="radio" name="dirAuthAutoRegistration" value="1" $strYesAutoRegister /> Yes
830 <input type="radio" name="dirAuthAutoRegistration" value="0" $strNoAutoRegister /> No
831
832 </li>
833 </ul>
834 </fieldset>
835 <fieldset class="options">
836 <legend>Directory Settings</legend>
837 <ul>
838 <li>
839 <label for="dirAuthEnableSsl"><strong>Enable SSL Connectivity?</strong></label>
840 <br />
841 <select id="dirAuthEnableSsl" name="dirAuthEnableSsl">
842 <option value="0" $strNoSSL>No SSL Connectivity</option>
843 <option value="1" $strSSL>Use SSL (ldaps)</option>
844 <option value="2" $strTLS>Use TLS</option>
845 </select>
846 <br />
847 <em>Use encryption (TLS, SSL, ldaps:// URL) when WordPress connects to the directory server(s)?</em>
848 </li>
849 <li>
850 <label for="dirAuthControllers"><strong>Directory Servers (Domain Controllers)</strong></label>
851 <br />
852 <input type="text" name="dirAuthControllers" value="$controllers" size="40"/><br />
853 <em>The DNS name or IP address of the directory server(s).</em><br />
854 <strong>NOTE:</strong> Separate multiple entries by a comma and/or alternate ports with a colon (eg: my.server1.org, my.server2.edu:387).
855 Unfortunately, alternate ports will be ignored when using LDAP/SSL, because of <a href="http://ca3.php.net/ldap_connect">the way</a> PHP handles the protocol.
856
857 </li>
858 <li>
859 <label for="dirAuthFilter"><strong>Account Filter</strong></label>
860 <br />
861 <input type="text" name="dirAuthFilter" value="$filter" size="40"/>
862 (Defaults to <em>$defaultFilter</em>)
863 <br />
864 <em>What LDAP field should we search the username against to locate the user's profile after successful login?</em>
865 </li>
866 <li>
867 <label for="dirAuthAccountSuffix"><strong>Account Suffix</strong></label>
868 <br />
869 <input type="text" name="dirAuthAccountSuffix" value="$accountSuffix" size="40" /><br />
870 <em>Suffix to be automatically appended to the username if desired. e.g. @domain.com</em><br />
871 <strong>NOTE:</strong> Changing this value will cause your existing directory users to have new accounts created the next time they login.
872 </li>
873 <li>
874 <label for="dirAuthBaseDn"><strong>Base DN</strong></label>
875 <br />
876 <input type="text" name="dirAuthBaseDn" value="$baseDn" size="40"/><br />
877 <em>The base DN for carrying out LDAP searches.</em>
878 </li>
879 <li>
880 <label for="dirAuthPreBindUser"><strong>Bind DN</strong></label>
881 <br />
882 <input type="text" name="dirAuthPreBindUser" value="$preBindUser" size="40"/><br />
883 <em>Enter a valid user account/DN to pre-bind with if your LDAP server does not allow anonymous profile searches, or requires a user with specific privileges to search.</em>
884 </li>
885 <li>
886 <label for="dirAuthPreBindPassword"><strong>Bind Password</strong></label>
887 <br />
888 <input type="password" name="dirAuthPreBindPassword" value="" size="40"/><br />
889 <em>Enter a password for the above Bind DN if a value is needed.</em><br />
890 <strong>Note 1</strong>: this value will be stored in clear text in your WordPress database.<br />
891 <strong>Note 2</strong>: Simply clear the Bind DN value if you wish to delete the stored password altogether.
892 </li>
893 <li>
894 <label for="dirAuthPreBindPassCheck"><strong>Confirm Password</strong></label>
895 <br />
896 <input type="password" name="dirAuthPreBindPassCheck" value="" size="40"/><br />
897 <em>Confirm the above Bind Password if you are setting a new value.</em>
898 </li>
899 <li>
900 <label for="dirAuthGroups"><strong>Authentication Groups</strong></label><br />
901 <input type="text" name="dirAuthGroups" id="dirAuthGroups" size="40" value="$strAuthGroups" /><br />
902 <em>Enter each group CN that the user must be a member of in order to authenticate.</em> <br />
903 <strong>NOTE:</strong> Separate multiple CNs by a comma.
904 </li>
905 </ul>
906 </fieldset>
907 <fieldset class="options">
908 <legend>Branding Settings</legend>
909 <ul>
910 <li>
911 <label for="dirAuthInstitution"><strong>Institution Name</strong></label>
912 <br />
913 <input type="text" name="dirAuthInstitution" value="$institution" size="40" />
914 <br />
915 <em>Name of your institution/company. Displayed on the login screen.</em>
916 </li>
917
918 <li>
919 <label for=""><strong>Marketing name for Institutional Single-Sign-On ID</strong></label>
920 <br />
921 <input type="text" name="dirAuthMarketingSSOID" value="$strMarketingSSOID" id="dirAuthMarketingSSOID" size="40" />
922 <br />
923 <em>How your institution/company refers to the single-sign-on ID you use.</em>
924 </li>
925 <li>
926 <label for="dirAuthLoginScreenMsg"><strong>Login Screen Message</strong></label>
927 <br />
928 <textarea name="dirAuthLoginScreenMsg" cols="40" rows="3">$loginScreenMsg</textarea>
929 <br />
930 <em>Displayed on the login screen, underneath the username/password fields.</em><br />
931 <strong>Note</strong>: Some HTML allowed: $allowedHTML
932 </li>
933 <li>
934 <label for="dirAuthChangePassMsg"><strong>Password Change Message</strong></label>
935 <br />
936 <textarea name="dirAuthChangePassMsg" cols="40" rows="3">$changePassMsg</textarea>
937 <br />
938 <em>Displayed wherever user passwords can be changed, for directory users only.</em><br />
939 <strong>Note</strong>: Some HTML allowed: $allowedHTML
940
941 </li>
942 <li>
943 <label for="dirAuthTOS"><strong>Terms of Services Agreement</strong></label>
944 <br />
945 <input type="radio" name="dirAuthTOS" value="1" $tTOS/> Yes
946 <input type="radio" name="dirAuthTOS" value="0" $fTOS/> No
947 <br />
948 <em>Ask directory users to agree to terms of services that you link to in the message above?</em><br />
949 <strong>Note</strong>: Checkbox disappears once checked, date of agreement is stored and users are no longer prompted.
950 </li>
951 </ul>
952 </fieldset>
953 <p class="submit"><input type="submit" name="dirAuthOptionsSave" value="Update Options »" /></p>
954 </form>
955 <p>Powered by $wpDARef.</p>
956 </div>
957________EOS;
958 }
959
960
961 /**
962 * Adds the `Directory Auth.` menu entry in the Wordpress Admin section, and the `Add Directory Authenticated User` to the Users menu
963 * Also activates the wpDirAuth config panel as a callback function.
964 *
965 * @uses wpDirAuth_optionsPanel
966 * @uses wpDirAuth_add_user_panel
967 */
968 function wpDirAuth_addMenu()
969 {
970 if (function_exists('add_options_page')) {
971 $strWpAdminPage = add_options_page(
972 'Directory Authentication Options',
973 'Directory Auth.',
974 'manage_options',
975 basename(__FILE__),
976 'wpDirAuth_optionsPanel'
977 );
978
979 //$strWpAdminPanel is here in case we want to add a contextual help panel later
980 }
981 }
982
983
984 /**
985 * Extending WP's login_form.
986 * Enforces the admin defined SSL login preferences and adds a directory
987 * login related message to the standard WP login screen.
988 *
989 * @uses WPDIRAUTH_DEFAULT_LOGINSCREENMSG
990 */
991 function wpDirAuth_loginFormExtra()
992 {
993 if (get_site_option('dirAuthEnable')) {
994
995 if (isset($_SERVER['SCRIPT_URI']) && preg_match('|^http|',$_SERVER['SCRIPT_URI'])) {
996 $selfURL = $_SERVER['SCRIPT_URI'];
997 }
998 else {
999 /**
1000 * $_SERVER['SCRIPT_URI'] seems to be unavilable in some PHP
1001 * installs, and $_SERVER['REQUEST_URI'] and $_SERVER['PHP_SELF']
1002 * have been known to sometimes have the same issue.
1003 * Thanks to Todd Beverly for helping out with this one. :)
1004 * @see http://wordpress.org/support/topic/129814?replies=27#post-605423
1005 */
1006 $selfURL = sprintf(
1007 'http%s://%s%s',
1008 (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 's' : ''),
1009 $_SERVER['HTTP_HOST'],
1010 (isset($_SERVER['REQUEST_URI'])
1011 ? $_SERVER['REQUEST_URI']
1012 : $_SERVER["SCRIPT_NAME"].'?'.$_SERVER['QUERY_STRING'])
1013 );
1014 }
1015
1016 //_log('contents of selfurl: '.$selfURL);
1017
1018
1019 if (get_site_option('dirAuthRequireSsl') && (!preg_match('|^https|',$selfURL))) {
1020 $sslURL = str_replace('http://','https://',$selfURL);
1021
1022 $refreshJS = '<script type="text/javascript">'."\n".'top.location.href=\''.$sslURL.'\';'."\n".'</script>" />';
1023 $refreshMeta = '<meta http-equiv="refresh" content="0;url='.$sslURL.'" />';
1024 $refreshMsg = 'Please access the <a href="'.$sslURL.'">encrypted version</a> of this page.';
1025
1026 if (headers_sent()) {
1027 echo $refreshJS.$refreshMeta.'<p>'.$refreshMsg.'</p></form></div></html>';
1028 }
1029 else {
1030 @ob_end_clean();
1031 if (!@header('Location:'.$sslURL)) {
1032 echo '<html><head>'.$refreshJS.$refreshMeta.'</head>'
1033 . '<body>'.$refreshMsg.'</body></html>';
1034 }
1035 }
1036
1037 exit;
1038 }
1039
1040 $dirAuthInstitution = stripslashes(get_site_option('dirAuthInstitution'));
1041 if (!$dirAuthInstitution) $dirAuthInstitution = __('Directory');
1042
1043 $loginScreenMsg = stripslashes(get_site_option('dirAuthLoginScreenMsg'));
1044 if (!$loginScreenMsg) $loginScreenMsg = __(sprintf(
1045 WPDIRAUTH_DEFAULT_LOGINSCREENMSG,
1046 get_site_option('dirAuthInstitution')
1047 ));
1048
1049 echo '
1050 <style>.wpDirAuthMsg a, .wpDirAuthMsg a:visited {color: #ebcd4e;}</style>
1051 <p class="wpDirAuthMsg">'.$loginScreenMsg.'</p>
1052 ';
1053 }
1054 }
1055
1056
1057 /**
1058 * Extending WP's show_password_fields.
1059 * Displays the directory password change message in profile.php and user.php.
1060 *
1061 * @return boolean Return format as expected by WP's show_password_fields()
1062 *
1063 * @uses WPDIRAUTH_DEFAULT_CHANGEPASSMSG
1064 */
1065 function wpDirAuth_hidePassFields()
1066 {
1067 global $profileuser, $userdata;
1068
1069 $editUserIsDirUser = get_user_meta($profileuser->ID, 'wpDirAuthFlag',true);
1070
1071 if (!$editUserIsDirUser) {
1072 return true;
1073 }
1074 else {
1075 // Editing directory user profile, show password msg
1076 $message = stripslashes(get_site_option('dirAuthChangePassMsg'));
1077 if (!$message) {
1078 $message = __(sprintf(
1079 WPDIRAUTH_DEFAULT_CHANGEPASSMSG,
1080 stripslashes(get_site_option('dirAuthInstitution'))
1081 ));
1082 }
1083
1084 if (get_site_option('dirAuthTOS')) {
1085 // TOS option is ON
1086 if (($TOSDate = get_user_meta($profileuser->ID, 'wpDirAuthTOS', true)) === '') {
1087 if ($userdata->ID == $profileuser->ID) {
1088 // Only show TOS acceptance checkbox to the owner of the profile.
1089 $message .= '</p><p class="desc">'
1090 . '<input type="checkbox" name="wpDirAuthTOS" value="1" style="width:15px; height:15px;" /> '
1091 . __('Accept terms of services.')
1092 . '</p><p class="desc">';
1093 }
1094 else {
1095 // Show generic message to other admins.
1096 $message .= '</p><p class="desc">'
1097 . __('User has not yet agreed to the terms of services.')
1098 . '</p><p class="desc">';
1099 }
1100 }
1101 else {
1102 // Show TOS acceptance date
1103 $message .= '</p><p class="desc">'
1104 . __('Terms of services accepted on')
1105 . ' '.$TOSDate
1106 . '</p><p class="desc">';
1107 }
1108 }
1109
1110 echo '<fieldset><legend>'
1111 . __('Directory Password Update')
1112 . '</legend><p class="desc">'
1113 . $message
1114 . '</p></fieldset>';
1115
1116 return false;
1117 }
1118 }
1119
1120
1121 /**
1122 * Extending WP's profile_update.
1123 * Saves the TOS acceptance if sent.
1124 *
1125 * @param integer $userID Sent by WP profile_update action
1126 * @return boolean Return format as expected by WP's profile_update()
1127 */
1128 function wpDirAuth_profileUpdate($userID){
1129 if (isset($_POST['wpDirAuthTOS']) && intval($_POST['wpDirAuthTOS']) === 1) {
1130 update_user_meta($userID, 'wpDirAuthTOS', date('Y-m-d H:i:s'));
1131 }
1132 return true;
1133 }
1134
1135
1136 /**
1137 * WP's wp_authenticate overwrite.
1138 * Processes the directory login and creates a new user on first access.
1139 *
1140 * @param string $username Login form username.
1141 * @param string $password Login form password
1142 * @return WP_Error|WP_User WP_User object if login successful, otherwise WP_Error object.
1143 *
1144 * @uses wpDirAuth_makeCookieMarker
1145 * @uses wpDirAuth_auth
1146 *
1147 * @see http://codex.wordpress.org/Pluggable_Functions
1148 */
1149 function wp_authenticate($username, $password)
1150 {
1151 //echo 'authenticating';exit;
1152 $boolRestoreBlog = false;
1153 if(defined('WPDIRAUTH_MULTISITE') && WPDIRAUTH_MULTISITE){
1154 //echo 'I should switch blogs!';exit;
1155 global $blog_id;
1156 $intOriginalBlog = $blog_id;
1157 switch_to_blog(1); //switch to the parent blog
1158 $boolRestoreBlog = true;
1159 }
1160 /**
1161 * @desc wp-hack for some reason, this function is being called even when a user just goes to the login page. added the next 3 lines so that
1162 * if the user arrives via $_GET, then we simply tell them to login
1163 */
1164 if($_SERVER['REQUEST_METHOD'] != 'POST'){
1165 if($boolRestoreBlog) restore_current_blog();
1166 return new WP_Error('incorrect_method',__('<strong>Please Login</strong>'));
1167 }
1168
1169 if (!$username) {
1170 if($boolRestoreBlog) restore_current_blog();
1171 return new WP_Error('empty_username', __('<strong>Login Error</strong>:
1172 The username field is empty.'));
1173 }
1174
1175 if (!$password) {
1176 if($boolRestoreBlog) restore_current_blog();
1177 return new WP_Error('empty_password', __('<strong>Login Error</strong>:
1178 The password field is empty.'));
1179 }
1180
1181 $enable = get_site_option('dirAuthEnable');
1182 $cookieMarker = get_site_option('dirAuthCookieMarker');
1183 $boolAutoRegister= (bool)get_site_option('dirAuthAutoRegister');
1184
1185 if (!$cookieMarker) {
1186 $cookieMarker = wpDirAuth_makeCookieMarker();
1187 }
1188
1189 /**
1190 * Get the login object. We will use it for first user insertion or when the
1191 * directory auth option is not activated.
1192 */
1193 $login = get_user_by('login',$username);
1194 $loginUserIsDirUser = (false !== $login) ? get_user_meta($login->ID, 'wpDirAuthFlag',true) : 0;
1195
1196 if (!$enable && $loginUserIsDirUser) {
1197 /*
1198 * Existing directory user, but directory access has now been disabled.
1199 */
1200 if($boolRestoreBlog) restore_current_blog();
1201 do_action( 'wp_login_failed', $username );
1202 return new WP_Error('login_disabled',__('<strong>Directory Login Error</strong>:
1203 Sorry, but the site administrators have disabled
1204 directory access in this WordPress install.'));
1205 }
1206 elseif ($enable) {
1207 /**
1208 * Directory auth == true
1209 */
1210
1211 if (!$login && $boolAutoRegister) {
1212 /**
1213 * No existing account record found, autoregister is on, try dir auth
1214 */
1215 $userData = wpDirAuth_auth($username,$password);
1216
1217 if ( !is_wp_error($userData) ) {
1218 /**
1219 * Passed directory signin, so create a new WP user
1220 */
1221
1222 $userLogin = sanitize_user($username);
1223 $userEmail = apply_filters('user_registration_email', $userData['email']);
1224
1225 if (username_exists($userLogin)) {
1226 /*
1227 * Username exists.
1228 */
1229 if($boolRestoreBlog) restore_current_blog();
1230 do_action( 'wp_login_failed', $username );
1231 return new WP_Error('username_exists',__('<strong>Directory Login Error</strong>:
1232 Could not create a new WP user account
1233 because the directory username <strong>' . htmlentities($userLogin,ENT_QUOTES,'UTF-8') . '</strong> is already
1234 registered on this site.'));
1235 } elseif (email_exists($userEmail)) {
1236 /*
1237 * Email exists.
1238 */
1239 if($boolRestoreBlog) restore_current_blog();
1240 do_action( 'wp_login_failed', $username );
1241 return new WP_Error('email_exists',__('<strong>Directory Login Error</strong>:
1242 Could not create a new WP account because
1243 the email <strong>' . htmlentities($userEmail,ENT_QUOTES,'UTF-8') . '</strong> is
1244 already registered with this site.'));
1245 } else {
1246 if(defined('WPDIRAUTH_MULTISITE') && WPDIRAUTH_MULTISITE && isset($boolRestoreBlog) && $boolRestoreBlog){
1247 restore_current_blog();
1248 }
1249
1250 if ($userID = wp_create_user($userLogin, $password, $userEmail)) {
1251 $userData['ID'] = $userID;
1252 $tmpAr = explode('@',$userData['email']);
1253 $userData['nickname'] = str_replace('.','_',$tmpAr[0]);
1254 $userData['display_name'] = $userData['first_name'].' '.$userData['last_name'];
1255 unset($userData['email']);
1256
1257 wp_update_user($userData);
1258 update_user_meta($userID, 'wpDirAuthFlag', 1);
1259 wpDirAuth_remove_password_nag($userID);
1260 //if($boolRestoreBlog) restore_current_blog();
1261 return new WP_User($userID);
1262 } else {
1263 /*
1264 * Unknown error.
1265 */
1266 //if($boolRestoreBlog) restore_current_blog();
1267 do_action( 'wp_login_failed', $username );
1268 return new WP_Error('creation_unknown_error',__('<strong>Directory Login Error</strong>:
1269 Could not create a new user account.
1270 Unknown error. [user: ' . htmlentities($userLogin,ENT_QUOTES,'UTF-8') . ', email: ' . htmlentities($userEmail,ENT_QUOTES,'UTF-8') . ']'));
1271 }
1272 }
1273 } else {
1274 /*
1275 * Did not pass dir auth, and no login present in WP
1276 */
1277 if($boolRestoreBlog) restore_current_blog();
1278 do_action( 'wp_login_failed', $username );
1279 return $userData;
1280 }
1281 } else {
1282
1283 /*
1284 * Dealing with an existing WP account
1285 */
1286 if (!$loginUserIsDirUser) {
1287 /*
1288 * WP-only user
1289 */
1290 if ( wp_check_password($password, $login->user_pass, $login->ID) ) {
1291 /*
1292 * WP user, password okay.
1293 */
1294 if($boolRestoreBlog) restore_current_blog();
1295 return new WP_User($login->ID);
1296 } else {
1297 /*
1298 * WP user, wrong pass
1299 */
1300 if($boolRestoreBlog) restore_current_blog();
1301 do_action( 'wp_login_failed', $username );
1302 return new WP_Error('incorrect_password',__('<strong>WordPress Login Error</strong>:
1303 Incorrect password.'));
1304 }
1305 } else {
1306 /**
1307 * Directory user, try ldap binding
1308 */
1309 $userData = wpDirAuth_auth($username,$password);
1310
1311 if ( !is_wp_error($userData) ) {
1312 /*
1313 * Directory user, password okay.
1314 */
1315 wpDirAuth_remove_password_nag($login->ID);
1316 if($boolRestoreBlog) restore_current_blog();
1317 return new WP_User($login->ID);
1318 }
1319 else {
1320 /*
1321 * Directory user, wrong pass
1322 */
1323 if($boolRestoreBlog) restore_current_blog();
1324 do_action( 'wp_login_failed', $username );
1325 return $userData;
1326 }
1327 }
1328 }
1329 }
1330 else {
1331 /**
1332 * Directory auth == false
1333 */
1334 if (!$login || ($login->user_login != $username) ) {
1335 /**
1336 * No existing account record found
1337 */
1338 if($boolRestoreBlog) restore_current_blog();
1339 do_action( 'wp_login_failed', $username );
1340 return new WP_Error('failed_login',__('<strong>WordPress Login Error</strong>:
1341 Could not authenticate user.
1342 Please check your credentials.'));
1343 }
1344 else {
1345 /*
1346 * Found an existing WP account.
1347 */
1348 if ( wp_check_password($password, $login->user_pass, $login->ID) ) {
1349 /*
1350 * WP user, password okay.
1351 */
1352 if($boolRestoreBlog) restore_current_blog();
1353 return new WP_User($login->ID);
1354 }
1355 else {
1356 /*
1357 * WP user, wrong pass
1358 */
1359 if($boolRestoreBlog) restore_current_blog();
1360 do_action( 'wp_login_failed', $username );
1361 return new WP_Error('incorrect_password',__('<strong>WordPress Login Error</strong>:
1362 Incorrect password.'));
1363 }
1364 }
1365 }
1366 }
1367
1368
1369 /**
1370 * WordPress wp_setcookie overwrite.
1371 * Sets the WP session cookies.
1372 *
1373 * @param string $username Login form username.
1374 * @param string $password Login form password
1375 * @param boolean $already_md5 Has the pswd been double-hashed already?
1376 * @param string $home
1377 * @param string $siteurl
1378 * @param boolean $remember
1379 * @return void
1380 *
1381 * @uses wpDirAuth_makeCookieMarker
1382 *
1383 * @deprecated
1384 *
1385 * @see http://codex.wordpress.org/Pluggable_Functions
1386 */
1387 function wpsetauthcookie($intUserId, $remember = false, $boolSecure = true)
1388 {
1389 global $wpdb;
1390
1391 /**
1392 * Try to locate the user's record and define if it is an existing directory user
1393 */
1394 $login = get_user_by('id',$intUserId);
1395 //$login = $wpdb->get_row('SELECT ID FROM $wpdb->users WHERE user_login = '$username'');
1396 $loginUserIsDirUser = ($login) ? get_usermeta($login->ID, 'wpDirAuthFlag') : 0;
1397
1398 /**
1399 * Get wpsDirAuth options
1400 */
1401 $enable = get_site_option('dirAuthEnable');
1402 $cookieMarker = get_site_option('dirAuthCookieMarker');
1403
1404 if (!$cookieMarker) {
1405 $cookieMarker = wpDirAuth_makeCookieMarker();
1406 }
1407
1408 /**
1409 * Set the password hash cookie
1410 */
1411 if (($enable) && ($loginUserIsDirUser)) {
1412 $password = md5($username).md5($cookieMarker);
1413 }
1414 else {
1415 if (!$already_md5) {
1416 $password = md5( md5($password) ); // Double hash the password in the cookie.
1417 }
1418 }
1419
1420 /**
1421 * Updated WP remember me option for directory users to only be
1422 * remembered for 1 hour so that institutional passwords are not
1423 * overly endangered when accessing the blog from a public terminal.
1424 */
1425 if ( $remember ){
1426 $duration = ($loginUserIsDirUser) ? strtotime('1 hour') : strtotime('6 months');
1427 $expire = time() + $duration;
1428 }
1429 else {
1430 $expire = 0;
1431 }
1432
1433 /**
1434 * The rest of the logic is from the original WP wp_setcookie
1435 * function, from /wp-inlcudes/pluggable.php version 2.2.2
1436 */
1437 if ( empty($home) )
1438 $cookiepath = COOKIEPATH;
1439 else
1440 $cookiepath = preg_replace('|https?://[^/]+|i', '', $home . '/' );
1441
1442 if ( empty($siteurl) ) {
1443 $sitecookiepath = SITECOOKIEPATH;
1444 $cookiehash = COOKIEHASH;
1445 } else {
1446 $sitecookiepath = preg_replace('|https?://[^/]+|i', '', $siteurl . '/' );
1447 $cookiehash = md5($siteurl);
1448 }
1449
1450 setcookie(USER_COOKIE, $username, $expire, $cookiepath, COOKIE_DOMAIN);
1451 setcookie(PASS_COOKIE, $password, $expire, $cookiepath, COOKIE_DOMAIN);
1452
1453 if ( $cookiepath != $sitecookiepath ) {
1454 setcookie(USER_COOKIE, $username, $expire, $sitecookiepath, COOKIE_DOMAIN);
1455 setcookie(PASS_COOKIE, $password, $expire, $sitecookiepath, COOKIE_DOMAIN);
1456 }
1457
1458 }
1459
1460 /**
1461 * Prints data on a variable into a comments block in the source code of a page. Used for debugging purposes only.
1462 *
1463 * @param mixed $mxdVar
1464 * @param string $strMsg
1465 */
1466 function wpDirAuthPrintDebug($mxdVar,$strMsg){
1467 echo PHP_EOL,'<!-- ',$strMsg,': ',PHP_EOL,var_export($mxdVar,true),PHP_EOL,'-->',PHP_EOL;
1468 }
1469
1470 /**
1471 * Removes the "you're using a default password"" nag for dirauth accounts
1472 *
1473 * @param integer $userID
1474 * @return void
1475 */
1476 function wpDirAuth_remove_password_nag($userID){
1477 if(get_user_option('default_password_nag',$userID)){
1478 update_user_option($userID, 'default_password_nag', false, true);
1479 }
1480 }
1481
1482 /**
1483 * Retrieves values given in WPDIRAUTH_LDAP_RETURN_KEYS from a valid, bound LDAP connection
1484 *
1485 * @param resource $rscConnection verified LDAP connection resource
1486 * @param string $strBaseDn
1487 * @param string $strFilterQuery
1488 * @param mixed $rscReult if LDAP search was already performed. default null
1489 * @return mixed WP_Error object if there was an error encountered, otherwise an array of user details
1490 *
1491 * @TODO right now it's actually coded such that what is returned is always the same, even if you change the keys in WPDIRAUTH_LDAP_RETURN_KEYS. Rewrite it so
1492 * it will dynamically retrieve the values. idea is that WPDIRAUTH_LDAP_RETURN_KEYS would become an associative array of key names to return => LDAP keys to retrieve.
1493 * WPDIRAUTH_LDAP_RETURN_KEYS = serialize(array(
1494 * 'first_name' =>'givenname',
1495 * 'last_name' =>'sn',
1496 * 'email' =>'mail'
1497 * ));
1498 * of course, we'll need to somehow require at least the email key since we need that one in order to add the user.
1499 */
1500 function wpDirAuth_retrieveUserDetails($rscConnection,$strBaseDn,$strFilterQuery,$rscResult=false){
1501 //now that we have a valid connection and are bound, we need to find the user.
1502
1503 if(is_bool($rscResult) && false === $rscResult){
1504 $rscResult = ldap_search($rscConnection,$strBaseDn,$strFilterQuery,unserialize(WPDIRAUTH_LDAP_RETURN_KEYS));
1505 }
1506
1507 /**
1508 * At this point, we will no longer use $strFilterQuery EXCEPT in the output of an error message. To ensure we dont introduce an injection point, we will encode any
1509 * html entities that might be present.
1510 */
1511 $strFilterQuery = htmlentities($strFilterQuery,ENT_QUOTES,'UTF-8');
1512
1513 if(!$rscResult){
1514 return new WP_Error ('noprofile_search', __('Directory authentication initially succeeded, but no valid profile was found (search procedure).')
1515 ." [$strFilter]");
1516 } else {
1517 $aryUserDetails = @ldap_get_entries($rscConnection, $rscResult);
1518
1519 $intCount = intval($aryUserDetails['count']);
1520 if ($intCount < 1) {
1521 return new WP_Error ('noprofile_getentries', __('Directory authentication initially succeeded, but no valid profile was found ("get entries" procedure).')
1522 ." [$strFilterQuery]");
1523 } elseif ($intCount > 1) {
1524 return new WP_Error ('not_unique', __('Directory authentication initially succeeded, but the username you sent is not a unique profile identifier.')
1525 . " [$strFilterQuery]");
1526 } else {
1527 $strEmail = isset($aryUserDetails[0]['mail'][0]) ? $aryUserDetails[0]['mail'][0] : '';
1528
1529 $strLastName = isset($aryUserDetails[0]['sn'][0]) ? $aryUserDetails[0]['sn'][0] : '';
1530
1531 $strFirstName = isset($aryUserDetails[0]['givenname'][0]) ? $aryUserDetails[0]['givenname'][0] : '';
1532
1533 return array(
1534 'email' => $strEmail,
1535 'last_name' => $strLastName,
1536 'first_name' => $strFirstName
1537 );
1538 }
1539 }
1540 }
1541
1542 /**
1543 * Handles connecting to LDAP and performing a search for the given SSOID
1544 *
1545 * @param string $strSSOID
1546 * @return mixed WP_Error object on failure, array of user details on success
1547 * @TODO this function shares a LOT with wpDirAuth_auth. see if you cant combine them some more
1548 */
1549 function wpDirAuth_ConnectAndLookupUser($strSSOID){
1550 $boolFound = false;
1551
1552 $strBaseDn = get_site_option('dirAuthBaseDn');
1553 $strPreBindUser = get_site_option('dirAuthPreBindUser','');
1554 $strPreBindPassword = get_site_option('dirAuthPreBindPassword','');
1555 $strAccountSuffix = get_site_option('dirAuthAccountSuffix');
1556 $strFilter = get_site_option('dirAuthFilter');
1557 $intEnableSSL = get_site_option('dirAuthEnableSsl');
1558
1559 if ($strAccountSuffix) $strSSOID .= $strAccountSuffix;
1560
1561 if (!$strFilter || empty($strFilter)) $strFilter = WPDIRAUTH_DEFAULT_FILTER;
1562
1563 $strFilterQuery = "($strFilter=$strSSOID)";
1564
1565 $aryControllers = wpDirAuth_shuffleControllers(explode(',', get_site_option('dirAuthControllers')));
1566
1567 if(is_wp_error($aryControllers)){
1568 return $aryControllers; //there werent any controllers to connect to
1569 }
1570
1571 /**
1572 * @todo if we get a successful connection, cant we break out of the loop before we go through binding and a search? Or is it possible that one DC in the
1573 * list might not allow anonymous searching and/or the pre-bind user/pass isnt valid on one of them and we need to try the next in the list?
1574 */
1575 foreach($aryControllers as $strDC){
1576 $rscConnection = wpDirAuth_establishConnection($strDC,$intEnableSSL);
1577 if(is_wp_error($rscConnection)){
1578 return $rscConnection; //tls failed to start on the DC
1579 }
1580
1581 if(!wpDirAuth_bindTest($rscConnection,$strPreBindUser,$strPreBindPassword,$strBaseDn)){
1582 return new WP_Error('login_failed',__('<strong>Error Connecting to LDAP Server</strong><p>'
1583 . 'There was an error connecting to your LDAP server ('. htmlentities($strDC,ENT_QUOTES,'UTF-8').'). Please see the LDAP error message below for troubleshooting:</p>'
1584 . ldap_error($rscConnection)));
1585 }
1586
1587 //successfully bound, now we need to get the user details
1588 return wpDirAuth_retrieveUserDetails($rscConnection,$strBaseDn,$strFilterQuery);
1589 }
1590 }
1591
1592 /**
1593 * Checks to make sure the user doesnt already exist and that the email associated with a SSOID isnt already in use in the blog, and if not, adds the user.
1594 *
1595 * @param string $strSSOID Single Sign On ID
1596 * @param string $strRole Role chosen to give the new user
1597 * @return mixed array of user details on success or WP_Error object on failure
1598 */
1599 function wpDirAuth_add_new_user($strSSOID,$strRole,$intBlogID = 0){
1600 /**
1601 * We need to see if the user name already exists. if not, then we need to see if the email address is already in use, if not, then we need to try and look
1602 * up the user. then if we actually found something, then we'll add them into wordpress
1603 */
1604 $strSSOID = sanitize_user($strSSOID);
1605 $intBlogID = is_int($intBlogID) ? $intBlogID : (int) $intBlogID; //just to make sure
1606
1607 if(username_exists($strSSOID)){
1608 echo '<p>user already exists</p>';
1609 return new WP_Error('username_exists',__('<p>Could not create a new Wordpress account because the directory username <strong>'
1610 . htmlentities($strSSOID,ENT_QUOTES,'UTF-8') . '</strong> is already registered on this site.</p>'));
1611 }
1612
1613 //we'll have to go ahead and look them up in LDAP in order to check their email address
1614 $aryUserDetails = wpDirAuth_ConnectAndLookupUser($strSSOID);
1615 if(is_wp_error($aryUserDetails)){
1616 return $aryUserDetails;
1617 }
1618 $strUserEmail = apply_filters('user_registration_email', $aryUserDetails['email']);
1619
1620 if(email_exists($strUserEmail)){
1621 echo '<p>Email address already exists</p>';
1622 return new WP_Error('email_exists',__('Could not create a new WP account because the email <strong>'
1623 . htmlentities($strUserEmail,ENT_QUOTES,'UTF-8') . '</strong> is already registered with this site.'));
1624 }
1625
1626 $aryUserDetails['user_pass'] = mt_rand();//we're going to store a random password in WP since directory users will never use it to log in anyway'
1627 $aryUserDetails['user_login'] = $strSSOID;
1628 $aryUserDetails['user_email'] = $aryUserDetails['email'] = $strUserEmail;
1629 /**
1630 * @TODO ask Stephen why he's replacing .'s with _'s in the user name of the email address. Does nickname not allow spaces?
1631 */
1632 $tmpAr = explode('@',$aryUserDetails['email']);
1633 $aryUserDetails['nickname'] = str_replace('.','_',$tmpAr[0]);
1634 $aryUserDetails['display_name'] = $aryUserDetails['first_name'].' '.$aryUserDetails['last_name'];
1635 $aryUserDetails['role'] = $strRole;
1636
1637 /**
1638 * Switch to the blog we want to insert the user into
1639 */
1640 if(defined('MULTISITE') && MULTISITE && function_exists('switch_to_blog')) switch_to_blog($intBlogID);
1641 $intUserID = wp_insert_user($aryUserDetails);
1642
1643 if(!is_int($intUserID)){
1644 return new WP_Error('createuser_failed',__('For an unknow reason, WP failed to create a new user.'
1645 .' Failure occurred at line ' . __LINE__ . ' in the function ' . __FUNCTION__ . ' in the file ' . basename(__FILE__) . '.'));
1646 }
1647
1648 $aryUserDetails['ID'] = $intUserID;
1649 update_user_meta($intUserID, 'wpDirAuthFlag', 1);
1650 wpDirAuth_remove_password_nag($intUserID);
1651
1652 //for situations where an admin is adding a user from a site edit screen
1653 /**
1654 if($intBlogID != 0){
1655 add_user_to_blog($intBlogID,$intUserID,$strRole);
1656 } */
1657
1658 if(defined('MULTISITE') && MULTISITE && function_exists('switch_to_blog')) restore_current_blog();
1659 return $aryUserDetails;
1660 }
1661
1662 /**
1663 * Loops through the WP_Error object and prints out the error messages it contains
1664 *
1665 * @param object $objError
1666 * @return void
1667 */
1668 function wpDirAuth_print_error_messages($objError){
1669 echo PHP_EOL,'<div class="error">',WPDIRAUTH_ERROR_TITLE,'<ul>',PHP_EOL;
1670 foreach($objError->get_error_messages() as $strErrMsg){
1671 echo '<li>',$strErrMsg,'</li>',PHP_EOL;
1672 }
1673 echo '</ul></div>',PHP_EOL;
1674 }
1675
1676 /**
1677 * Constructs the message to be displayed when a new user has been added successfully
1678 *
1679 * @param string $strSSOID User's Single Sign On ID
1680 * @param integer $strUserID user's wordpress user ID
1681 * @param array Data on the sites and roles that the user has been added to
1682 * @return string
1683 * @uses wpDirAuth_determine_A_or_An
1684 *
1685 */
1686 function wpDirAuth_construct_success_msg($strSSOID,$strUserID,$arySitesData,$strExtraMsg=''){
1687 //$arySitesData = array('blogname','role','siteurl');
1688 $strMsg = '<div id="message" class="updated">
1689 <p>Just created user <strong><a href="user-edit.php?user_id=%d">%s</a></strong> as %s. %s
1690 </div>';
1691
1692 $strSiteMessage = '%s for site <a href="%s">%s</a>';
1693 $arySiteMsgParts = array();
1694 foreach($arySitesData as $arySiteData){
1695 $arySiteMsgParts[] = sprintf($strSiteMessage,$arySiteData['role'],$arySiteData['siteurl'],$arySiteData['blogname']);
1696 }
1697
1698 return sprintf($strMsg,$strUserID,$strSSOID,implode($arySiteMsgParts,', '),$strExtraMsg);
1699 }
1700
1701 /**
1702 * Just determines if the word $strWord should be prefaced with 'a' or 'an'.
1703 * Yea, i know it's picky, but I work with editors who complain about this type of stuff all the time =P
1704 *
1705 * @param string $strWord
1706 * @return string
1707 */
1708 function wpDirAuth_determine_A_or_An($strWord){
1709 $strAorAn = 'a';
1710 if(in_array(substr($strWord,0,1),array('a','e','i','o','u'))){
1711 $strAorAn .= 'n';
1712 }
1713
1714 return $strAorAn;
1715 }
1716
1717 /**
1718 * Adds contextual help to the Add Dir Auth page under the Users menu
1719 *
1720 */
1721 function wpDirAuth_add_user_contextual_help(){
1722 _wpdirauth_log(__FUNCTION__,'function called!');
1723 $strMarketingSSOID = get_site_option('dirAuthMarketingSSOID','Username');
1724 $objScreen = get_current_screen();
1725
1726
1727
1728 $strContent = '<p>' . __('To add a directory authenticated user from your institution to your site, fill in the form on this screen. If you’re not sure which role to assign, you can use the link below to review the different roles and their capabilities. Here is a basic overview of roles:') . '</p>' .
1729 '<ul>' .
1730 '<li>' . __('Administrators have access to all the administration features.') . '</li>' .
1731 '<li>' . __('Editors can publish posts, manage posts as well as manage other people’s posts, etc.') . '</li>' .
1732 '<li>' . __('Authors can publish and manage their own posts.') . '</li>' .
1733 '<li>' . __('Contributors can write and manage their posts but not publish posts or upload media files.') . '</li>' .
1734 '<li>' . __('Subscribers can read comments/comment/receive newsletters, etc.') . '</li>' .
1735 '</ul>' .
1736 '<p>' . __('The user\'s insitutional single-sign-on ID (e.g. ' . $strMarketingSSOID .') will become the user\'s Wordpress username.') . '</p>' .
1737 '<p>' . __('New users will receive an email letting them know they’ve been added as a user for your site.') . '</p>' .
1738 '<p>' . __('Remember to click the Add User button at the bottom of this screen when you are finished.') . '</p>' .
1739 '<p><strong>' . __('For more information:') . '</strong></p>' .
1740 '<p>' . __('<a href="http://wordpress.org/support/" target="_blank">Support Forums</a>') . '</p>';
1741
1742 $objScreen->add_help_tab(array(
1743 'id'=>'wpdirauth-help',
1744 'title'=>'wpDirAuth Help',
1745 'content'=>$strContent
1746
1747 ));
1748 }
1749
1750 /**
1751 * Processes and outputs the Add Dir Auth user form.
1752 * @return void
1753 */
1754 function wpDirAuth_add_user_panel(){
1755 _log('WPDIRAUTH - function ' . __FUNCTION__ . ' activated. ');
1756 /**
1757 * Still needed?
1758 */
1759 global $id;
1760 /**
1761 * get_current_screen()->id = site-users-network will let us know if we are on the sites,edit,user tab
1762 */
1763 $strScreenID = get_current_screen()->id;
1764 /**
1765 * Are we running in a wordpress network and in the network area?
1766 */
1767 $boolIsNetworkAdminScreen = (is_network_admin() && $strScreenID != 'site-users-network') ? true : false;
1768 /**
1769 * How do we refer to their SSOID?
1770 */
1771 $strMarketingSSOID = get_site_option('dirAuthMarketingSSOID','Username');
1772
1773 $strReferer = wpDirAuth_get_referer();
1774
1775 /**
1776 * defaults
1777 */
1778 $strWpDirAuthSSOID = '';
1779 $strWpDirAuthRole = '';
1780 $boolConfirmationEmail = true;
1781 $objErrors = new WP_Error;
1782 $strSuccess = '';
1783 if($boolIsNetworkAdminScreen){
1784 $arySitesData = wpDirAuth_retrieve_multisite_blog_data();
1785 }
1786
1787 if($_POST){
1788 if(wp_verify_nonce($_POST['_wpnonce_add-da-user'],'add-da-user')){
1789 /**
1790 * We gots a problem.... if they've checked all the boxes and chosen roles but forgot to enter the pawprint (it happens, you did
1791 * it yourself!) then we cant rebuild the list of which sites were checked/not checked later because we're jumping out before
1792 * we get to the point where we build that data.
1793 */
1794 if(isset($_POST['ssoid']) && $_POST['ssoid'] == ''){
1795 $objErrors->add('blank_ssoid',__('<p>'.$strMarketingSSOID.' can not be left blank.</p>'));
1796 } else {
1797 $strWpDirAuthSSOID = wpDirAuth_sanitize($_POST['ssoid']);
1798
1799 if($boolIsNetworkAdminScreen && $strReferer != 'site-users.php'){
1800 $arySitesAndRoles = array();
1801 $aryValidSiteIDs = array_keys($arySitesData);
1802 $aryValidRoles = array_keys(get_editable_roles());
1803 _log('contents of the post in function ' . __FUNCTION__.' at line ' . __LINE__ . ':'.PHP_EOL.var_export($_POST,true));
1804 //we SHOULD have at least one site set.
1805 for($i=0;$i<count($arySitesData);++$i){
1806 $strPostSite = 'site'.$i;
1807 $intCountPostSite = count($_POST[$strPostSite]);
1808 /**
1809 * We need to make sure that the site param is set, that it's an array and that it contains at least one element, but no more than
1810 * two
1811 */
1812 if(isset($_POST[$strPostSite]) && is_array($_POST[$strPostSite]) && $intCountPostSite>0 && $intCountPostSite<3){
1813 if($intCountPostSite == 1 && is_string(current($_POST[$strPostSite]))){
1814 /**
1815 * If the array has only one element, then this site wasnt selected as one we want to add the user to. but we
1816 * need, for simplicity sake, to make the array contain two elements before we do input validation
1817 */
1818 $_POST[$strPostSite] = array('',current($_POST[$strPostSite]));
1819 /**
1820 * Since we know that the array has two elements, we'll test to make sure the siteid is valid'
1821 */
1822 } elseif(!is_numeric($_POST[$strPostSite][0]) || !in_array($_POST[$strPostSite][0],$aryValidSiteIDs)) {
1823 $_POST[$strPostSite][0] = '';
1824 }
1825
1826 /**
1827 *
1828 */
1829 if(!in_array($_POST[$strPostSite][1],$aryValidRoles)){
1830 $_POST[$strPostSite][1] = '';
1831 }
1832
1833 /**
1834 * If we now have non-empty values for both elements, we'll add them to our array to be used for inserting the user into sites
1835 */
1836 if($_POST[$strPostSite][0] != '' && $_POST[$strPostSite][1] != ''){
1837 $arySitesAndRoles[$i] = array('blog_id'=>$_POST[$strPostSite][0],'role'=>$_POST[$strPostSite][1]);
1838 }
1839
1840 }
1841 }
1842
1843 }
1844
1845 $strWpDirAuthRole = (isset($_POST['role']) && in_array($_POST['role'],array_keys(get_editable_roles()))) ? $_POST['role'] : get_site_option('default_role');
1846 $intBlogID = (isset($_POST['id']) && is_numeric($_POST['id'])) ? intval($_POST['id']) : '';
1847 if(isset($_POST['noconfirmation']) && $_POST['noconfirmation'] == 1) $boolConfirmationEmail = false;
1848
1849 if(!isset($arySitesAndRoles) || !$boolIsNetworkAdminScreen){
1850 $aryUserData = wpDirAuth_add_new_user($strWpDirAuthSSOID,$strWpDirAuthRole,$intBlogID);
1851 _log('adding a standard user (' . $strWpDirAuthSSOID .')from either inside a site, or from the edit section of a site');
1852 _log('user data from newly added user is : ' . PHP_EOL . var_export($aryUserData,true) . PHP_EOL);
1853 } elseif(count($arySitesAndRoles)<1) {
1854 $aryUserData = new WP_Error('no_site_role_selected','<p>You will need to select at least one site to add this user to.</p>');
1855 } else {
1856 $aryUserData = wpDirAuth_add_new_user_to_multi_sites($strWpDirAuthSSOID,$arySitesAndRoles);
1857 _log('adding a user (' . $strWpDirAuthSSOID .')from the network Add Dir Auth user section');
1858 }
1859
1860 if(is_wp_error($aryUserData)){
1861 //foreach($objErrors->)
1862
1863 //$mxdErrors = $aryUserData;
1864 $objErrors->add($aryUserData->get_error_code(),$aryUserData->get_error_message(),$aryUserData->get_error_data());
1865 } else {
1866 $arySitesAddedTo = array();
1867 if(isset($arySitesAndRoles) && count($arySitesAndRoles)!=0){
1868 foreach($arySitesAndRoles as $arySiteData){
1869 $arySitesAddedTo[] = array(
1870 'blogname'=>$arySitesData[$arySiteData['blog_id']],
1871 'aoran' =>wpDirAuth_determine_A_or_An($arySiteData['role']),
1872 'role' =>$arySiteData['role'],
1873 'siteurl' =>get_site_url($arySiteData['blog_id'],'','https')
1874
1875 );
1876 }
1877 } else {
1878 $arySitesAddedTo[] = array(
1879 'blogname' =>get_site_option('blogname'),
1880 'aoran' =>wpDirAuth_determine_A_or_An($strWpDirAuthRole),
1881 'role' =>$strWpDirAuthRole,
1882 'siteurl' =>site_url()
1883 );
1884 }
1885
1886 /**
1887 * ok, the admin has just successfully added a user to a site from the sites->edit->users tab. Since we cant seem to
1888 * redirect them back to the screen automatically, let's give them a link to go back.'
1889 */
1890 if($strReferer == 'site-users.php' && $boolIsNetworkAdminScreen){
1891 $strReturnToURL = wp_get_referer();
1892 $strExtraMessage = '<a href="'.$strReturnToURL.'">Return to the User tab</a> of the '. $arySitesData[$intBlogID] . ' site.';
1893 } else {
1894 $strExtraMessage = '';
1895 }
1896
1897 $strSuccess = wpDirAuth_construct_success_msg($strWpDirAuthSSOID,$aryUserData['ID'],$arySitesAddedTo,$strExtraMessage);
1898 _log('for user ' . $strWpDirAuthSSOID . ', added them to ' . var_export($arySitesAddedTo,true).'.');
1899
1900 if($boolConfirmationEmail){
1901 foreach($arySitesAddedTo as $arySiteAddedToData){
1902 $strMsg = sprintf(WPDIRAUTH_EMAIL_NEWUSER_NOTIFY,$arySiteAddedToData['blogname'],$arySiteAddedToData['aoran'],$arySiteAddedToData['role'],$strMarketingSSOID,$strWpDirAuthSSOID,$arySiteAddedToData['siteurl'].'/wp-login.php');
1903 wp_mail($aryUserData['email'],'['.$arySiteAddedToData['blogname'].'] You\'ve been added!',$strMsg);
1904 }
1905 }
1906
1907 //reset back to defaults
1908 $strWpDirAuthSSOID = '';
1909 $strWpDirAuthRole = '';
1910 $boolConfirmationEmail = true;
1911 }
1912 }
1913 } else {
1914 $objErrors->add('invalid-nonce',__('Invalid nonce value'));
1915 }
1916 }
1917
1918
1919
1920
1921 ?>
1922 <h3>Add New Directory Authentication User</h3>
1923 <?php
1924 if(count($objErrors->errors) != 0) {
1925 wpDirAuth_print_error_messages($objErrors);
1926 } elseif($strSuccess != ''){
1927 echo $strSuccess;
1928 }
1929 ?> <p><?php _e('Add a directory authenticated user to this site/network'); ?></p>
1930 <p><?php _e('Please note: Your LDAP/AD instance must allow anonymous profile searches, or you must provide a pre-bind account/password in the <a href="options-general.php?page='.basename(__FILE__).'">Directory Auth settings page.</a>') ?></p>
1931
1932 <form action="<?php if(isset($strScreenID) && $strScreenID == 'site-users-network') echo 'users.php?page=wpDirAuth'; ?>" method="post" name="adddauser" id="createuser" class="add:users: validate"<?php do_action('user_new_form_tag');?>>
1933 <?php
1934 if(isset($id) && $id != '' && is_multisite()){
1935 echo '<input type="hidden" name="id" value="',$id,'" />',PHP_EOL;
1936 }
1937 ?>
1938 <input name="action" type="hidden" value="add-da-user" />
1939 <?php wp_nonce_field( 'add-da-user', '_wpnonce_add-da-user' ); ?>
1940 <table class="form-table">
1941 <tr class="form-field form-required">
1942 <th scope="row">
1943 <label for="ssoid"><?php _e($strMarketingSSOID.'/SSOID'); ?> <span class="description"><?php _e('(required)'); ?></span></label>
1944 </th>
1945 <td>
1946 <input name="ssoid" type="text" id="ssoid" value="<?php echo esc_attr($strWpDirAuthSSOID); ?>" aria-required="true" />
1947 </td>
1948 </tr>
1949 <?php if($boolIsNetworkAdminScreen):?>
1950 <tr class="form-field">
1951 <th scope="row"><label for="blogs"><?php _e('Site');?></label></th>
1952 <th><label for="role"><?php _e('Role');?></label></th>
1953 </tr>
1954 <?php
1955
1956 $i=0;
1957
1958 foreach($arySitesData as $intSiteID=>$strSiteName){
1959 $boolChecked = false;
1960
1961 if(isset($arySitesAndRoles[$i])){
1962 $aryFormSiteData = $arySitesAndRoles[$i];
1963 } elseif(isset($_POST['site'.$i])) {
1964 $aryFormSiteData = $_POST['site'.$i];
1965 } else {
1966 $aryFormSiteData = array();
1967 }
1968
1969 _log('aryFormSiteData at line ' . __LINE__ . ': ' . var_export($aryFormSiteData,true));
1970
1971 /**
1972 * We are working on the assumption that there are either ALWAYS two elements in aryformSiteData or the array is empty.
1973 * If the first element in the array isnt empty, then the current site needs to be checked
1974 */
1975 if(reset($aryFormSiteData) != ''){
1976 $boolChecked = true;
1977 }
1978
1979 /**
1980 * If the last element (eg second, role) isnt empty, then we want to select it from the list
1981 */
1982 $strRoleSelected = (end($aryFormSiteData) != '') ? current($aryFormSiteData) : '';
1983
1984 echo '<tr>
1985 <td>
1986 <input name="site'.$i.'[]" value="'.$intSiteID.'" id="blog_'.$intSiteID.'" type="checkbox"';
1987
1988 if($boolChecked) echo ' checked="checked"';
1989
1990 echo ' /> '.$strSiteName.'
1991 </td>
1992 <td>
1993 <select name="site'.$i.'[]" id="role_'.$intSiteID.'">';
1994 wp_dropdown_roles($strRoleSelected);
1995 echo PHP_EOL,'</select>
1996 </td>
1997 </tr>';
1998 ++$i;
1999 }
2000
2001 ?>
2002 <?php else: ?>
2003 <tr class="form-field">
2004 <th scope="row"><label for="role"><?php _e('Role'); ?></label></th>
2005 <td><select name="role" id="role">
2006 <?php
2007 $strCurrentRole = empty($strWpDirAuthRole) ? get_site_option('default_role') : $strWpDirAuthRole;
2008 wp_dropdown_roles($strCurrentRole);
2009 ?>
2010 </select>
2011 </td>
2012 </tr>
2013 <?php endif;?>
2014 <tr>
2015 <th scope="row"><label for="noconfirmation"><?php _e('Skip Confirmation Email') ?></label></th>
2016 <td><label for="noconfirmation"><input type="checkbox" name="noconfirmation" id="noconfirmation" value="1" <?php checked(!$boolConfirmationEmail); ?> /> <?php _e( 'Add the user without sending them a confirmation email.' ); ?></label></td>
2017 </tr>
2018 </table>
2019
2020 <?php submit_button( __( 'Add New User '), 'primary', 'createuser', true, array( 'id' => 'createusersub' ) ); ?>
2021
2022 </form>
2023
2024 <?php
2025 } // end wpDirAuth_add_user_panel() function
2026
2027 /**
2028 * Add custom WordPress actions
2029 *
2030 * @uses wpDirAuth_addMenu
2031 * @uses wpDirAuth_loginFormExtra
2032 * @uses wpDirAuth_profileUpdate
2033 * @uses wpDirAuth_add_user_contextual_help
2034 */
2035 if (function_exists('add_action')) {
2036 /**
2037 *ok, if we are in a multisite, we want to add the settings for wpDirAuth
2038 * to the Network Admin area, but NOT the child sites. Otherwise, for
2039 * single sites, we need to add an admin panel
2040 *
2041 * Also for MUTLISITE, we need to add extra add user pages since we can
2042 * add users in multiple areas when we are running a MULTISITE
2043 */
2044 if(WPDIRAUTH_MULTISITE){
2045 add_action('network_admin_menu','wpDirAuth_addNetworkMenu');
2046 add_action('show_network_site_users_add_new_form', 'wpDirAuth_add_user_panel');
2047 //add_action('network_site_users_after_list_table', 'wpDirAuth_add_user_panel');
2048 add_action('network_admin_menu','wpDirAuth_network_adduser');
2049 } else {
2050 add_action('admin_menu', 'wpDirAuth_addMenu');
2051 }
2052
2053 /**
2054 * EVERYSITE, regardless of multi or not, needs the ability to add users
2055 */
2056 add_action('admin_menu','wpDirAuth_add_users_page');
2057
2058 add_action('login_form', 'wpDirAuth_loginFormExtra');
2059 add_action('profile_update', 'wpDirAuth_profileUpdate');
2060 add_action('lostpassword_form',function ()
2061 {
2062 echo get_site_option('dirAuthChangePassMsg');
2063 });
2064
2065 add_action('admin_head-users_page_'.basename(__FILE__,'.php'),'wpDirAuth_add_user_contextual_help');
2066 }
2067
2068
2069
2070 /**
2071 * Add custom WordPress filters
2072 *
2073 * @uses wpDirAuth_hidePassFields
2074 */
2075 if (function_exists('add_filter')) {
2076 add_filter('show_password_fields', 'wpDirAuth_hidePassFields');
2077 add_filter('allow_password_reset','wpDirAuth_allowPasswordReset',10,2);
2078 add_filter('auth_cookie_expiration','wpDirAuth_cookieExpire',10,3);
2079 }
2080
2081 /**
2082 * Callback function to add wpdirauth add user panel to users panel
2083 *
2084 * 20160426 - something changed in wordpress roles & caps as of 4.4.2. role create_users no longer allows admins who
2085 * do not posses super-admin privelege to see the menu item. changing the cap to add_users allows it to function
2086 * but i dont know WHY, which I *do* *not* *like*.
2087 */
2088 function wpDirAuth_add_users_page(){
2089 if(function_exists('add_users_page')){
2090 add_users_page(
2091 'Add Directory Authentication Users',
2092 'Add Directory Authenticated User',
2093 'add_users',
2094 basename(__FILE__),
2095 'wpDirAuth_add_user_panel'
2096 );
2097 }
2098 }
2099
2100 /**
2101 *
2102 */
2103 function wpDirAuth_allowPasswordReset($bool,$intUserID)
2104 {
2105 _wpdirauth_log($bool,'contents of bool',false,array('line'=>__LINE__,'file'=>__FILE__));
2106 _wpdirauth_log($intUserID,'contents of user id',false,array('line'=>__LINE__,'file'=>__FILE__));
2107 $mxdReturn = true;
2108
2109 $boolDirAuthEnabled = get_site_option('dirAuthEnable');
2110 _wpdirauth_log($boolDirAuthEnabled,'contents of boolDirAuthEnabled',false,array('line'=>__LINE__,'file'=>__FILE__));
2111 if(1 == $boolDirAuthEnabled){
2112 $intDirAuthUser = get_user_meta($intUserID,'wpDirAuthFlag',true);
2113 _wpdirauth_log($intDirAutherUser,'contents of intDirAuthUser',false,array('line'=>__LINE__,'file'=>__FILE__));
2114 if(1 == $intDirAuthUser){
2115
2116 $strPasswordReset = '<h3>Error: Unable to reset password</h3>';
2117 $strPasswordReset .= get_site_option('dirAuthChangePassMsg');
2118 add_filter('login_message',function(){return '';});
2119 $mxdReturn = new WP_Error('invalid_username',$strPasswordReset);
2120 }
2121 }
2122
2123 return $mxdReturn;
2124 }
2125
2126 function wpDirAuth_cookieExpire($intExpireTime,$intUserID,$boolRemember)
2127 {
2128 //_wpdirauth_log($intUserID,'the user id');
2129 //_wpdirauth_log($intExpireTime,'the expiration time');
2130 //_wpdirauth_log($boolRemember,'whether or not to remember the user');
2131
2132 if(1 == get_user_meta($intUserID,'wpDirAuthFlag',true)){
2133 /**
2134 * @todo make this an option in the wpSettings
2135 */
2136 $intExpireTime = 60 * 60;
2137 _wpdirauth_log($intExpireTime,'user is dirauth user so this is how long will set the cookie for');
2138 }
2139
2140 return $intExpireTime;
2141
2142 }
2143
2144 /**
2145 * TESTING
2146 */
2147 function wpDirAuth_network_adduser(){
2148 add_submenu_page('users.php','Add Directory Authenticated User','Add Dir Auth User','add_users','wpDirAuth','wpDirAuth_add_user_panel');
2149 }
2150
2151 function wpDirAuth_addNetworkMenu(){
2152 $strWpDirAuthPage = add_submenu_page('settings.php','wpDirAuth Directory Authentication Options','wpDirAuth','manage_options','wpDirAuth_optionsPanel','wpDirAuth_optionsPanel');
2153 //$strWpDirAuthPage is here in case we want to add a contextual help panel later
2154 }
2155
2156 function wpDirAuth_retrieve_multisite_blog_data(){
2157 global $wpdb;
2158 $aryBlogData = array();
2159 $arySites = $wpdb->get_results($wpdb->prepare('SELECT blog_id FROM '. $wpdb->prefix . 'blogs ORDER BY blog_id'));
2160 _log('result of arySites: '.PHP_EOL.var_export($arySites,true).PHP_EOL);
2161 foreach($arySites as $objSiteData){
2162 $intSiteKey = $objSiteData->blog_id;
2163 $strTableName = $wpdb->prefix;
2164 $strTableName .= ($intSiteKey != 1) ? $intSiteKey . '_' : '';
2165 $strTableName .= 'options';
2166 /**
2167 * Wonder if I should do wpdb->get_var here instead?
2168 */
2169 $arySiteData = $wpdb->get_results($wpdb->prepare("SELECT option_value from $strTableName WHERE option_name = 'blogname'"),ARRAY_A);
2170 $aryBlogData[$intSiteKey] = (isset($arySiteData[0]['option_value']) && $arySiteData[0]['option_value'] != '') ? $arySiteData[0]['option_value'] : 'Unable to Retrive Blog Name';
2171 }
2172 _log('aryBlogData:'.PHP_EOL.var_export($aryBlogData,true).PHP_EOL);
2173 return $aryBlogData;
2174 }
2175
2176 /**
2177 * put your comment there...
2178 *
2179 * @param string $strSSOID
2180 * @param array $aryBlogIDsRoles should be a nested array with the sub-array containing the keys 'blog_id' and 'role'
2181 * @return mixed WP_Error or user details upon success.
2182 */
2183 function wpDirAuth_add_new_user_to_multi_sites($strSSOID,$aryBlogIDsRoles){
2184 $mxdFirstElement = reset($aryBlogIDsRoles);//reset back to the beginning
2185 if(count($aryBlogIDsRoles)<1 || !$mxdFirstElement){
2186 return new WP_Error('blog_id_role_missing',__('<p>Could not create a new Wordpress account because data on blog id and role is '
2187 . 'missing. Function: ' . __FUNCTION__.', line ' . __LINE__.'.</p>'));
2188 } else {
2189
2190 $aryFirstSite = current($aryBlogIDsRoles);
2191 $aryUserData = wpDirAuth_add_new_user($strSSOID,$aryFirstSite['role'],$aryFirstSite['blog_id']);
2192 if(is_wp_error($aryUserData)){
2193 return $aryUserData;
2194 } else {
2195 //we already added for the first site
2196 unset($aryBlogIDsRoles[key($aryBlogIDsRoles)]);
2197 foreach($aryBlogIDsRoles as $arySiteDetails){
2198 add_user_to_blog($arySiteDetails['blog_id'],$aryUserData['ID'],$arySiteDetails['role']);
2199 }
2200 }
2201
2202 return $aryUserData;
2203 }
2204 }
2205
2206 function wpDirAuth_get_referer(){
2207 $strReferer = basename(wp_get_referer());
2208 if(strpos($strReferer,'?') !== FALSE){
2209 $aryRefererParts = explode('?',$strReferer);
2210 $strReferer = $aryRefererParts[0];
2211 }
2212
2213 return $strReferer;
2214 }
2215}
2216
2217register_activation_hook(__FILE__, 'wpDirAuth_activation');
2218
2219function wpDirAuth_activation($network_wide){
2220 if($network_wide){
2221 /**
2222 * Prior to v1.7.5, wpDirAuth options were stored in wp_options when
2223 * network activated instead of wp_sitemeta. To ensure that users dont
2224 * lose their settings when upgrading to 1.7.5 or newer, we'll check
2225 * to see if there are wpDirAuth options in wp_options when network
2226 * activating. If so, we'll copy them over to wp_sitemeta and then
2227 * delete them from wp_options
2228 */
2229 $mxdWpDirAuthEnable = get_option('dirAuthEnable');
2230 if(is_integer($mxdWpDirAuthEnable) && $mxdWpDirAuthEnable !== FALSE){
2231 foreach(unserialize(WPDIRAUTH_OPTIONS) as $strOption){
2232 update_site_option($strOption, get_site_option($strOption));
2233 delete_option($strOption);
2234 }
2235 }
2236 }
2237}
2238
2239if(!function_exists('_log')){
2240 /**
2241 * For logging debug messages into the debug log.
2242 *
2243 * @param mixed $message
2244 */
2245 function _log( $message, $boolBackTraced = false ) {
2246 _wpdirauth_log($message,null,$boolBackTraced);
2247 }
2248}
2249
2250if(!function_exists('_wpdirauth_log')){
2251 /**
2252 * For logging debug messages into the debug log.
2253 *
2254 * @param mixed $mxdVariable variable we need to debug
2255 * @param $strPrependMessage message to include
2256 * @param boolean $boolBackTraced
2257 * @param array $aryDetails details for doing a mini backtrace instead of the full thing
2258 *
2259 */
2260 function _wpdirauth_log( $mxdVariable, $strPrependMessage = null, $boolBackTraced = false, $aryDetails = array() ) {
2261 $boolBackTrace = false;
2262 /**
2263 * This is here so I can leave my debugging messages in the code but disable them from logging when out in
2264 * production.
2265 */
2266 $boolDoLog = false;
2267 if( WP_DEBUG === true && $boolDoLog){
2268 $strMessage = 'WPDIRAUTH: ';
2269
2270 if(count($aryDetails) > 0){
2271 if(isset($aryDetails['line'])){
2272 $strMessage .= 'At line number ' . $aryDetails['line'] . ' ';
2273 }
2274
2275 if(isset($aryDetails['func'])){
2276 $strMessage .= 'inside of function ' . $aryDetails['func'] . ' ';
2277 }
2278
2279 if(isset($aryDetails['file'])){
2280 $strMessage .= 'in file ' . $aryDetails['file'] .' ';
2281 }
2282
2283 $strMessage .= PHP_EOL;
2284 }
2285
2286 if(!is_null($strPrependMessage)) $strMessage .= $strPrependMessage.' ';
2287
2288 if( is_array( $mxdVariable ) || is_object( $mxdVariable ) ){
2289 $strMessage .= PHP_EOL . var_export($mxdVariable,true);
2290 } else {
2291 $strMessage .= $mxdVariable;
2292 }
2293
2294 if($boolBackTrace && $boolBackTraced){
2295 $aryBackTrace = debug_backtrace();
2296
2297 $strMessage .= PHP_EOL.'Contents of backtrace:'.PHP_EOL.var_export($aryBackTrace,true).PHP_EOL;
2298 }
2299
2300 error_log($strMessage);
2301 }
2302 }
2303}