From a1ca2aa6d5988ce539d920e2cbf0477c25194feb Mon Sep 17 00:00:00 2001 From: xokaido Date: Sat, 1 Feb 2014 08:27:57 -0800 Subject: [PATCH] Completely switched to the PDO instead of mysqli... Lots of changes made, removed all the mysqli things, simplified the code, adjusted some lines to be more beautiful and readable --- xok.auth.class.php | 812 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 812 insertions(+) create mode 100644 xok.auth.class.php diff --git a/xok.auth.class.php b/xok.auth.class.php new file mode 100644 index 0000000..6edf67f --- /dev/null +++ b/xok.auth.class.php @@ -0,0 +1,812 @@ +config_file ); + if( $language ) + $this->setLang( $language ); + else + $this->setLang( 'en' ); + $this->mysqli = new mysqli($db['host'], $db['user'], $db['pass'], $db['name']); + $this->db = new PDO("mysql:host={$db['host']};dbname={$db['name']};charset=utf8", $db['user'], $db['pass']); + unset($db['pass']); // $mysqli is public, remove password for security + } + + /* + * Get user hash + * @return string $this->hash + */ + + function getHash() + { return $this->hash; + } + + /* + * Set Language (localization) + * @param string $loc + * @return boolean + */ + + function setLang( $loc ) + { unset( $this->lang ); + require( 'lang.'. $loc .'.php' ); + $this->lang = $lang; // $lang array is in the lang file... + unset( $lang ); + return $this->loc = $loc; + } + + /* + * Log user in via MySQL Database + * @param string $username + * @param string $password + * @return boolean + */ + + function login($username, $password) + { + if(!isset($_COOKIE['auth_session'])) + { $attcount = $this->getattempt($_SERVER['REMOTE_ADDR']); + if($attcount >= $this->auth_conf['max_attempts']) + { $this->errormsg[] = $this->lang['login_lockedout']; + $this->errormsg[] = $this->lang['login_wait30']; + return false; + } + else // Input verification : + { if(strlen($username) == 0) + { $this->errormsg[] = $this->lang['login_username_empty']; + return false; + } + elseif(strlen($username) > 30) + { $this->errormsg[] = $this->lang['login_username_long']; + return false; + } + elseif(strlen($username) < 3) + { $this->errormsg[] = $this->lang['login_username_short']; + return false; + } + elseif(strlen($password) == 0) + { $this->errormsg[] = $this->lang['login_password_empty']; + return false; + } + elseif(strlen($password) > 30) + { $this->errormsg[] = $this->lang['login_password_short']; + return false; + } + elseif(strlen($password) < 5) + { $this->errormsg[] = $this->lang['login_password_long']; + return false; + } + else // Input is valid + { $password = $this->hashpass($password); + list( $isactive ) = $this->db_query( 'SELECT isactive FROM users WHERE username = ? AND password = ?', array( $username, $password ), true ); + if( !$isactive ) // Account is not activated + { $this->LogActivity($username, 'AUTH_LOGIN_FAIL', 'Account inactive'); + $this->errormsg[] = $this->lang['login_account_inactive']; + return false; + } + else // Account is activated + { $this->newsession($username); + $this->LogActivity($username, 'AUTH_LOGIN_SUCCESS', 'User logged in'); + $this->successmsg[] = $this->lang['login_success']; + return true; + } + } + } + } + else // User is already logged in + { $this->errormsg[] = $this->lang['login_already']; + return false; + } + } + + /* + * Register a new user into the database + * @param string $username + * @param string $password + * @param string $verifypassword + * @param string $email + * @return boolean + */ + + function register($username, $password, $verifypassword, $email) + { if(!isset($_COOKIE['auth_session'])) // Input Verification : + { if(strlen($username) == 0) + $this->errormsg[] = $this->lang['register_username_empty']; + elseif(strlen($username) > 30) + $this->errormsg[] = $this->lang['register_username_long']; + elseif(strlen($username) < 3) + $this->errormsg[] = $this->lang['register_username_short']; + + if(strlen($password) == 0) + $this->errormsg[] = $this->lang['register_password_empty']; + elseif(strlen($password) > 30) + $this->errormsg[] = $this->lang['register_password_long']; + elseif(strlen($password) < 5) + $this->errormsg[] = $this->lang['register_password_short']; + elseif($password !== $verifypassword) + $this->errormsg[] = $this->lang['register_password_nomatch']; + elseif(strstr($password, $username)) + $this->errormsg[] = $this->lang['register_password_username']; + + if(strlen($email) == 0) + $this->errormsg[] = $this->lang['register_email_empty']; + elseif(strlen($email) > 100) + $this->errormsg[] = $this->lang['register_email_long']; + elseif(strlen($email) < 5) + $this->errormsg[] = $this->lang['register_email_short']; + elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)) + $this->errormsg[] = $this->lang['register_email_invalid']; + + if(count($this->errormsg) == 0) // Input is valid + { $user = $this->db_query( 'SELECT * FROM users WHERE username=?', array( $username ) , true ); + if(count( $user ) != 0) // Username already exists + { $this->LogActivity('UNKNOWN', 'AUTH_REGISTER_FAIL', 'Username ({$username}) already exists'); + $this->errormsg[] = $this->lang['register_username_exist']; + return false; + } + else // Username is not taken + { $email = $this->db_query( 'SELECT * FROM users WHERE email=?', array( $email ), true ); + if( count( $email ) != 0) // Email address is already used + { $this->LogActivity('UNKNOWN', 'AUTH_REGISTER_FAIL', 'Email ({$email}) already exists'); + $this->errormsg[] = $this->lang['register_email_exist']; + return false; + } + else // Email address isn't already used + { $password = $this->hashpass($password); + $activekey = $this->randomkey(15); + + $this->db_query( 'INSERT INTO users (username, password, email, activekey) VALUES (?, ?, ?, ?)', array( $username, $password, $email, $activekey ) ); + + $message_from = $this->auth_conf['email_from']; + $message_subj = $this->auth_conf['site_name'] . ' - Account activation required !'; + $message_cont = 'Hello {$username}

'; + $message_cont .= 'You recently registered a new account on ' . $this->auth_conf['site_name'] . '
'; + $message_cont .= 'To activate your account please click the following link

'; + $message_cont .= 'auth_conf['base_url'] . '?page=activate&username={$username}&key={$activekey}\'>Activate my account'; + $message_head = 'From: {$message_from}' . '\r\n'; + $message_head .= 'MIME-Version: 1.0' . '\r\n'; + $message_head .= 'Content-type: text/html; charset=iso-8859-1' . '\r\n'; + + mail($email, $message_subj, $message_cont, $message_head); + $this->LogActivity($username, 'AUTH_REGISTER_SUCCESS', 'Account created and activation email sent'); + $this->successmsg[] = $this->lang['register_success']; + return true; + } + } + } + else + return false; + } + else // User is logged in + { $this->errormsg[] = $this->lang['register_email_loggedin']; + return false; + } + } + + /* + * Creates a new session for the provided username and sets cookie + * @param string $username + */ + + function newsession($username) + { $hash = md5(microtime()); + $ip = $_SERVER['REMOTE_ADDR']; + $expiredate = date('Y-m-d H:i:s', strtotime($this->auth_conf['session_duration'])); + $expiretime = strtotime($expiredate); + list( $uid ) = $this->db_query( 'SELECT id FROM users WHERE username=?', array( $username ), true ); + $this->db_query( 'DELETE FROM sessions WHERE username=?', array( $username ) ); + $this->db_query( 'INSERT INTO sessions (uid, username, hash, expiredate, ip) VALUES (?, ?, ?, ?, ?)', array( $uid, $username, $hash, $expiredate, $ip ) ); + setcookie('auth_session', $hash, $expiretime); + } + + /* + * Deletes the user's session based on hash + * @param string $hash + */ + + function deletesession($hash) + { list( $username ) = $this->db_query ( 'SELECT username FROM sessions WHERE hash=?', array( $hash ), true ); + if( !$username ) // Hash doesnt exist + { $this->LogActivity('UNKNOWN', 'AUTH_LOGOUT', 'User session cookie deleted - Database session not deleted - Hash ({'. $hash .'}) didnt exist'); + $this->errormsg[] = $this->lang['deletesession_invalid']; + setcookie('auth_session', $hash, time() - 3600); + } + else // Hash exists, Delete all sessions for that username : + { $this->db_query( 'DELETE FROM sessions WHERE username=?', array( $username ) ); + $this->LogActivity($username, 'AUTH_LOGOUT', 'User session cookie deleted - Database session deleted - Hash ({$hash})'); + setcookie('auth_session', $hash, time() - 3600); + } + } + + /* + * Provides an associative array of user info based on session hash + * @param string $hash + * @return array $session + */ + + function sessioninfo($hash) + { list( $session['uid'], $session['username'], $session['expiredate'], $session['ip'] ) = $this->db_query( 'SELECT uid, username, expiredate, ip FROM sessions WHERE hash=?', array( $hash ), true ); + if( !$session['uid'] ) // Hash doesnt exist + { $this->errormsg[] = $this->lang['sessioninfo_invalid']; + setcookie('auth_session', $hash, time() - 3600); + return false; + } + else // Hash exists + return $session; + } + + /* + * Checks if session is valid (Current IP = Stored IP + Current date < expire date) + * @param string $hash + * @return bool + */ + + function checksession($hash) + { list( $username, $db_expiredate, $db_ip ) = $this->db_query( 'SELECT username, expiredate, ip FROM sessions WHERE hash=?', array( $hash ), true ); + if( !$username ) // Hash doesnt exist + { setcookie('auth_session', $hash, time() - 3600); + $this->LogActivity($username, 'AUTH_CHECKSESSION', 'User session cookie deleted - Hash ({'. $hash .'}) didnt exist'); + return false; + } + else + { if($_SERVER['REMOTE_ADDR'] != $db_ip) // Hash exists, but IP has changed + { $this->db_query( 'DELETE FROM sessions WHERE username=?', array( $username ) ); + setcookie('auth_session', $hash, time() - 3600); + $this->LogActivity($username, 'AUTH_CHECKSESSION', 'User session cookie deleted - IP Different ( DB : {$db_ip} / Current : ' . $_SERVER['REMOTE_ADDR'] . ' )'); + return false; + } + else + { $expiredate = strtotime($db_expiredate); + $currentdate = strtotime(date('Y-m-d H:i:s')); + if($currentdate > $expiredate) // Hash exists, IP is the same, but session has expired + { $this->db_query( 'DELETE FROM sessions WHERE username=?', array( $username ) ); + setcookie('auth_session', $hash, time() - 3600); + $this->LogActivity($username, 'AUTH_CHECKSESSION', 'User session cookie deleted - Session expired ( Expire date : {$db_expiredate} )'); + return false; + } + else // Hash exists, IP is the same, date < expiry date + return true; + } + } + } + + /* + * Returns a random string, length can be modified + * @param int $length + * @return string $key + */ + + function randomkey($length = 10) + { $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890'; + $key = ''; + for($i = 0; $i < $length; $i++) + $key .= $chars{rand(0, strlen($chars) - 1)}; + return $key; + } + + /* + * Activate a user's account + * @param string $username + * @param string $key + * @return boolean + */ + + function activate($username, $key) + { // Input verification + if(strlen($username) == 0) + { $this->errormsg[] = $this->lang['activate_username_empty']; + return false; + } + elseif(strlen($username) > 30) + { $this->errormsg[] = $this->lang['activate_username_long']; + return false; + } + elseif(strlen($username) < 3) + { $this->errormsg[] = $this->lang['activate_username_short']; + return false; + } + elseif(strlen($key) == 0) + { $this->errormsg[] = $this->lang['activate_key_empty']; + return false; + } + elseif(strlen($key) > 15) + { $this->errormsg[] = $this->lang['activate_key_long']; + return false; + } + elseif(strlen($key) < 15) + { $this->errormsg[] = $this->lang['activate_key_short']; + return false; + } + else + { list( $isactive, $activekey ) = $this->db_query( 'SELECT isactive, activekey FROM users WHERE username=?', array( $username ), true ); + + if( !$activekey ) // User doesnt exist + { $this->LogActivity('UNKNOWN', 'AUTH_ACTIVATE_FAIL', 'Username Incorrect : {$username}'); + $this->errormsg[] = $this->lang['activate_username_incorrect']; + return false; + } + else // User exists + { if($isactive == 1) // Account is already activated + { $this->LogActivity($username, 'AUTH_ACTIVATE_FAIL', 'Account already activated'); + $this->errormsg[] = $this->lang['activate_account_activated']; + return true; + } + else // Account isn't activated + { if($key == $activekey) // Activation keys match + { $new_isactive = 1; + $new_activekey = '0'; + $this->db_query( 'UPDATE users SET isactive=?, activekey=? WHERE username=?', array( $new_isactive, $new_activekey, $username ) ); + $this->LogActivity($username, 'AUTH_ACTIVATE_SUCCESS', 'Activation successful. Key Entry deleted.'); + $this->successmsg[] = $this->lang['activate_success']; + return true; + } + else // Activation Keys dont match + { $this->LogActivity($username, 'AUTH_ACTIVATE_FAIL', 'Activation keys dont match ( DB : {'. $activekey .'} / Given : {$key} )'); + $this->errormsg[] = $this->lang['activate_key_incorrect']; + return false; + } + } + } + } + } + + /* + * Changes a user's password, providing the current password is known + * @param string $username + * @param string $currpass + * @param string $newpass + * @param string $verifynewpass + * @return boolean + */ + + function changepass($username, $currpass, $newpass, $verifynewpass) + { if(strlen($username) == 0) + $this->errormsg[] = $this->lang['changepass_username_empty']; + elseif(strlen($username) > 30) + $this->errormsg[] = $this->lang['changepass_username_long']; + elseif(strlen($username) < 3) + $this->errormsg[] = $this->lang['changepass_username_short']; + /************************************************************************/ + if(strlen($currpass) == 0) + $this->errormsg[] = $this->lang['changepass_currpass_empty']; + elseif(strlen($currpass) < 5) + $this->errormsg[] = $this->lang['changepass_currpass_short']; + elseif(strlen($currpass) > 30) + $this->errormsg[] = $this->lang['changepass_currpass_long']; + /************************************************************************/ + if(strlen($newpass) == 0) + $this->errormsg[] = $this->lang['changepass_newpass_empty']; + elseif(strlen($newpass) < 5) + $this->errormsg[] = $this->lang['changepass_newpass_short']; + elseif(strlen($newpass) > 30) + $this->errormsg[] = $this->lang['changepass_newpass_long']; + elseif(strstr($newpass, $username)) + $this->errormsg[] = $this->lang['changepass_password_username']; + elseif($newpass !== $verifynewpass) + $this->errormsg[] = $this->lang['changepass_password_nomatch']; + + if(count($this->errormsg) == 0) + { $currpass = $this->hashpass($currpass); + $newpass = $this->hashpass($newpass); + list( $db_currpass ) = $this->db_query( 'SELECT password FROM users WHERE username=?', array( $username ), true ); + + if( !$db_currpass ) + { $this->LogActivity('UNKNOWN', 'AUTH_CHANGEPASS_FAIL', 'Username Incorrect ({$username})'); + $this->errormsg[] = $this->lang['changepass_username_incorrect']; + return false; + } + else + { if($currpass == $db_currpass) + { $this->db_query( 'UPDATE users SET password=? WHERE username=?', array( $newpass, $username ) ); + $this->LogActivity($username, 'AUTH_CHANGEPASS_SUCCESS', 'Password changed'); + $this->successmsg[] = $this->lang['changepass_success']; + return true; + } + else + { $this->LogActivity($username, 'AUTH_CHANGEPASS_FAIL', 'Current Password Incorrect ( DB : {$db_currpass} / Given : {$currpass} )'); + $this->errormsg[] = $this->lang['changepass_currpass_incorrect']; + return false; + } + } + } + else + return false; + } + + /* + * Changes the stored email address based on username + * @param string $username + * @param string $email + * @return boolean + */ + + function changeemail($username, $email) + { if(strlen($username) == 0) + $this->errormsg[] = $this->lang['changeemail_username_empty']; + elseif(strlen($username) > 30) + $this->errormsg[] = $this->lang['changeemail_username_long']; + elseif(strlen($username) < 3) + $this->errormsg[] = $this->lang['changeemail_username_short']; + /*****************************************************************************/ + if(strlen($email) == 0) + $this->errormsg[] = $this->lang['changeemail_email_empty']; + elseif(strlen($email) > 100) + $this->errormsg[] = $this->lang['changeemail_email_long']; + elseif(strlen($email) < 5) + $this->errormsg[] = $this->lang['changeemail_email_short']; + elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)) + $this->errormsg[] = $this->lang['changeemail_email_invalid']; + + if(count($this->errormsg) == 0) + { list( $db_email ) = $this->db_query( 'SELECT email FROM users WHERE username=?', array( $username ), true ); + + if( !$db_email ) + { $this->LogActivity('UNKNOWN', 'AUTH_CHANGEEMAIL_FAIL', 'Username Incorrect ({$username})'); + $this->errormsg[] = $this->lang['changeemail_username_incorrect']; + return false; + } + else + { if($email == $db_email) + { $this->LogActivity($username, 'AUTH_CHANGEEMAIL_FAIL', 'Old and new email matched ({$email})'); + $this->errormsg[] = $this->lang['changeemail_email_match']; + return false; + } + else + { $this->db_query( 'UPDATE users SET email=? WHERE username=?', array( $email, $username ) ); + $this->LogActivity($username, 'AUTH_CHANGEEMAIL_SUCCESS', 'Email changed from {$db_email} to {$email}'); + $this->successmsg[] = $this->lang['changeemail_success']; + return true; + } + } + } + else + return false; + } + + /* + * Give the user the ability to change their password if the current password is forgotten + * by sending email to the email address associated to that user + * @param string $username + * @param string $email + * @param string $key + * @param string $newpass + * @param string $verifynewpass + * @return boolean + */ + + function resetpass($username = '0', $email ='0', $key = '0', $newpass = '0', $verifynewpass = '0') + { $attcount = $this->getattempt($_SERVER['REMOTE_ADDR']); + if($attcount >= $this->auth_conf['max_attempts']) + { $this->errormsg[] = $this->lang['resetpass_this->lockedout']; + $this->errormsg[] = $this->lang['resetpass_wait30']; + return false; + } + else + { if($username == '0' && $key == '0') + { if(strlen($email) == 0) + $this->errormsg[] = $this->lang['resetpass_email_empty']; + elseif(strlen($email) > 100) + $this->errormsg[] = $this->lang['resetpass_email_long']; + elseif(strlen($email) < 5) + $this->errormsg[] = $this->lang['resetpass_email_short']; + elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)) + $this->errormsg[] = $this->lang['resetpass_email_invalid']; + + $resetkey = $this->randomkey(15); + list( $username ) = $this->db_query( 'SELECT username FROM users WHERE email=?', array( $email ), true ); + + if( !$username ) + { $this->errormsg[] = $this->lang['resetpass_email_incorrect']; + $attcount = $attcount + 1; + $remaincount = $this->auth_conf['max_attempts'] - $attcount; + $this->LogActivity('UNKNOWN', 'AUTH_RESETPASS_FAIL', 'Email incorrect ({$email})'); + $this->errormsg[] = sprintf($this->lang['resetpass_attempts_remaining'], $remaincount); + $this->addattempt($_SERVER['REMOTE_ADDR']); + return false; + } + else + { $this->db_query( 'UPDATE users SET resetkey=? WHERE username=?', array( $resetkey, $username ) ); + + $message_from = $this->auth_conf['email_from']; + $message_subj = $this->auth_conf['site_name'] . ' - Password reset request !'; + $message_cont = 'Hello {$username}

'; + $message_cont .= 'You recently requested a password reset on ' . $this->auth_conf['site_name'] . '
'; + $message_cont .= 'To proceed with the password reset, please click the following link :

'; + $message_cont .= 'auth_conf['base_url'] . '?page=forgot&username={$username}&key={$resetkey}\'>Reset My Password'; + $message_head = 'From: {$message_from}' . '\r\n'; + $message_head .= 'MIME-Version: 1.0' . '\r\n'; + $message_head .= 'Content-type: text/html; charset=iso-8859-1' . '\r\n'; + mail($email, $message_subj, $message_cont, $message_head); + $this->LogActivity($username, 'AUTH_RESETPASS_SUCCESS', 'Reset pass request sent to {$email} ( Key : {$resetkey} )'); + $this->successmsg[] = $this->lang['resetpass_email_sent']; + return true; + } + } + else // Reset Password + { if(strlen($key) == 0) + $this->errormsg[] = $this->lang['resetpass_key_empty']; + elseif(strlen($key) < 15) + $this->errormsg[] = $this->lang['resetpass_key_short']; + elseif(strlen($key) > 15) + $this->errormsg[] = $this->lang['resetpass_key_long']; + + if(strlen($newpass) == 0) + $this->errormsg[] = $this->lang['resetpass_newpass_empty']; + elseif(strlen($newpass) > 30) + $this->errormsg[] = $this->lang['resetpass_newpass_long']; + elseif(strlen($newpass) < 5) + $this->errormsg[] = $this->lang['resetpass_newpass_short']; + elseif(strstr($newpass, $username)) + $this->errormsg[] = $this->lang['resetpass_newpass_username']; + elseif($newpass !== $verifynewpass) + $this->errormsg[] = $this->lang['resetpass_newpass_nomatch']; + + if(count($this->errormsg) == 0) + { list( $db_key ) = $this->db_query( 'SELECT resetkey FROM users WHERE username=?', array( $username ), true ); + if( !$db_key ) + { $this->errormsg[] = $this->lang['resetpass_username_incorrect']; + $attcount = $attcount + 1; + $remaincount = $this->auth_conf['max_attempts'] - $attcount; + $this->LogActivity('UNKNOWN', 'AUTH_RESETPASS_FAIL', 'Username incorrect ({$username})'); + $this->errormsg[] = sprintf($this->lang['resetpass_attempts_remaining'], $remaincount); + $this->addattempt($_SERVER['REMOTE_ADDR']); + return false; + } + else + { if($key == $db_key) + { $newpass = $this->hashpass($newpass); + $resetkey = '0'; + $this->db_query( 'UPDATE users SET password=?, resetkey=? WHERE username=?', array( $newpass, $resetkey, $username ) );; + $this->LogActivity($username, 'AUTH_RESETPASS_SUCCESS', 'Password reset - Key reset'); + $this->successmsg[] = $this->lang['resetpass_success']; + return true; + } + else + { + $this->errormsg[] = $this->lang['resetpass_key_incorrect']; + $attcount = $attcount + 1; + $remaincount = 5 - $attcount; + $this->LogActivity($username, 'AUTH_RESETPASS_FAIL', 'Key Incorrect ( DB : {$db_key} / Given : {$key} )'); + $this->errormsg[] = sprintf($this->lang['resetpass_attempts_remaining'], $remaincount); + $this->addattempt($_SERVER['REMOTE_ADDR']); + return false; + } + } + } + else + return false; + } + } + } + + /* + * Checks if the reset key is correct for provided username + * @param string $username + * @param string $key + * @return boolean + */ + + function checkresetkey($username, $key) + { $attcount = $this->getattempt($_SERVER['REMOTE_ADDR']); + + if($attcount >= $this->auth_conf['max_attempts']) + { $this->errormsg[] = $this->lang['resetpass_this->lockedout']; + $this->errormsg[] = $this->lang['resetpass_wait30']; + return false; + } + else + { if(strlen($username) == 0) + return false; + elseif(strlen($username) > 30) + return false; + elseif(strlen($username) < 3) + return false; + elseif(strlen($key) == 0) + return false; + elseif(strlen($key) < 15) + return false; + elseif(strlen($key) > 15) + return false; + else + { list( $db_key ) = $this->db_query( 'SELECT resetkey FROM users WHERE username=?', array( $username ), true ); + if( !$db_key ) + { $this->LogActivity('UNKNOWN', 'AUTH_CHECKRESETKEY_FAIL', 'Username doesnt exist ({$username})'); + $this->addattempt($_SERVER['REMOTE_ADDR']); + $this->errormsg[] = $this->lang['checkresetkey_username_incorrect']; + $attcount = $attcount + 1; + $remaincount = $this->auth_conf['max_attempts'] - $attcount; + $this->errormsg[] = sprintf($this->lang['checkresetkey_attempts_remaining'], $remaincount); + return false; + } + else + { if($key == $db_key) + return true; + else + { $this->LogActivity($username, 'AUTH_CHECKRESETKEY_FAIL', 'Key provided is different to DB key ( DB : {$db_key} / Given : {$key} )'); + $this->addattempt($_SERVER['REMOTE_ADDR']); + $this->errormsg[] = $this->lang['checkresetkey_key_incorrect']; + $attcount = $attcount + 1; + $remaincount = $this->auth_conf['max_attempts'] - $attcount; + $this->errormsg[] = sprintf($this->lang['checkresetkey_attempts_remaining'], $remaincount); + return false; + } + } + } + } + } + + /* + * Deletes a user's account. Requires user's password + * @param string $username + * @param string $password + * @return boolean + */ + + function deleteaccount($username, $password) + { if(strlen($username) == 0) + $this->errormsg[] = $this->lang['deleteaccount_username_empty']; + elseif(strlen($username) > 30) + $this->errormsg[] = $this->lang['deleteaccount_username_long']; + elseif(strlen($username) < 3) + $this->errormsg[] = $this->lang['deleteaccount_username_short']; + + if(strlen($password) == 0) + $this->errormsg[] = $this->lang['deleteaccount_password_empty']; + elseif(strlen($password) > 30) + $this->errormsg[] = $this->lang['deleteaccount_password_long']; + elseif(strlen($password) < 5) + $this->errormsg[] = $this->lang['deleteaccount_password_short']; + + if(count($this->errormsg) == 0) + { $password = $this->hashpass($password); + list( $db_password ) = $this->db_query( 'SELECT password FROM users WHERE username=?', array( $username ), true ); + if( !$db_password ) + { $this->LogActivity('UNKNOWN', 'AUTH_DELETEACCOUNT_FAIL', 'Username Incorrect ({$username})'); + $this->errormsg[] = $this->lang['deleteaccount_username_incorrect']; + return false; + } + else + { if( $password == $db_password[0] ) + { $this->db_query( 'DELETE FROM users WHERE username=?', array( $username ) ); + $this->db_query( 'DELETE FROM sessions WHERE username=?', array( $username ) ); + $this->LogActivity($username, 'AUTH_DELETEACCOUNT_SUCCESS', 'Account deleted - Sessions deleted'); + $this->successmsg[] = $this->lang['deleteaccount_success']; + return true; + } + else + { $this->LogActivity($username, 'AUTH_DELETEACCOUNT_FAIL', 'Password incorrect ( DB : {$db_password} / Given : {$password} )'); + $this->errormsg[] = $this->lang['deleteaccount_password_incorrect']; + return false; + } + } + } + else + return false; + } + + /* + * Adds a new attempt to database based on user's IP + * @param string $ip + */ + + function addattempt($ip) + { $attempt_count = $this->db_query( 'SELECT count FROM attempts WHERE ip = ?', array( $ip ), true ); + if($count == 0) // No record of this IP in attempts table already exists, create new + { $attempt_expiredate = date('Y-m-d H:i:s', strtotime($this->auth_conf['security_duration'])); + $attempt_count = 1; + $this->db_query( 'INSERT INTO attempts (ip, count, expiredate) VALUES (?, ?, ?)', array( $ip, $attempt_count, $attempt_expiredate ) ); + } + else // IP Already exists in attempts table, add 1 to current count + { $attempt_expiredate = date('Y-m-d H:i:s', strtotime($this->auth_conf['security_duration'])); + $attempt_count = $attempt_count + 1; + $this->db_query( 'UPDATE attempts SET count=?, expiredate=? WHERE ip=?', array( $attempt_count, $attempt_expiredate, $ip ) ); + } + } + + /* + * Provides amount of attempts already in database based on user's IP + * @param string $ip + * @return int $attempt_count + */ + + function getattempt($ip) + { list( $attempt_count ) = $this->db_query( 'SELECT count FROM attempts WHERE ip = ?', array( $ip ), true ); + return $attempt_count; + } + + /* + * Function used to remove expired attempt logs from database (Recommended as Cron Job) + */ + + function expireattempt() + { list( $ip, $expiredate ) = $this->db_query( 'SELECT ip, expiredate FROM attempts', array( ), true ); + $curr_time = strtotime(date('Y-m-d H:i:s')); + if( !$expiredate ) + { while($query->fetch()) // TODO: CHECK THIS OUT, WE NEED TO LOOP THROUGH A VALID VARIABLE!!! + { $attempt_expiredate = strtotime($expiredate); + if($attempt_expiredate <= $curr_time) + $this->db_query( 'DELETE FROM attempts WHERE ip = ?', array( $ip ) ); + } + } + } + + /* + * Logs users actions on the site to database for future viewing + * @param string $username + * @param string $action + * @param string $additionalinfo + * @return boolean + */ + + function LogActivity($username, $action, $additionalinfo = 'none') + { if( !$username ) + $username = 'GUEST'; + elseif(strlen($username) < 3) + { $this->errormsg[] = $this->lang['logactivity_username_short']; + return false; + } + elseif(strlen($username) > 30) + { $this->errormsg[] = $this->lang['logactivity_username_long']; + return false; + } + + if(strlen($action) == 0) + { $this->errormsg[] = $this->lang['logactivity_action_empty']; + return false; + } + elseif(strlen($action) < 3) + { $this->errormsg[] = $this->lang['logactivity_action_short']; + return false; + } + elseif(strlen($action) > 100) + { $this->errormsg[] = $this->lang['logactivity_action_long']; + return false; + } + + if(count($this->errormsg) == 0) + { $ip = $_SERVER['REMOTE_ADDR']; + $date = date('Y-m-d H:i:s'); + $this->db_query( 'INSERT INTO activitylog (date, username, action, additionalinfo, ip) VALUES (?, ?, ?, ?, ?)', array( $date, $username, $action, $additionalinfo, $ip ) ); + return true; + } + } + + /* + * Hash user's password with SHA512, base64_encode, ROT13 and salts ! + * @param string $password + * @return string $hashed_pass + */ + + function hashpass($password) + { $hashed_pass = hash('SHA512', base64_encode( str_rot13( hash('SHA512', str_rot13( $this->auth_conf['salt_1'] . $password . $this->auth_conf['salt_2']))))); + $this->hash = $hashed_pass; + return $hashed_pass; + } + + /* + * Query Database and send an SQL + * @param string $query + * @param array $params + * @param bool $fetch + * @return array fetched values + */ + + function db_query( $query, $params, $fetch = false ) + { $thing = $this->db->prepare( $query ); + if( !is_array( $params ) ) + { $tmp = $params; + unset( $params ); + $params = array( $tmp ); + } + $thing->execute( $params ); + if( $fetch ) + return $thing->fetch(); + return true; + } +}