e107inc/e107

View on GitHub
e107_handlers/login.php

Summary

Maintainability
B
6 hrs
Test Coverage
D
69%
<?php
/*
 * e107 website system
 *
 * Copyright (C) 2008-2013 e107 Inc (e107.org)
 * Released under the terms and conditions of the
 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
 *
 * Login handler
 *
*/


if (!defined('e107_INIT')) { exit; }


// require_once(e_HANDLER.'user_handler.php'); //shouldn't be necessary
e107::includeLan(e_LANGUAGEDIR.e_LANGUAGE.'/lan_login.php');

// TODO - class constants
define ('LOGIN_TRY_OTHER', 2);        // Try some other authentication method
define ('LOGIN_CONTINUE',1);        // Not rejected (which is not exactly the same as 'accepted') by alt_auth
define ('LOGIN_ABORT',-1);            // Rejected by alt_auth
define ('LOGIN_BAD_PW', -2);        // Password wrong
define ('LOGIN_BAD_USER', -3);        // User not in DB
define ('LOGIN_BAD_USERNAME', -4);    // Username format unacceptable (e.g. too long)
define ('LOGIN_BAD_CODE', -5);        // Wrong image code entered
define ('LOGIN_MULTIPLE', -6);         // Error if multiple logins not allowed
define ('LOGIN_NOT_ACTIVATED', -7);    // User in DB, not activated
define ('LOGIN_BLANK_FIELD', -8);    // Username or password blank
define ('LOGIN_BAD_TRIGGER', -9);    // Rejected by trigger event
define ('LOGIN_BANNED', -10);        // Banned user attempting login
define ('LOGIN_CHAP_FAIL', -11);    // CHAP login failed
define ('LOGIN_DB_ERROR', -12);        // Error adding user to main DB

/**
 * TODO - use new user model, compact everything in max 2 classes
 */
class userlogin
{
    protected $e107;
    protected $userMethods;            // Pointer to user handler
    protected $userIP;                // IP address
    protected $lookEmail = false;    // Flag set if logged in using email address
    protected $userData = array();    // Information for current user
    protected $passResult = false;    // USed to determine if stored password needs update
    protected $testMode   = false;
    protected $secImageType = 'logcode';

    public function __construct()
    {
        $this->e107 = e107::getInstance();
        $this->userIP = e107::getIPHandler()->getIP();
        $this->userMethods = e107::getUserSession();
    }

    /**
     * @param $area
     * @return void
     */
    public function setSecureImageMode($area)
    {
        $modes = array(
            'admin' => 'admincode',
            'login' => 'logcode',
        //    'fpw'   => '',
        );

        $this->secImageType = varset($modes[$area],'not-a-pref');

    }

