Advertisement
gilzow

wpDirAuth 1.7.16 beta

Apr 27th, 2016
420
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 103.18 KB | None | 0 0
  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. /*
  58. PLUGIN META INFO FOR WORDPRESS LISTINGS
  59. Plugin Name: wpDirAuth
  60. Plugin URI:  http://wpdirauth.gilzow.com/
  61. Description: 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.
  66. Version: 1.7.15
  67. Author: Paul Gilzow
  68. Author URI: http://gilzow.com/
  69. */
  70.  
  71. /**
  72.  * wpDirAuth version.
  73.  */
  74. define('WPDIRAUTH_VERSION', '1.7.15');
  75.  
  76. /**
  77.  * wpDirAuth signature.
  78.  */
  79. define('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.  */
  84. define('WPDIRAUTH_DEFAULT_FILTER', 'samAccountName');
  85.  
  86. /**
  87.  * Default login screen message.
  88.  */
  89. define('WPDIRAUTH_DEFAULT_LOGINSCREENMSG', '%s members can login directly using their institutional password.');
  90.  
  91. /**
  92.  * Default password change message.
  93.  */
  94. define('WPDIRAUTH_DEFAULT_CHANGEPASSMSG', 'To change a %s password, please refer to the official institutional password policy.');
  95.  
  96. /**
  97.  * Allowed HTML (messages)
  98.  */
  99. define('WPDIRAUTH_ALLOWED_TAGS', '<a><strong><em><p><ul><ol><li>');
  100.  
  101. define('WPDIRAUTH_ERROR_TITLE',__('<strong>Directory Authentication Error</strong>: '));
  102.  
  103. define('WPDIRAUTH_LDAP_RETURN_KEYS',serialize(array('sn', 'givenname', 'mail')));
  104.  
  105. define('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.  */
  110. define('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.  */
  115. define('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.  
  134. if (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. }
  224. else {
  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 &raquo;" /></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 &nbsp;
  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 &nbsp;
  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 &nbsp;
  830.                             <input type="radio" name="dirAuthAutoRegistration" value="0" $strNoAutoRegister /> No &nbsp;
  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 &nbsp;
  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 &raquo;" /></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&#8217;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&#8217;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&#8217;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 ' />&nbsp;&nbsp;'.$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.  
  2217. register_activation_hook(__FILE__, 'wpDirAuth_activation');
  2218.  
  2219. function 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.  
  2239. if(!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.  
  2250. if(!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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement