1
0
mirror of https://github.com/e107inc/e107.git synced 2025-01-17 20:58:30 +01:00

Additional doc, options related to editing EUFs

This commit is contained in:
e107steved 2010-01-31 22:21:11 +00:00
parent 7815537cdf
commit c8b45cc024

View File

@ -9,19 +9,24 @@
* Handler - user-related functions * Handler - user-related functions
* *
* $Source: /cvs_backup/e107_0.8/e107_handlers/user_handler.php,v $ * $Source: /cvs_backup/e107_0.8/e107_handlers/user_handler.php,v $
* $Revision: 1.21 $ * $Revision: 1.22 $
* $Date: 2009-12-16 22:26:27 $ * $Date: 2010-01-31 22:21:11 $
* $Author: e107steved $ * $Author: e107steved $
* *
*/ */
/* /**
USER HANDLER CLASS - manages login and various user functions *
* @package e107
* @subpackage e107_handlers
* @version $Id: user_handler.php,v 1.22 2010-01-31 22:21:11 e107steved Exp $;
*
* USER HANDLER CLASS - manages login and various user functions
*
* @todo - consider vetting of user_xup (if we keep it)
*/
Vetting routines TODO:
user_xup processing - nothing special?
*/
if (!defined('e107_INIT')) { exit; } if (!defined('e107_INIT')) { exit; }
@ -58,11 +63,11 @@ class UserHandler
var $otherFields = array(); var $otherFields = array();
// Constructor // Constructor
function UserHandler() public function __construct()
{ {
global $pref; global $pref;
/* /**
Table of vetting methods for user data - lists every field whose value could be set manually. Table of vetting methods for user data - lists every field whose value could be set manually.
Valid 'vetMethod' values (use comma separated list for multiple vetting): Valid 'vetMethod' values (use comma separated list for multiple vetting):
0 - Null method 0 - Null method
@ -145,8 +150,16 @@ class UserHandler
} }
// Given plaintext password and login name, generate password string to store in DB /**
function HashPassword($password, $login_name, $force='') * Given plaintext password and login name, generate password string to store in DB
*
* @param string $password - plaintext password as entered by user
* @param string $login_name - string used to log in (could actually be email address)
* @param empty|PASSWORD_E107_MD5|PASSWORD_E107_SALT $force - if non-empty, forces a particular type of password
*
* @return string|boolean - FALSE if invalid emcoding method, else encoded password to store in DB
*/
public function HashPassword($password, $login_name, $force='')
{ {
if ($force == '') $force = $this->preferred; if ($force == '') $force = $this->preferred;
switch ($force) switch ($force)
@ -162,55 +175,76 @@ class UserHandler
} }
// Verify existing plaintext password against a stored hash value (which defines the encoding format and any 'salt') /**
// Return PASSWORD_INVALID if invalid password * Verify existing plaintext password against a stored hash value (which defines the encoding format and any 'salt')
// Return PASSWORD_VALID if valid password *
// Return a new hash to store if valid password but non-preferred encoding * @param string $password - plaintext password as entered by user
function CheckPassword($password, $login_name, $stored_hash) * @param string $login_name - string used to log in (could actually be email address)
* @param string $stored_hash - required value for password to match
*
* @return PASSWORD_INVALID|PASSWORD_VALID|string
* PASSWORD_INVALID if no match
* PASSWORD_VALID if valid password
* Return a new hash to store if valid password but non-preferred encoding
*/
public function CheckPassword($password, $login_name, $stored_hash)
{ {
if (strlen(trim($password)) == 0) return PASSWORD_INVALID; if (strlen(trim($password)) == 0) return PASSWORD_INVALID;
if (($this->passwordOpts <= 1) && (strlen($stored_hash) == 32)) if (($this->passwordOpts <= 1) && (strlen($stored_hash) == 32))
{ // Its simple md5 encoding { // Its simple md5 encoding
if (md5($password) !== $stored_hash) return PASSWORD_INVALID; if (md5($password) !== $stored_hash) return PASSWORD_INVALID;
if ($this->preferred == PASSWORD_E107_MD5) return PASSWORD_VALID; if ($this->preferred == PASSWORD_E107_MD5) return PASSWORD_VALID;
return $this->HashPassword($password); // Valid password, but non-preferred encoding; return the new hash return $this->HashPassword($password); // Valid password, but non-preferred encoding; return the new hash
} }
// Allow the salted password even if disabled - for those that do try to go back! // Allow the salted password even if disabled - for those that do try to go back!
// if (($this->passwordOpts >= 1) && (strlen($stored_hash) == 35) && (substr($stored_hash,0,3) == PASSWORD_E107_ID)) // if (($this->passwordOpts >= 1) && (strlen($stored_hash) == 35) && (substr($stored_hash,0,3) == PASSWORD_E107_ID))
if ((strlen($stored_hash) == 35) && (substr($stored_hash,0,3) == PASSWORD_E107_ID)) if ((strlen($stored_hash) == 35) && (substr($stored_hash,0,3) == PASSWORD_E107_ID))
{ // Its the standard E107 salted hash { // Its the standard E107 salted hash
$hash = $this->HashPassword($password, $login_name, PASSWORD_E107_SALT); $hash = $this->HashPassword($password, $login_name, PASSWORD_E107_SALT);
if ($hash === FALSE) return PASSWORD_INVALID; if ($hash === FALSE) return PASSWORD_INVALID;
return ($hash == $stored_hash) ? PASSWORD_VALID : PASSWORD_INVALID; return ($hash == $stored_hash) ? PASSWORD_VALID : PASSWORD_INVALID;
} }
return PASSWORD_INVALID;
return PASSWORD_INVALID;
} }
// Verifies a standard response to a CHAP challenge /**
function CheckCHAP($challenge, $response, $login_name, $stored_hash ) * Verifies a standard response to a CHAP challenge
*
* @param string $challenge - the string sent to the user
* @param string $response - the response returned by the user
* @param string $login_name - user's login name
* @param string $stored_hash - password hash as stored in DB
*
* @return PASSWORD_INVALID|PASSWORD_VALID
*/
public function CheckCHAP($challenge, $response, $login_name, $stored_hash )
{ {
if (strlen($challenge) != 40) return PASSWORD_INVALID; if (strlen($challenge) != 40) return PASSWORD_INVALID;
if (strlen($response) != 32) return PASSWORD_INVALID; if (strlen($response) != 32) return PASSWORD_INVALID;
$valid_ret = PASSWORD_VALID; $valid_ret = PASSWORD_VALID;
if (strlen($stored_hash) == 32) if (strlen($stored_hash) == 32)
{ // Its simple md5 password storage { // Its simple md5 password storage
$stored_hash = PASSWORD_E107_ID.md5($stored_hash.$login_name); // Convert to the salted format always used by CHAP $stored_hash = PASSWORD_E107_ID.md5($stored_hash.$login_name); // Convert to the salted format always used by CHAP
if ($this->passwordOpts != PASSWORD_E107_MD5) $valid_ret = $stored_response; if ($this->passwordOpts != PASSWORD_E107_MD5) $valid_ret = $stored_response;
} }
$testval = md5(substr($stored_hash,strlen(PASSWORD_E107_ID)).$challenge); $testval = md5(substr($stored_hash,strlen(PASSWORD_E107_ID)).$challenge);
if ($testval == $response) return $valid_ret; if ($testval == $response) return $valid_ret;
return PASSWORD_INVALID; return PASSWORD_INVALID;
} }
// Checks whether the user has to validate a user setting change by entering password (basically, if that field affects the /**
// stored password value) * Checks whether the user has to validate a change of user settings by entering password (basically, if that field affects the
// Returns TRUE if change required, FALSE otherwise * stored password value)
function isPasswordRequired($fieldName) *
* @param string $fieldName - name of field being changed
*
* @return bool TRUE if change required, FALSE otherwise
*/
public function isPasswordRequired($fieldName)
{ {
if ($this->preferred == PASSWORD_E107_MD5) return FALSE; if ($this->preferred == PASSWORD_E107_MD5) return FALSE;
switch ($fieldName) switch ($fieldName)
@ -224,8 +258,13 @@ class UserHandler
} }
// Determines whether its necessary to store a separate password for email address validation
function needEmailPassword() /**
* Determines whether its necessary to store a separate password for email address validation
*
* @return bool TRUE if separate password
*/
public function needEmailPassword()
{ {
if ($this->preferred == PASSWORD_E107_MD5) return FALSE; if ($this->preferred == PASSWORD_E107_MD5) return FALSE;
if ($this->passwordEmail) return TRUE; if ($this->passwordEmail) return TRUE;
@ -233,50 +272,73 @@ class UserHandler
} }
// Checks whether the password value can be converted to the current default
// Returns TRUE if conversion possible.
// Returns FALSE if conversion not possible, or not needed
function canConvert($password)
{
if ($this->preferred == PASSWORD_E107_MD5) return FALSE;
if (strlen($password) == 32) return TRUE; // Can convert from md5 to salted
return FALSE;
}
/**
// Given md5-encoded password and login name, generate password string to store in DB * Checks whether the password value can be converted to the current default
function ConvertPassword($password, $login_name) *
* @param string $password - hashed password
* @return bool TRUE if conversion possible, FALSE if not possible, or not needed.
*/
public function canConvert($password)
{ {
if ($this->canConvert($password) === FALSE) return $password; if ($this->preferred == PASSWORD_E107_MD5) return FALSE;
return PASSWORD_E107_ID.md5($password.$login_name); if (strlen($password) == 32) return TRUE; // Can convert from md5 to salted
return FALSE;
} }
// Generates a random user login name according to some pattern. /**
// Checked for uniqueness. * Given md5-encoded password and login name, generate password string to store in DB
function generateUserLogin($pattern, $seed='') *
* @param string $password - MD5-hashed password
* @param string $login_name - user's login name
*
* @return string hashed password to store in DB, converted as necessary
*/
public function ConvertPassword($password, $login_name)
{ {
$ul_sql = new db; if ($this->canConvert($password) === FALSE) return $password;
if (strlen($pattern) < 6) $pattern = '##....'; return PASSWORD_E107_ID.md5($password.$login_name);
do
{
$newname = $this->generateRandomString($pattern, $seed);
} while ($ul_sql->db_Select('user','user_id',"`user_loginname`='{$newname}'"));
return $newname;
} }
// Generates a random string - for user login name, password etc, according to some pattern. /**
// Checked for uniqueness. * Generates a random user login name according to some pattern.
// Pattern format: * Checked for uniqueness.
// # - an alpha character *
// . - a numeric character * @param string $pattern - defines the format of the username
// * - an alphanumeric character * @param int $seed - may be used with the random pattern generator
// ^ - next character from seed *
// alphanumerics are included 'as is' * @return string a user login name, guaranteed unique in the database.
function generateRandomString($pattern, $seed = '') */
public function generateUserLogin($pattern, $seed='')
{
$ul_sql = new db;
if (strlen($pattern) < 6) $pattern = '##....';
do
{
$newname = $this->generateRandomString($pattern, $seed);
} while ($ul_sql->db_Select('user','user_id',"`user_loginname`='{$newname}'"));
return $newname;
}
/**
* Generates a random string - for user login name, password etc, according to some pattern.
* @param string $pattern - defines the output format:
* # - an alpha character
* . - a numeric character
* * - an alphanumeric character
* ^ - next character from seed
* alphanumerics are included 'as is'
* @param int $seed - may be used with the random pattern generator
*
* @return string - the required random string
*/
public function generateRandomString($pattern, $seed = '')
{ {
if (strlen($pattern) < 6) if (strlen($pattern) < 6)
$pattern = '##....'; $pattern = '##....';
@ -343,13 +405,6 @@ class UserHandler
{ {
$newname .= $c; $newname .= $c;
} }
/*
else
{
$t = rand(0, $alphaNumLength);
$newname .= $alphaNum[$t];
}
*/
} }
} }
return $newname; return $newname;
@ -357,17 +412,22 @@ class UserHandler
// Split up an email address to check for banned domains. /**
// Return false if invalid address. Otherwise returns a set of values to check * Split up an email address to check for banned domains.
function make_email_query($email, $fieldname = 'banlist_ip') * @param string $email - email address to process
* @param string $fieldname - name of field being searched in DB
*
* @return bool|string false if invalid address. Otherwise returns a set of values to check
*/
public function make_email_query($email, $fieldname = 'banlist_ip')
{ {
global $tp; $tp = e107::getParser();
$tmp = strtolower($tp -> toDB(trim(substr($email, strrpos($email, "@")+1)))); // Pull out the domain name $tmp = strtolower($tp -> toDB(trim(substr($email, strrpos($email, "@")+1)))); // Pull out the domain name
if ($tmp == '') return FALSE; if ($tmp == '') return FALSE;
if (strpos($tmp,'.') === FALSE) return FALSE; if (strpos($tmp,'.') === FALSE) return FALSE;
$em = array_reverse(explode('.',$tmp)); $em = array_reverse(explode('.',$tmp));
$line = ''; $line = '';
$out = array('*@'.$tmp); // First element looks for domain as email address $out = array("='*@.{$tmp}'"); // First element looks for domain as email address
foreach ($em as $e) foreach ($em as $e)
{ {
$line = '.'.$e.$line; $line = '.'.$e.$line;
@ -378,11 +438,20 @@ class UserHandler
function makeUserCookie($lode,$autologin = FALSE)
/**
* Create user cookie
*
* @param array $lode - user information from DB - 'user_id' and 'user_password' required
* @param bool $autologin - TRUE if the 'Remember Me' box ticked
*
* @return none
*/
public function makeUserCookie($lode,$autologin = FALSE)
{ {
global $pref; global $pref;
$cookieval = $lode['user_id'].".".md5($lode['user_password']); // (Use extra md5 on cookie value to obscure hashed value for password) $cookieval = $lode['user_id'].'.'.md5($lode['user_password']); // (Use extra md5 on cookie value to obscure hashed value for password)
if ($pref['user_tracking'] == "session") if ($pref['user_tracking'] == 'session')
{ {
$_SESSION[$pref['cookie_name']] = $cookieval; $_SESSION[$pref['cookie_name']] = $cookieval;
} }
@ -400,21 +469,23 @@ class UserHandler
} }
// Generate an array of all the basic classes a user belongs to /**
// if $asArray TRUE, returns results in an array; else as a comma-separated string * Generate an array of all the basic classes a user belongs to
// If $incInherited is TRUE, includes inherited classes *
function addCommonClasses($userData, $asArray = FALSE, $incInherited = FALSE) * Note that the passed data may relate to the currently logged in user, or if an admin is logged in, to a different user
*
* @param array $userData - user's data record - must include the 'user_class' element
* @param boolean $asArray if TRUE, returns results in an array; else as a comma-separated string
* @param boolean $incInherited if TRUE, includes inherited classes
* @param boolean $fromAdmin - if TRUE, adds e_UC_ADMIN and e_UC_MAINADMIN in if current user's entitlement permits
*
* @return array|string of userclass information according to $asArray
*/
public function addCommonClasses($userData, $asArray = FALSE, $incInherited = FALSE, $fromAdmin = FALSE)
{ {
if ($incInherited) if ($incInherited)
{ {
$classList = array(); $classList = e107::getUserClass()->get_all_user_classes($var['user_class']);
global $e_userclass;
if (!isset($e_userclass) && !is_object($e_userclass))
{
require_once(e_HANDLER."userclass_class.php");
$e_userclass = new user_class;
}
$classList = $e_userclass->get_all_user_classes($var['user_class']);
} }
else else
{ {
@ -427,21 +498,28 @@ class UserHandler
$classList[] = $c; $classList[] = $c;
} }
} }
if ((varset($userData['user_admin'],0) == 1) && strlen($userData['user_perms'])) if (((varset($userData['user_admin'],0) == 1) && strlen($userData['user_perms'])) || ($fromAdmin && ADMIN))
{ {
$classList[] = e_UC_ADMIN; $classList[] = e_UC_ADMIN;
if (strpos($userData['user_perms'],'0') === 0) if ((strpos($userData['user_perms'],'0') === 0) || getperms('0'))
{ {
$classList[] = e_UC_MAINADMIN; $classList[] = e_UC_MAINADMIN;
} }
} }
if ($asArray) return $classList; if ($asArray) return $classList;
return implode(',',$classList); return implode(',',$classList);
} }
// Return an array of descriptive names for each field in the user DB. If $all is false, just returns the modifiable ones. Else returns all
function getNiceNames($all = FALSE) /**
* Return an array of descriptive names for each field in the user DB.
*
* @param bool $all if false, just returns modifiable fields. Else returns all
*
* $return array - key is field name, value is 'nice name' (descriptive name)
*/
public function getNiceNames($all = FALSE)
{ {
// $ret = array('user_id' => LAN_USER_13); // $ret = array('user_id' => LAN_USER_13);
foreach ($this->userVettingInfo as $k => $v) foreach ($this->userVettingInfo as $k => $v)
@ -499,9 +577,16 @@ Following fields auto-filled in code as required:
user_pwchange user_pwchange
*/ */
// Function does validation specific to user data. Updates the $targetData array as appropriate.
// Returns TRUE if nothing updated; FALSE if errors found (only checks data previously passed as good)
function userValidation(&$targetData) /**
* Function does validation specific to user data. Updates the $targetData array as appropriate.
*
* @param array $targetData - user data generated from earlier vetting stages - only the data in $targetData['data'] is checked
*
* @return bool TRUE if nothing updated; FALSE if errors found
*/
public function userValidation(&$targetData)
{ {
global $e107, $pref; global $e107, $pref;
$u_sql = new db; $u_sql = new db;
@ -556,10 +641,19 @@ Following fields auto-filled in code as required:
return $ret; return $ret;
} }
// Given an array of user data intended to be written to the DB, adds empty strings (or other default value) for any field which doesn't have a default in the SQL definition.
// (Avoids problems with MySQL in STRICT mode.).
// Returns TRUE if additions made, FALSE if no change. /**
function addNonDefaulted(&$userInfo) * Given an array of user data intended to be written to the DB, adds empty strings (or other default value) for any field which doesn't have a default in the SQL definition.
* (Avoids problems with MySQL in STRICT mode.).
*
* @param array $userInfo - user data destined for the database
*
* @return bool TRUE if additions made, FALSE if no change.
*
* @todo - may be unnecessary with auto-generation of _NOTNULL array in db handler
*/
public function addNonDefaulted(&$userInfo)
{ {
// $nonDefaulted = array('user_signature' => '', 'user_prefs' => '', 'user_class' => '', 'user_perms' => ''); // $nonDefaulted = array('user_signature' => '', 'user_prefs' => '', 'user_class' => '', 'user_perms' => '');
$nonDefaulted = array('user_signature' => '', 'user_prefs' => '', 'user_class' => '', 'user_perms' => '', 'user_realm' => ''); // Delete when McFly finished $nonDefaulted = array('user_signature' => '', 'user_prefs' => '', 'user_class' => '', 'user_perms' => '', 'user_realm' => ''); // Delete when McFly finished
@ -576,8 +670,14 @@ Following fields auto-filled in code as required:
} }
// Delete time-expired partial registrations from the user DB, clean up user_extended table /**
function deleteExpired($force = FALSE) * Delete time-expired partial registrations from the user DB, clean up user_extended table
*
* @param bool $force - set TRUE to force check of user_extended table
*
* @return int number of user records deleted
*/
public function deleteExpired($force = FALSE)
{ {
global $pref, $sql; global $pref, $sql;
$temp1 = 0; $temp1 = 0;
@ -595,10 +695,20 @@ Following fields auto-filled in code as required:
} }
// Called to update initial user classes, probationary user class etc
function userClassUpdate(&$user, $event='userveri') /**
* Called to update initial user classes, probationary user class etc after various user events
*
* @param array $user - user data. 'user_class' must be present
* @param string $event = userveri|userall|userfull|userpartial - defines event
*
* @return boolean - true if $user['user_class'] updated, false otherwise
*/
public function userClassUpdate(&$user, $event='userveri')
{ {
global $pref, $tp; global $pref;
$tp = e107::getParser();
$initClasses = array(); $initClasses = array();
$doClasses = FALSE; $doClasses = FALSE;
@ -642,14 +752,18 @@ Following fields auto-filled in code as required:
$ret = TRUE; $ret = TRUE;
} }
} }
return $ret;
} }
/** /**
* Updates user status, primarily the user_ban field, to reflect outside events * Updates user status, primarily the user_ban field, to reflect outside events
*
* @param string $start - 'ban', 'bounce' * @param string $start - 'ban', 'bounce'
* @param integer $uid - internal user ID, zero if not known * @param integer $uid - internal user ID, zero if not known
* @param string $emailAddress - email address (optional) * @param string $emailAddress - email address (optional)
*
* @return boolean | string - FALSE if user found, error message if not * @return boolean | string - FALSE if user found, error message if not
*/ */
public function userStatusUpdate($action, $uid, $emailAddress = '') public function userStatusUpdate($action, $uid, $emailAddress = '')