    /**
    # Class called when user attempts to log in
    #
    # @param string $username, $_POSTED user name
    # @param string $userpass, $_POSTED user password
    # @param $autologin - 'signup' - uses a specially encoded password - logs in if matches
    #                    - zero for 'normal' login
    #                    - non-zero sets the 'remember me' flag in the cookie
    ' @param string $response - response string returned by CHAP login (instead of password)
    # @return  boolean - FALSE on login fail, TRUE on login successful
    */
    public function login($username, $userpass, $autologin, $response = '', $noredirect = false)
    {
        $pref = e107::getPref();
        $tp = e107::getParser();
        $sql = e107::getDb();

        $e_event = e107::getEvent();
        $_E107 = e107::getE107();
        
        $username = trim($username);
        $userpass = trim($userpass);

        if($_E107['cli'] && ($username == ''))
        {
            return FALSE;
        }
        
        $forceLogin = ($autologin === 'signup');
        if(!$forceLogin && $autologin === 'provider') $forceLogin = 'provider';

        if(empty($username) || (empty($userpass) && empty($response) && $forceLogin !== 'provider'))
        {    // Required fields blank
            return $this->invalidLogin($username,LOGIN_BLANK_FIELD);
        }

//        $this->e107->admin_log->addEvent(4,__FILE__."|".__FUNCTION__."@".__LINE__,"DBG","User login",'IP: '.$fip,FALSE,LOG_TO_ROLLING);
//        $this->e107->check_ban("banlist_ip='{$this->userIP}' ",FALSE);            // This will exit if a ban is in force
        e107::getIPHandler()->checkBan("banlist_ip='{$this->userIP}' ",FALSE);            // This will exit if a ban is in force
        
        $autologin = intval($autologin);        // Will decode to zero if forced login
        $authorized = false;
        if (!$forceLogin && e107::isInstalled('alt_auth'))
        {
            $authMethod[0] = varset($pref['auth_method'], 'e107');        // Primary authentication method
            $authMethod[1] = varset($pref['auth_method2'], 'none');        // Secondary authentication method (if defined)
            $result = false;
            foreach ($authMethod as $key => $method)
            {
                if ($method == 'e107')
                {
                    if ($this->lookupUser($username, $forceLogin))
                    {
                        if ($this->checkUserPassword($username, $userpass, $response, $forceLogin) === TRUE)
                        {
                            $authorized = true;
                            $result = LOGIN_CONTINUE;        // Valid User exists in local DB
                        }
                        elseif(varset($pref['auth_badpassword'], TRUE))
                        {
                            $result = LOGIN_TRY_OTHER;
                            continue; // Should use alternate method for password auth
                        }
                        else 
                        {
                            return $this->invalidLogin($username,LOGIN_ABORT);
                        }
                    }
                }
                else
                {
                    if ($method != 'none')
                    {
                        $auth_file = e_PLUGIN.'alt_auth/'.$method.'_auth.php';
                        if (file_exists($auth_file))
                        {
                            require_once(e_PLUGIN.'alt_auth/alt_auth_login_class.php');
                            $al = new alt_login($method, $username, $userpass); 
                            $result = $al->loginResult; 
                            switch ($result)
                            {
                                case LOGIN_ABORT :
                                    return $this->invalidLogin($username,LOGIN_ABORT);
                                break;
                                case LOGIN_DB_ERROR :
                                    return $this->invalidLogin($username,LOGIN_DB_ERROR);
                                break;
                                case AUTH_SUCCESS:
                                    $authorized = true;
                                break;
                                case LOGIN_TRY_OTHER:
                                    if ($key === array_key_last($authMethod)) { 
                                        return $this->invalidLogin($username,LOGIN_ABORT);
                                    }
                                    continue 2;
                                break;
                            }
                        }
                    }
                }
                if ($result === LOGIN_CONTINUE)
                {
                    break;
                }
            }
        }

        $username = preg_replace("/\sOR\s|\=|\#/", "", $username);

        // Check secure image
        if (!$forceLogin && !empty($pref[$this->secImageType]) && extension_loaded('gd'))
        {
            if ($secImgResult = e107::getSecureImg()->invalidCode($_POST['rand_num'], $_POST['code_verify'])) // Invalid code
            {
                return $this->invalidLogin($username, LOGIN_BAD_CODE, $secImgResult);
            }

        }

        if (empty($this->userData))        // May have retrieved user data earlier
        {
            if (!$this->lookupUser($username, $forceLogin))
            {
                return false;        // User doesn't exist
            }
        }

        if ($authorized !== true && $this->checkUserPassword($username, $userpass, $response, $forceLogin) !== true)
        {
            return false;
        }


        // Check user status
        switch ($this->userData['user_ban'])
        {
            case USER_REGISTERED_NOT_VALIDATED : // User not fully signed up - hasn't activated account.
                return $this->invalidLogin($username, LOGIN_NOT_ACTIVATED);
            case USER_BANNED :        // User banned
                return $this->invalidLogin($username, LOGIN_BANNED,$this->userData['user_id']);
            case USER_VALIDATED :        // Valid user
                break;            // Nothing to do ATM
            case USER_EMAIL_BOUNCED:
                $bounceLAN      = LAN_LOGIN_36;
                $bounceMessage  =  $tp->lanVars($bounceLAN, $this->userData['user_email'],true );
                $bounceMessage  = str_replace(array('[',']'),array("<a href='".e_HTTP."usersettings.php'>","</a>"), $bounceMessage);

                e107::getMessage()->addWarning($bounceMessage, 'default', true);
                break;
            default :            // May want to pick this up
        }


        // User is OK as far as core is concerned
//        $this->e107->admin_log->addEvent(4,__FILE__."|".__FUNCTION__."@".__LINE__,"DBG","User login",'User passed basics',FALSE,LOG_TO_ROLLING);
        if (($this->passResult !== FALSE) && ($this->passResult !== PASSWORD_VALID))
        {  // May want to rewrite password using salted hash (or whatever the preferred method is) - $pass_result has the value to write
            // If login by email address also allowed, will have to write that value too
//              $sql->update('user',"`user_password` = '{$pass_result}' WHERE `user_id`=".intval($this->userData['user_id']));
            $reHashedPass = $this->userMethods->rehashPassword($this->userData,$userpass);
            if($reHashedPass !==false)
            {
                $log = e107::getLog();
                $auditLog = "User Password ReHashed";
                $log->user_audit(USER_AUDIT_LOGIN, $auditLog, $this->userData['user_id'], $this->userData['user_name']);
                $this->userData['user_password'] = $reHashedPass;
            }
        }


        $userpass = '';                // Finished with any plaintext password - can get rid of it




        $ret = $e_event->trigger("preuserlogin", $username);
        if ($ret != '')
        {
            return $this->invalidLogin($username,LOGIN_BAD_TRIGGER,$ret);
        }


        // Trigger events happy as well
        $user_id = $this->userData['user_id'];
        $user_name = $this->userData['user_name'];
        $user_admin = $this->userData['user_admin'];
        $user_email = $this->userData['user_email'];

        /* restrict more than one person logging in using same us/pw */
        if(!empty($pref['session_save_method']) && ($pref['session_save_method'] === 'db') && !empty($pref['disallowMultiLogin']) && !empty($user_id))
        {
            // logout any existing user of this account.
            $mLog = '';
            if($sql->delete('session', "session_user = ".$user_id))
            {
                $mLog = 'Dropped existing user session: #' . $user_id. " ".$username;
            }

            if($onlineIP = $sql->retrieve("online", "online_ip", "online_user_id='".$user_id.".".$user_name."'"))
            {
                $mLog .= ' ('. e107::getIpHandler()->ipDecode($onlineIP).')';
                $sql->delete('online', "online_user_id='".$user_id.".".$user_name."'");
            }

            if(!empty($mLog))
            {
                $this->logNote('LAN_ROLL_LOG_07', $mLog );
            }

        }
        elseif(!empty($pref['track_online']) && !empty($pref['disallowMultiLogin']) && !empty($user_id))
        {
            if($sql->select("online", "online_ip", "online_user_id='".$user_id.".".$user_name."'"))
            {
                return $this->invalidLogin($username, LOGIN_MULTIPLE, $user_id);
            }
        }




        // User login definitely accepted here

        if($ret = $e_event->trigger("user_validlogin", $user_id))
        {
            return false;
        }

        $cookieval = $this->validLogin($this->userData, $autologin);

        if($_E107['cli'])
        {
            return $cookieval;
        }


        if($noredirect)
        {
            return true;
        }

        $redir = e_REQUEST_URL;
        $class_list = $this->userMethods->addCommonClasses($this->userData, TRUE);
        //$redir = e_SELF;
        //if (e_QUERY) $redir .= '?'.str_replace('&amp;','&',e_QUERY);
        if (isset($pref['frontpage_force']) && is_array($pref['frontpage_force']))
        {    // See if we're to force a page immediately following login - assumes $pref['frontpage_force'] is an ordered list of rules
//          $log_info = "New user: ".$this->userData['user_name']."  Class: ".$this->userData['user_class']."  Admin: ".$this->userData['user_admin']."  Perms: ".$this->userData['user_perms'];
//          $this->e107->admin_log->addEvent(4,__FILE__."|".__FUNCTION__."@".__LINE__,"DBG","Login Start",$log_info,FALSE,FALSE);
            // FIXME - front page now supports SEF URLs - make a check here
            foreach ($pref['frontpage_force'] as $fk=>$fp)
            {
                if (in_array($fk,$class_list))
                {  // We've found the entry of interest
                    if (strlen($fp))
                    {
                        if (strpos($fp, 'http') === FALSE)
                        {
                            $fp = str_replace(e_HTTP, '', $fp);        // This handles sites in a subdirectory properly (normally, will replace nothing)
                            $fp = SITEURL.$fp;
                        }
                        //$redir = ((strpos($fp, 'http') === FALSE) ? SITEURL : '').$tp->replaceConstants($fp, TRUE, FALSE);
                        $redir = e107::getParser()->replaceConstants($fp, TRUE, FALSE);
        //                $this->e107->admin_log->addEvent(4,__FILE__."|".__FUNCTION__."@".__LINE__,"DBG","Redirect active",$redir,FALSE,FALSE);
                    }
                    break;
                }
            }
        }
        
        $redirPrev = e107::getRedirect()->getPreviousUrl();

        if($redirPrev)
        {
            e107::getRedirect()->redirect($redirPrev);
        }

        e107::getRedirect()->redirect($redir);
        exit();
    }


    /**
     * @return array
     */
    public function getUserData()
    {
        return $this->userData;
    }

    /**
     * Look up a user in the e107 database, according to the options set (for login name/email address)
     * Note: PASSWORD IS NOT VERIFIED BY THIS ROUTINE
     * @param string $username - as entered
     * @param boolean $forceLogin - TRUE if login is being forced from clicking signup link; normally FALSE
     * @return boolean TRUE if name exists, and $this->userData array set up
     *                   FALSE otherwise
     */
    protected function lookupUser($username, $forceLogin)
    {
        $pref = e107::getPref();
        $log = e107::getLog();

        $maxLength = varset($pref['loginname_maxlength'],30);

        /*
         * 2: Username/Email and Password
         * 1: Email and Password
         * 0: Username and Password
         */
        if(!empty($pref['allowEmailLogin'])) // Email login only
        {
            $maxLength = 254; // Maximum email length    
        }

        // Check username general format
        if (!$forceLogin && (strlen($username) > $maxLength)) // Error - invalid username
        {
            $auditLog = array('reason'=>'username longer than maxlength', 'maxlength'=> $maxLength, 'username'=>$username);
            $log->user_audit(USER_AUDIT_LOGIN, $auditLog, 0, $username);
            $this->invalidLogin($username,LOGIN_BAD_USERNAME);
            return FALSE;
        }

        $query = $this->getLookupQuery($username, $forceLogin);

        if (e107::getDb()->select('user', '*', $query) !== 1)     // Handle duplicate emails as well // Invalid user
        {
            $auditLog = array('reason'=>'query failed to return a result', 'query'=>$query, 'username'=>$username);
            $log->user_audit(USER_AUDIT_LOGIN, $auditLog, 0, $username);
            return $this->invalidLogin($username,LOGIN_BAD_USER);
        }

        // User is in DB here
        $this->userData = e107::getDb()->fetch();        // Get user info
        $this->userData['user_perms'] = trim($this->userData['user_perms']);
        $this->lookEmail = ($username == $this->userData['user_email']) ? 1 : 0;        // Know whether login name or email address used now
        
        return TRUE;
    }



    /**
     *    Generate a DB query to look up a user, dependent on the various login options supported.
     */
    public function getLookupQuery($username, $forceLogin, $dbAlias = '')
    {
        $pref = e107::getPref();
        $tp = e107::getParser();

        $username = preg_replace("/\sOR\s|\=|\#/", "", $username);
        
        if($forceLogin === 'provider')
        {
            return "{$dbAlias}`user_xup`='".$tp->toDB($username)."'";
        }

        $qry[0] = "{$dbAlias}`user_loginname`= '".$tp->toDB($username)."'";  // username only  (default)
        $qry[1] = "{$dbAlias}`user_email` = '".$tp->toDB($username)."'";   // email only
        $qry[2] = (strpos($username,'@') !== false ) ? "{$dbAlias}`user_loginname`= '".$tp->toDB($username)."'  OR {$dbAlias}`user_email` = '".$tp->toDB($username)."'" : $qry[0];  //username or email
        

        // Look up user in DB - even if email addresses allowed, still look up by user name as well - user could have specified email address for their login name
        $query = (!$forceLogin && varset($pref['allowEmailLogin'],0)) ? $qry[$pref['allowEmailLogin']] : $qry[0];
        return $query;
    }


    /**
     * Checks user password againt preferences set etc
     * Assumes that $this->userData array already set up
     *
     * @param string $username - the user name string as entered (might not relate to the intended user at this stage)
     * @param string $userpass - as entered
     * @param string $response - received string if CHAP used
     * @param boolean $forceLogin - TRUE if login is being forced from clicking signup link; normally FALSE
     * @return bool|string if valid password
     *           otherwise FALSE
     */
    protected function checkUserPassword($username, $userpass, $response, $forceLogin)
    {
        $pref = e107::getPref();
        $log = e107::getLog();
        
        if($forceLogin === 'provider') return true;
        /*
        if ($this->lookEmail && vartrue($pref['passwordEncoding']))
        {
            $tmp = e107::getArrayStorage()->unserialize($this->userData['user_prefs']);
            if(!$tmp && $this->userData['user_prefs']) $tmp = unserialize($this->userData['user_prefs']); // try old storage type
            $requiredPassword = varset($tmp['email_password'], $this->userData['user_password']);    // Use email-specific password if set. Otherwise, 'normal' one might work
            unset($tmp);
        }
        else
        {
            $requiredPassword = $this->userData['user_password'];
        }
        */

        // Now check password
        if ($forceLogin)
        {
            if (md5($this->userData['user_name'].$this->userData['user_password'].$this->userData['user_join']) != $userpass)
            {
                return $this->invalidLogin($username,LOGIN_BAD_PW);
            }
        }
        else
        {
            $session = e107::getSession();
            $gotChallenge = $session->is('challenge');
            //$aLogVal = "U: {$username}, P: ******, C: ".$session->get('challenge')." R:{$response} S: {$this->userData['user_password']} Prf: {$pref['password_CHAP']}/{$gotChallenge}";
            if ((($pref['password_CHAP'] > 0) && ($response && $gotChallenge) && ($response != $session->get('challenge'))) || ($pref['password_CHAP'] == 2))
            {  // Verify using CHAP
                  //$this->e107->admin_log->addEvent(4,__FILE__."|".__FUNCTION__."@".__LINE__,"DBG","CHAP login",$aLogVal, FALSE, LOG_TO_ROLLING);
                if (($pass_result = $this->userMethods->CheckCHAP($session->get('challenge'), $response, $username, $this->userData['user_password'])) === PASSWORD_INVALID)
                {
                    return $this->invalidLogin($username,LOGIN_CHAP_FAIL);
                }
            }
            else // Plaintext password
            {

                $login_name = ($this->lookEmail) ? $this->userData['user_loginname'] : $username;

                  $auditLog = array(
                    'type'              => (($this->lookEmail) ? 'email' : 'userlogin'),
                    'login_name'        => $login_name,
                //    'userpass'          => $userpass,
                    'pwdHash'           => $this->userData['user_password']
                );

                if (($pass_result = $this->userMethods->CheckPassword($userpass, $login_name, $this->userData['user_password'])) === PASSWORD_INVALID)
                {
                    $auditLog['result'] = intval($pass_result);
                    $log->user_audit(USER_AUDIT_LOGIN, $auditLog, $this->userData['user_id'], $this->userData['user_name']);
                    return $this->invalidLogin($username,LOGIN_BAD_PW);
                }

                $auditLog['result'] = intval($pass_result);

                $log->user_audit(USER_AUDIT_LOGIN, $auditLog, $this->userData['user_id'], $this->userData['user_name']);
            }


            $this->passResult = $pass_result;
        }

        return true;
    }


    /**
     * @return array
     */
    public function test()
    {

        $this->testMode = true;
        $errors = array(
            'LOGIN_TRY_OTHER'=> 2,        // Try some other authentication method
            'LOGIN_CONTINUE'=>1,        // Not rejected (which is not exactly the same as 'accepted') by alt_auth
            'LOGIN_ABORT'=>-1,            // Rejected by alt_auth
            'LOGIN_BAD_PW'=> -2,        // Password wrong
            'LOGIN_BAD_USER'=> -3,        // User not in DB
            'LOGIN_BAD_USERNAME'=> -4,    // Username format unacceptable (e.g. too long)
            'LOGIN_BAD_CODE'=> -5,        // Wrong image code entered
            'LOGIN_MULTIPLE'=> -6,         // Error if multiple logins not allowed
            'LOGIN_NOT_ACTIVATED'=> -7,    // User in DB=> not activated
            'LOGIN_BLANK_FIELD'=> -8,    // Username or password blank
            'LOGIN_BAD_TRIGGER'=> -9,    // Rejected by trigger event
            'LOGIN_BANNED'=> -10,        // Banned user attempting login
            'LOGIN_CHAP_FAIL'=> -11,    // CHAP login failed
            'LOGIN_DB_ERROR'=> -12,        // Error adding user to main DB
        );

        $ret = [];
        foreach($errors as $k=>$v)
        {
            $ret[] = $this->invalidLogin("John Smith", $v, 'Custom error text');
        //    echo "<h4>".$k."</h4>";
        //    $ret[] = e107::getMessage()->render();
        }

        return $ret;

    }

    /**
     * called to log the reason for a failed login.
     * @param $username
     * @param $reason
     * @param string $extra_text
     * @return boolean Currently always returns false - could return some other value
     */
    protected function invalidLogin($username, $reason, $extra_text = '')
    {
        global $pref;

        $doCheck = FALSE;            // Flag set if need to ban check
        $this->userData = array();

        switch($reason)
        {
            case LOGIN_ABORT :        // alt_auth reject
                $message = LAN_LOGIN_21;
                $this->genNote($this->userIP, $username, 'Alt_auth: ' . LAN_LOGIN_14);
                $this->logNote('LAN_ROLL_LOG_04', 'Alt_Auth: ' . $username);
                $doCheck = true;
                break;
            case LOGIN_DB_ERROR :    // alt_auth couldn't add valid user
                $message = LAN_LOGIN_31;
                $this->genNote($username, 'Alt_auth: ' . LAN_LOGIN_30);
//                $this->logNote('LAN_ROLL_LOG_04', 'Alt_Auth: '.$username);    // Added in alt_auth login
                $doCheck = true;
                break;
            case LOGIN_BAD_PW :
                $message = LAN_LOGIN_21;
                $this->logNote('LAN_ROLL_LOG_03', $username);
                break;
            case LOGIN_CHAP_FAIL :
                $message = LAN_LOGIN_21;
                $this->logNote('LAN_ROLL_LOG_03', 'CHAP: ' . $username);
                break;
            case LOGIN_BAD_USER :
                $message = LAN_LOGIN_21;
                $this->genNote($username, LAN_LOGIN_14);
                $this->logNote('LAN_ROLL_LOG_04', $username);
                $doCheck = true;
                break;
            case LOGIN_BAD_USERNAME :
                $message = LAN_LOGIN_21;
                $this->logNote('LAN_ROLL_LOG_08', $username);
                break;
            case LOGIN_MULTIPLE :
                $message = LAN_LOGIN_24;
                $this->logNote('LAN_ROLL_LOG_07', "U: {$username} IP: {$this->userIP}");
                $this->genNote($username, LAN_LOGIN_16);
                $doCheck = true;
                break;
            case LOGIN_BAD_CODE :
                $message = $extra_text; // LAN_LOGIN_23;
                $this->logNote('LAN_ROLL_LOG_02', $username);
                break;
            case LOGIN_NOT_ACTIVATED :
                if($pref['user_reg_veri'] == 2)
                {
                    $message = LAN_LOGIN_37;
                }
                else
                {
                    $srch = array("[", "]");
                    $repl = array("<a href='" . e_HTTP . "signup.php?resend'>", "</a>");
                    $message = str_replace($srch, $repl, LAN_LOGIN_22);
                }
                $this->logNote('LAN_ROLL_LOG_05', $username);
                $this->genNote($username, LAN_LOGIN_27);
                $doCheck = true;
                break;
            case LOGIN_BLANK_FIELD :
                $message = LAN_LOGIN_20;
                $this->logNote('LAN_ROLL_LOG_01', $username);
                break;
            case LOGIN_BAD_TRIGGER :
                $message = $extra_text;
                $this->logNote('LAN_ROLL_LOG_06', $username);
                break;
            case LOGIN_BANNED :
                $message = LAN_LOGIN_21;        // Just give 'incorrect login' message
                $this->genNote($username, LAN_LOGIN_25);
                $this->logNote('LAN_ROLL_LOG_09', $username);
                break;
            default :        // Something's gone wrong!
                $message = LAN_LOGIN_21;        // Just give 'incorrect login' message
                $this->genNote($username, LAN_LOGIN_26);
                $this->logNote('LAN_ROLL_LOG_10', $username);
        }

        e107::getMessage()->reset()->addError($message); // prevent duplicates

        if($this->testMode === true)
        {
            return $message;
        }

        defined('LOGINMESSAGE') or define('LOGINMESSAGE', $message);

    //    $sql->update('online', 'user_active = 0 WHERE user_ip = "'.$this->userIP.'" LIMIT 1');

        if ($doCheck) // See if ban required (formerly the checkibr() function)
        {
            if($pref['autoban'] == 1 || $pref['autoban'] == 3) // Flood + Login or Login Only.
            {
                $fails = e107::getDb()->count("generic", "(*)", "WHERE gen_ip='{$this->userIP}' AND gen_type='failed_login' ");

                $failLimit = vartrue($pref['failed_login_limit'],10);

                if($fails >= $failLimit)
                {
                    $time = time();
                    $description = e107::getParser()->lanVars(LAN_LOGIN_18,$failLimit);
                    e107::getIPHandler()->add_ban(4, $description, $this->userIP, 1);
                    e107::getDb()->insert("generic", "0, 'auto_banned', '".$time."', 0, '{$this->userIP}', '{$extra_text}', '".LAN_LOGIN_20.": ".e107::getParser()->toDB($username).", ".LAN_LOGIN_17);
                    e107::getEvent()->trigger('user_ban_failed_login', array('time'=>$time, 'ip'=>$this->userIP, 'other'=>$extra_text)); 
                }
            }
        }
        return false;        // Passed back to signal failed login
    }


    /**
     * Make a note of an event in the rolling log
     * @param string $title - title of logged event
     * @param string $text - detail of event
     * @return void
     */
    protected function logNote($title, $text)
    {
        $title = e107::getParser()->toDB($title);
    //    $text  = e107::getParser()->toDB($text);
    //    $text = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS_);

        $debug = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,4);
        $debug[] = $text;

        // unset($debug[0]);
        $debug[0] = e_REQUEST_URI;

    //    $array = debug_backtrace();
    //    e107::getLog()->addEvent(4, $array, "LOGIN", $title, $text, FALSE, LOG_TO_ROLLING);
        e107::getLog()->addEvent(4, $debug[1]['file']."|".$debug[1]['function']."@".$debug[1]['line'], "LOGIN", $title, $debug, FALSE, LOG_TO_ROLLING);
    }


    /**
     * Make a note of a failed login in the 'generic' table
     * @param string $username - as entered
     * @param string $msg1 - detail of event
     * @return void
     */
    protected function genNote($username, $msg1)
    {
        $message = e107::getParser()->toDB($msg1." ::: ".LAN_LOGIN_1.": ".$username);
        e107::getDb()->insert("generic", "0, 'failed_login', '".time()."', 0, '{$this->userIP}', 0, '{$message}'");
    }



    /**
     * Assumes the user is valid and logs them in.
     * @param array $userData ie. user_id, user_name, user_email,user_join, user_admin
     * @param bool $autologin 
     * @return bool|void
     */
    public function validLogin($userData, $autologin=false)
    {

        $cookieval = $this->userMethods->makeUserCookie($userData, $autologin);

        // Calculate class membership - needed for a couple of things
        // Problem is that USERCLASS_LIST just contains 'guest' and 'everyone' at this point
        $class_list = $this->userMethods->addCommonClasses($userData, true);



        $edata_li = array('user_id'    => $userData['user_id'], 'user_name' => $userData['user_name'], 'class_list' => implode(',', $class_list), /*'remember_me' => $autologin,*/
                          'user_admin' => $userData['user_admin'], 'user_email' => $userData['user_email']);

        $userAuditPref = e107::getPref('user_audit_class', e_UC_NOBODY);
        if (check_class($userAuditPref, $class_list))
        {
            e107::getLog()->user_audit(USER_AUDIT_LOGIN,  $edata_li, $userData['user_id'], $userData['user_name']);
        }

        e107::getEvent()->trigger("login", $edata_li);

        //  // 'New user' probationary period expired - we can take them out of the class
        if(check_class(e_UC_NEWUSER, $class_list) && $this->userMethods->newUserExpired($userData['user_join']))
        {
            $userData['user_class'] = e107::getUserClass()->ucRemove(e_UC_NEWUSER, $userData['user_class']);
//            $this->e107->admin_log->addEvent(4,__FILE__."|".__FUNCTION__."@".__LINE__,"DBG","Login new user complete",$userData['user_class'],FALSE,FALSE);
            e107::getDb()->update('user', "`user_class` = '" . $userData['user_class'] . "' WHERE `user_id`=" . $userData['user_id'] . " LIMIT 1");
            $edata_li = array('user_id' => $userData['user_id'], 'user_name' => $userData['user_name'], 'class_list' => $userData['user_class'], 'user_email' => $userData['user_email']);
            e107::getEvent()->trigger('userNotNew', $edata_li);
        }

        return $cookieval;
    }


}