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

1140 lines
33 KiB
PHP
Raw Normal View History

<?php
/*
* e107 website system
*
2009-11-18 01:06:08 +00:00
* Copyright (C) 2008-2009 e107 Inc (e107.org)
* Released under the terms and conditions of the
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
*
* Handler - user-related functions
*
* $Source: /cvs_backup/e107_0.8/e107_handlers/user_handler.php,v $
* $Revision: 1.22 $
* $Date: 2010-01-31 22:21:11 $
* $Author: e107steved $
*
*/
/**
*
* @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)
*/
if (!defined('e107_INIT')) { exit; }
// Codes for `user_ban` field (not all used ATM)
define('USER_VALIDATED',0);
define('USER_BANNED',1);
define('USER_REGISTERED_NOT_VALIDATED',2);
define('USER_EMAIL_BOUNCED', 3);
define('USER_BOUNCED_RESET', 4);
define('USER_TEMPORARY_ACCOUNT', 5);
define('PASSWORD_E107_MD5',0);
define('PASSWORD_E107_SALT',1);
define('PASSWORD_E107_ID','$E$'); // E107 salted
define('PASSWORD_INVALID', FALSE);
define('PASSWORD_VALID',TRUE);
define ('PASSWORD_DEFAULT_TYPE',PASSWORD_E107_MD5);
//define ('PASSWORD_DEFAULT_TYPE',PASSWORD_E107_SALT);
// Required language file - if not loaded elsewhere, uncomment next line
//include_lan(e_LANGUAGEDIR.e_LANGUAGE.'/lan_user.php');
class UserHandler
{
var $userVettingInfo = array();
var $preferred = PASSWORD_DEFAULT_TYPE; // Preferred password format
var $passwordOpts = 0; // Copy of pref
var $passwordEmail = FALSE; // True if can use email address to log in
var $otherFields = array();
// Constructor
public function __construct()
{
global $pref;
/**
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):
0 - Null method
1 - Check for duplicates
2 - Check against $pref['signup_disallow_text']
3 - Check email address against remote server, only if option enabled
Index is the destination field name. If the source index name is different, specify 'srcName' in the array.
Possible processing options:
'dbClean' - 'sanitising' method for final value:
- 'toDB' - passes final value through $tp->toDB()
- 'intval' - converts to an integer
- 'image' - checks image for size
- 'avatar' - checks an image in the avatars directory
'stripTags' - strips HTML tags from the value (not an error if there are some)
'minLength' - minimum length (in utf-8 characters) for the string
'maxLength' - minimum length (in utf-8 characters) for the string
'longTrim' - if set, and the string exceeds maxLength, its trimmed
'enablePref' - value is processed only if the named $pref evaluates to true; otherwise any input is discarded without error
*/
$this->userVettingInfo = array(
'user_name' => array('niceName'=> LAN_USER_01, 'fieldType' => 'string', 'vetMethod' => '1,2', 'vetParam' => 'signup_disallow_text', 'srcName' => 'username', 'stripTags' => TRUE, 'stripChars' => '/&nbsp;|\#|\=|\$/', fixedBlock => 'anonymous', 'minLength' => 2, 'maxLength' => varset($pref['displayname_maxlength'],15)), // Display name
'user_loginname' => array('niceName'=> LAN_USER_02, 'fieldType' => 'string', 'vetMethod' => '1', 'vetParam' => '', 'srcName' => 'loginname', 'stripTags' => TRUE, 'stripChars' => '/&nbsp;|\#|\=|\$/', 'minLength' => 2, 'maxLength' => varset($pref['loginname_maxlength'],30)), // User name
'user_login' => array('niceName'=> LAN_USER_03, 'fieldType' => 'string', 'vetMethod' => '0', 'vetParam' => '', 'srcName' => 'realname', 'dbClean' => 'toDB'), // Real name (no real vetting)
'user_customtitle' => array('niceName'=> LAN_USER_04, 'fieldType' => 'string', 'vetMethod' => '0', 'vetParam' => '', 'srcName' => 'customtitle', 'dbClean' => 'toDB', 'enablePref' => 'signup_option_customtitle'), // No real vetting
'user_password' => array('niceName'=> LAN_USER_05, 'fieldType' => 'string', 'vetMethod' => '0', 'vetParam' => '', 'srcName' => 'password1', 'dataType' => 2, 'minLength' => varset($pref['signup_pass_len'],1)),
'user_sess' => array('niceName'=> LAN_USER_06, 'fieldType' => 'string', 'vetMethod' => '0', 'vetParam' => '', 'stripChars' => "#\"|'|(|)#", 'dbClean' => 'image', 'imagePath' => e_UPLOAD.'avatars/', 'maxHeight' => varset($pref['im_height'], 100), 'maxWidth' => varset($pref['im_width'], 120)), // Photo
'user_image' => array('niceName'=> LAN_USER_07, 'fieldType' => 'string', 'vetMethod' => '0', 'vetParam' => '', 'srcName' => 'image', 'stripChars' => "#\"|'|(|)#", 'dbClean' => 'avatar', 'maxHeight' => varset($pref['im_height'], 100), 'maxWidth' => varset($pref['im_width'], 120)), // Avatar
'user_email' => array('niceName'=> LAN_USER_08, 'fieldType' => 'string', 'vetMethod' => '1,3', 'vetParam' => '', 'fieldOptional' => varset($pref['disable_emailcheck'],0), 'srcName' => 'email', 'dbClean' => 'toDB'),
'user_signature' => array('niceName'=> LAN_USER_09, 'fieldType' => 'string', 'vetMethod' => '0', 'vetParam' => '', 'srcName' => 'signature', 'dbClean' => 'toDB'),
'user_hideemail' => array('niceName'=> LAN_USER_10, 'fieldType' => 'int', 'vetMethod' => '0', 'vetParam' => '', 'srcName' => 'hideemail', 'dbClean' => 'intval'),
'user_xup' => array('niceName'=> LAN_USER_11, 'fieldType' => 'string', 'vetMethod' => '0', 'vetParam' => '', 'srcName' => 'user_xup', 'dbClean' => 'toDB'),
'user_class' => array('niceName'=> LAN_USER_12, 'fieldType' => 'string', 'vetMethod' => '0', 'vetParam' => '', 'srcName' => 'class', 'dataType' => '1')
);
$this->otherFields = array(
'user_join' => LAN_USER_14,
'user_lastvisit' => LAN_USER_15,
'user_currentvisit' => LAN_USER_16,
'user_comments' => LAN_USER_17,
'user_ip' => LAN_USER_18,
'user_ban' => LAN_USER_19,
'user_prefs' => LAN_USER_20,
'user_visits' => LAN_USER_21,
'user_admin' => LAN_USER_22,
'user_perms' => LAN_USER_23,
'user_pwchange' => LAN_USER_24
// user_chats int(10) unsigned NOT NULL default '0',
);
$this->otherFieldTypes = array(
'user_join' => 'int',
'user_lastvisit' => 'int',
'user_currentvisit' => 'int',
'user_comments' => 'int',
'user_ip' => 'string',
'user_ban' => 'int',
'user_prefs' => 'string',
'user_visits' => 'int',
'user_admin' => 'int',
'user_perms' => 'string',
'user_pwchange' => 'int'
);
$this->passwordOpts = varset($pref['passwordEncoding'],0);
$this->passwordEmail = varset($pref['allowEmailLogin'],FALSE);
switch ($this->passwordOpts)
{
case 1 :
case 2 :
$this->preferred = PASSWORD_E107_SALT;
break;
case 0 :
default :
$this->preferred = PASSWORD_E107_MD5;
$this->passwordOpts = 0; // In case it got set to some stupid value
break;
}
return FALSE;
}
/**
* 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;
switch ($force)
{
case PASSWORD_E107_MD5 :
return md5($password);
case PASSWORD_E107_SALT :
return PASSWORD_E107_ID.md5(md5($password).$login_name);
break;
}
return FALSE;
}
/**
* Verify existing plaintext password against a stored hash value (which defines the encoding format and any 'salt')
*
* @param string $password - plaintext password as entered by user
* @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 (($this->passwordOpts <= 1) && (strlen($stored_hash) == 32))
{ // Its simple md5 encoding
if (md5($password) !== $stored_hash) return PASSWORD_INVALID;
if ($this->preferred == PASSWORD_E107_MD5) return PASSWORD_VALID;
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!
// 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))
{ // Its the standard E107 salted hash
$hash = $this->HashPassword($password, $login_name, PASSWORD_E107_SALT);
if ($hash === FALSE) return PASSWORD_INVALID;
return ($hash == $stored_hash) ? PASSWORD_VALID : PASSWORD_INVALID;
}
return PASSWORD_INVALID;
}
/**
* 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($response) != 32) return PASSWORD_INVALID;
$valid_ret = PASSWORD_VALID;
if (strlen($stored_hash) == 32)
{ // Its simple md5 password storage
$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;
}
$testval = md5(substr($stored_hash,strlen(PASSWORD_E107_ID)).$challenge);
if ($testval == $response) return $valid_ret;
return PASSWORD_INVALID;
}
/**
* Checks whether the user has to validate a change of user settings by entering password (basically, if that field affects the
* stored password value)
*
* @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;
switch ($fieldName)
{
case 'user_email' :
return $this->passwordEmail;
case 'user_loginname' :
return TRUE;
}
return FALSE;
}
/**
* 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->passwordEmail) return TRUE;
return FALSE;
}
/**
* Checks whether the password value can be converted to the current default
*
* @param string $password - hashed password
* @return bool TRUE if conversion possible, FALSE if not possible, or not needed.
*/
public 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
*
* @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)
{
if ($this->canConvert($password) === FALSE) return $password;
return PASSWORD_E107_ID.md5($password.$login_name);
}
/**
* Generates a random user login name according to some pattern.
* Checked for uniqueness.
*
* @param string $pattern - defines the format of the username
* @param int $seed - may be used with the random pattern generator
*
* @return string a user login name, guaranteed unique in the database.
*/
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 = '')
{
2009-08-08 23:09:08 +00:00
if (strlen($pattern) < 6)
$pattern = '##....';
$newname = '';
// Create alpha [A-Z][a-z]
$alpha = '';
for($i = 65; $i < 91; $i++)
{
2009-08-08 23:09:08 +00:00
$alpha .= chr($i).chr($i+32);
}
$alphaLength = strlen($alpha) - 1;
// Create digit [0-9]
$digit = '';
for($i = 48; $i < 57; $i++)
{
$digit .= chr($i);
}
$digitLength = strlen($digit) - 1;
// Create alpha numeric [A-Z][a-z]
$alphaNum = $alpha.$digit;
$alphaNumLength = strlen($alphaNum) - 1;
// Next character of seed (if used)
$seed_ptr = 0;
for ($i = 0, $patternLength = strlen($pattern); $i < $patternLength; $i++)
{
$c = $pattern[$i];
switch ($c)
{
2009-08-08 23:09:08 +00:00
// Alpha only (upper and lower case)
case '#' :
$t = rand(0, $alphaLength);
$newname .= $alpha[$t];
break;
// Numeric only - [0-9]
case '.' :
$t = rand(0, $digitLength);
$newname .= $digit[$t];
break;
// Alphanumeric
case '*' :
$t = rand(0, $alphaNumLength);
$newname .= $alphaNum[$t];
break;
// Next character from seed
case '^' :
if ($seed_ptr < strlen($seed))
{
$newname .= $seed[$seed_ptr];
$seed_ptr++;
}
break;
// (else just ignore other characters in pattern)
default :
if (strrpos($alphaNum, $c) !== FALSE)
{
$newname .= $c;
}
}
}
2009-08-08 23:09:08 +00:00
return $newname;
}
/**
* Split up an email address to check for banned domains.
* @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')
{
$tp = e107::getParser();
$tmp = strtolower($tp -> toDB(trim(substr($email, strrpos($email, "@")+1)))); // Pull out the domain name
if ($tmp == '') return FALSE;
if (strpos($tmp,'.') === FALSE) return FALSE;
$em = array_reverse(explode('.',$tmp));
$line = '';
$out = array("='*@.{$tmp}'"); // First element looks for domain as email address
foreach ($em as $e)
{
$line = '.'.$e.$line;
$out[] = '`'.$fieldname."`='*{$line}'";
}
return implode(' OR ',$out);
}
/**
* 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;
$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')
{
$_SESSION[$pref['cookie_name']] = $cookieval;
}
else
{
if ($autologin == 1)
{ // Cookie valid for up to 30 days
cookie($pref['cookie_name'], $cookieval, (time() + 3600 * 24 * 30));
}
else
{
cookie($pref['cookie_name'], $cookieval);
}
}
}
/**
* Generate an array of all the basic classes a user belongs to
*
* 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)
{
$classList = e107::getUserClass()->get_all_user_classes($var['user_class']);
}
else
{
if ($userData['user_class'] != '') $classList = explode(',',$userData['user_class']);
}
foreach (array(e_UC_MEMBER, e_UC_READONLY, e_UC_PUBLIC) as $c)
{
if (!in_array($c,$classList))
{
$classList[] = $c;
}
}
if (((varset($userData['user_admin'],0) == 1) && strlen($userData['user_perms'])) || ($fromAdmin && ADMIN))
{
$classList[] = e_UC_ADMIN;
if ((strpos($userData['user_perms'],'0') === 0) || getperms('0'))
{
$classList[] = e_UC_MAINADMIN;
}
}
if ($asArray) return $classList;
return implode(',',$classList);
}
/**
* 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);
foreach ($this->userVettingInfo as $k => $v)
{
$ret[$k] = $v['niceName'];
}
if ($all)
{
$ret = array_merge($ret, $this->otherFields);
}
return $ret;
}
//===================================================
// User Field validation
//===================================================
/* $_POST field names:
DB signup usersettings quick add function
------------------------------------------------------------------------------
user_id - user_id - Unique user ID
user_name name$ username username Display name
user_loginname loginname loginname loginname User name (login name)
user_customtitle - customtitle - Custom title
user_password password1 password1 password1 Password (prior to encoding)
password2 password2 password1 (Check password field)
user_sess * - Photo (file on server)
user_email email email email Email address
email_confirm
user_signature signature signature - User signature
user_image image image* - Avatar (may be external URL or file on server)
user_hideemail hideemail hideemail - Flag to hide user's email address
user_login realname realname realname User Real name
user_xup xupexist$ user_xup - XUP file link
user_class class class userclass User class (array on form)
user_loginname may be auto-generated
* avatar (user_image) and photo (user_sess) may be uploaded files
$changed to match the majority vote
Following fields auto-filled in code as required:
user_join
user_lastvisit
user_currentvisit
user_chats
user_comments
user_forums
user_ip
user_ban
user_prefs
user_viewed
user_visits
user_admin
user_perms
user_pwchange
*/
/**
* 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;
$u_sql = new db;
$ret = TRUE;
$errMsg = '';
if (isset($targetData['data']['user_email']))
{
$v = trim($targetData['data']['user_email']); // Always check email address if its entered
if ($v == '')
{
if (!varsettrue($pref['disable_emailcheck']))
{
$errMsg = ERR_MISSING_VALUE;
}
}
elseif (!check_email($v))
{
$errMsg = ERR_INVALID_EMAIL;
}
elseif ($u_sql->db_Count('user', '(*)', "WHERE `user_email`='".$v."' AND `user_ban`=1 "))
{
$errMsg = ERR_BANNED_USER;
}
else
{ // See if email address banned
$wc = $this->make_email_query($v); // Generate the query for the ban list
if ($wc) { $wc = "`banlist_ip`='{$v}' OR ".$wc; }
if (($wc === FALSE) || !$e107->check_ban($wc, FALSE, TRUE))
{
// echo "Email banned<br />";
$errMsg = ERR_BANNED_EMAIL;
}
}
if ($errMsg)
{
unset($targetData['data']['user_email']); // Remove the valid entry
}
}
else
{
if (!isset($targetData['errors']['user_email']) && !varset($pref['disable_emailcheck'],FALSE))
{ // We may have already picked up an error on the email address - or it may be allowed to be empty
$errMsg = ERR_MISSING_VALUE;
}
}
if ($errMsg)
{ // Update the error
$targetData['errors']['user_email'] = $errMsg;
$targetData['failed']['user_email'] = $v;
$ret = FALSE;
}
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.).
*
* @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' => '', 'user_realm' => ''); // Delete when McFly finished
$ret = FALSE;
foreach ($nonDefaulted as $k => $v)
{
if (!isset($userInfo[$k]))
{
$userInfo[$k] = $v;
$ret = TRUE;
}
}
return $ret;
}
/**
* 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;
$temp1 = 0;
if (isset($pref['del_unv']) && $pref['del_unv'] && $pref['user_reg_veri'] != 2)
{
$threshold= intval(time() - ($pref['del_unv'] * 60));
if (($temp1 = $sql->db_Delete('user', 'user_ban = 2 AND user_join < '.$threshold)) > 0) { $force = TRUE; }
}
if ($force)
{ // Remove 'orphaned' extended user field records
2009-09-28 21:32:08 +00:00
$sql->db_Select_gen("DELETE `#user_extended` FROM `#user_extended` LEFT JOIN `#user` ON `#user_extended`.`user_extended_id` = `#user`.`user_id`
WHERE `#user`.`user_id` IS NULL");
}
return $temp1;
}
/**
* 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 = e107::getParser();
$initClasses = array();
$doClasses = FALSE;
$doProbation = FALSE;
$ret = FALSE;
switch ($event)
{
case 'userall' :
$doClasses = TRUE;
$doProbation = TRUE;
break;
case 'userfull' : // A 'fully fledged' user
if (!$pref['user_reg_veri'] || ($pref['init_class_stage'] == '2'))
{
$doClasses = TRUE;
}
$doProbation = TRUE;
break;
case 'userpartial' :
if ($pref['init_class_stage'] == '1')
{ // Set initial classes if to be done on partial signup, or if selected to add them now
$doClasses = TRUE;
}
$doProbation = TRUE;
break;
}
if ($doClasses)
{
if (isset($pref['initial_user_classes'])) { $initClasses = explode(',',$pref['initial_user_classes']); } // Any initial user classes to be set at some stage
if ($doProbation && (varset($pref['user_new_period'], 0) > 0))
{
$initClasses[] = e_UC_NEWUSER; // Probationary user class
}
if (count($initClasses))
{ // Update the user classes
if ($user['user_class'])
{
$initClasses = array_unique(array_merge($initClasses, explode(',',$user['user_class'])));
}
$user['user_class'] = $tp->toDB(implode(',',$initClasses));
$ret = TRUE;
}
}
return $ret;
}
/**
* Updates user status, primarily the user_ban field, to reflect outside events
*
2009-12-16 22:26:27 +00:00
* @param string $start - 'ban', 'bounce'
* @param integer $uid - internal user ID, zero if not known
* @param string $emailAddress - email address (optional)
*
* @return boolean | string - FALSE if user found, error message if not
*/
public function userStatusUpdate($action, $uid, $emailAddress = '')
{
$db = e107::getDb();
$qry = '';
$error = FALSE; // Assume no error to start with
$uid = intval($uid); // Precautionary - should have already been done
switch ($action)
{
case 'ban' :
$newVal = USER_BANNED;
$logEvent = USER_AUDIT_BANNED;
break;
case 'bounce' :
$newVal = USER_EMAIL_BOUNCED;
$logEvent = USER_AUDIT_MAIL_BOUNCE;
break;
case 'reset' :
$newVal = USER_BOUNCED_RESET;
$logEvent = USER_AUDIT_BOUNCE_RESET;
break;
case 'temp' :
$newVal = USER_TEMPORARY_ACCOUNT;
$logEvent = USER_AUDIT_TEMP_ACCOUNT;
break;
default :
return 'Invalid action: '.$action;
}
if ($uid) { $qry = '`user_id`='.$uid; }
if ($emailAddress) { if ($qry) $qry .= ' OR '; $qry .= "`user_email` = '{$emailAddress}'"; }
if (FALSE === $db->db_Select('user', 'user_id, user_email, user_ban, user_loginname', $qry.' LIMIT 1'))
{
$error = 'User not found: '.$uid.'/'.$emailAddress;
}
else
{
$row = $db->db_Fetch(MYSQL_ASSOC);
if ($uid && ($uid != $row['user_id']))
{
$error = 'UID mismatch: '.$uid.'/'.$row['user_id'];
}
elseif ($emailAddress && ($emailAddress != $row['user_email']))
{
$error = 'User email mismatch: '.$emailAddress.'/'.$row['user_email'];
}
else
{ // Valid user!
if ($row['user_ban'] != $newVal) // We could implement a hierarchy here, so that an important status isn't overridden by a lesser one
{ // Only update if needed
$db->db_Update('user', '`user_ban` = '.$newVal.', `user_email` = \'\' WHERE `user_id` = '.$row['user_id'].' LIMIT 1');
// Add to user audit log TODO: Should we log to admin log as well?
$adminLog = e107::getAdminLog();
$adminLog->user_audit($logEvent, array('user_ban' => $newVal, 'user_email' => $row['user_email']), $row['user_id'], $row['user_loginname']);
}
}
}
return $error;
}
}
e107::includeLan(e_LANGUAGEDIR.e_LANGUAGE."/admin/lan_administrator.php");
class e_userperms
{
protected $core_perms = array(
"1"=> ADMSLAN_19,
"2"=> ADMSLAN_20,
"3"=> ADMSLAN_21,
"4"=> ADMSLAN_22, // Moderate users/bans etc
"5"=> ADMSLAN_23, // create/edit custom pages
"J"=> ADMSLAN_41, // create/edit custom menus
"Q"=> ADMSLAN_24, // Manage download categories
"6"=> ADMSLAN_25, // Upload /manage files
"Y"=> ADMSLAN_67, // file inspector
"O"=> ADMSLAN_68, // notify
"7"=> ADMSLAN_26,
"8"=> ADMSLAN_27,
"C"=> ADMSLAN_64,
"9"=> ADMSLAN_28,
"W"=> ADMSLAN_65,
"D"=> ADMSLAN_29,
"E"=> ADMSLAN_30,
"F"=> ADMSLAN_31,
"G"=> ADMSLAN_32,
"S"=> ADMSLAN_33,
"T"=> ADMSLAN_34,
"V"=> ADMSLAN_35,
"X"=> ADMSLAN_66,
"A"=> ADMSLAN_36, // Configure Image Settings
"B"=> ADMSLAN_37,
"H"=> ADMSLAN_39,
"I"=> ADMSLAN_40,
"L"=> ADMSLAN_43,
"R"=> ADMSLAN_44,
"U"=> ADMSLAN_45,
"M"=> ADMSLAN_46,
"N"=> ADMSLAN_47,
// "Z"=> ADMSLAN_62,
);
protected $plugin_perms = array();
protected $language_perms = array();
protected $main_perms = array();
protected $permSectionDiz = array(
'core' => ADMSLAN_74,
'plugin' => ADLAN_CL_7,
'language' => ADLAN_132,
'main' => ADMSLAN_58
);
function __construct()
{
$sql = e107::getDb('sql2');
$tp = e107::getParser();
$sql->db_Select("plugin", "*", "plugin_installflag='1'");
while ($row2 = $sql->db_Fetch())
{
$this->plugin_perms[("P".$row2['plugin_id'])] = LAN_PLUGIN." - ".$tp->toHTML($row2['plugin_name'], FALSE, 'RAWTEXT,defs');
}
asort($this->plugin_perms);
$this->plugin_perms = array("Z"=>ADMSLAN_62) + $this->plugin_perms;
if(e107::getConfig()->getPref('multilanguage'))
{
$lanlist = explode(",",e_LANLIST);
sort($lanlist);
foreach($lanlist as $langs)
{
$this->language_perms[$langs] = $langs;
}
}
if(getperms('0'))
{
$this->main_perms = array('0' => ADMSLAN_58);
}
}
function renderSectionDiz($key)
{
return $this->permSectionDiz[$key];
}
function getPermList($type='all')
{
if($type == 'core')
{
return $this->core_perms;
}
if($type == 'plugin')
{
return $this->plugin_perms;
}
if($type == 'language')
{
return $this->language_perms;
}
if($type == 'main')
{
return $this->main_perms;
}
if($type == 'grouped')
{
$ret = array();
$ret['core'] = $this->core_perms;
$ret['plugin'] = $this->plugin_perms;
if(vartrue($this->language_perms))
{
$ret['language'] = $this->language_perms;
}
if(vartrue($this->main_perms))
{
$ret['main'] = $this->main_perms;
}
return $ret;
}
return array_merge($this->core_perms,$this->plugin_perms,$this->language_perms,$this->main_perms);
}
function checkb($arg, $perms, $label='')
{
$frm = e107::getForm();
$par = "<div class='field-spacer'>";
$par .= $frm->checkbox('perms[]', $arg, getperms($arg, $perms));
if ($label)
{
$par .= $frm->label($label,'perms[]', $arg);
}
$par .= "</div>\n";
return $par;
}
function renderPerms($perms,$uniqueID='')
{
$tmp = explode(".",$perms);
$permdiz = $this->getPermList();
$ptext = array();
foreach($tmp as $p)
{
$ptext[] = $permdiz[$p];
}
$id = "id_".$uniqueID;
$text = "<div onclick=\"e107Helper.toggle('id_{$id}')\" class='e-pointer' title='".ADMSLAN_71."'>{$perms}</div>";
if(varset($ptext))
{
$text .= "<div id='id_{$id}' class='e-hideme'><ul><li>".implode("</li><li>",$ptext)."</li></ul></div>";
}
/*
$text = "<a href='#".$id."' class='e-expandit' title='".ADMSLAN_71."'>{$perms}</a>";
if(varset($ptext))
{
$text .= "<div class='e-hideme' id='".$id."' ><ul><li>".implode("</li><li>",$ptext)."</li></ul></div>";
}
*/
return $text;
}
/**
* Render edit admin perms form.
2009-11-17 14:50:37 +00:00
*
* @param array $row [optional] containing $row['user_id'], $row['user_name'], $row['user_perms'];
2009-11-17 14:50:37 +00:00
* @return void
*/
2009-11-17 14:50:37 +00:00
function edit_administrator($row = '')
{
2009-11-17 14:50:37 +00:00
$pref = e107::getPref();
$lanlist = explode(",", e_LANLIST);
require_once(e_HANDLER."user_handler.php");
$prm = $this;
$ns = e107::getRender();
$sql = e107::getDb();
$frm = e107::getForm();
$a_id = $row['user_id'];
$ad_name = $row['user_name'];
$a_perms = $row['user_perms'];
$text = "
<form method='post' action='".e_SELF."' id='myform'>
<fieldset id='core-administrator-edit'>
<legend class='e-hideme'>".ADMSLAN_52."</legend>
<table cellpadding='0' cellspacing='0' class='adminform'>
<colgroup span='2'>
<col class='col-label' />
<col class='col-control' />
</colgroup>
<tbody>
<tr>
<td class='label'>".ADMSLAN_16.": </td>
<td class='control'>
".$ad_name."
<input type='hidden' name='ad_name' size='60' value='{$ad_name}' />
</td>
</tr>
<tr>
<td class='label'>".ADMSLAN_18."</td>
<td class='control'>
";
$groupedList = $prm->getPermList('grouped');
foreach($groupedList as $section=>$list)
{
$text .= "\t\t<div class='field-section'><h4>".$prm->renderSectionDiz($section)."</h4>"; //XXX Lan - General
foreach($list as $key=>$diz)
{
$text .= $prm->checkb($key, $a_perms, $diz);
}
$text .= "</div>";
}
$text .= "<div class='field-section'>
".$frm->admin_button('check_all', 'jstarget:perms', 'action', LAN_CHECKALL)."
".$frm->admin_button('uncheck_all', 'jstarget:perms', 'action', LAN_UNCHECKALL)."
</div>
</td>
</tr>
</tbody>
</table>
<div class='buttons-bar center'>
<input type='hidden' name='a_id' value='{$a_id}' />
".$frm->admin_button('update_admin', ADMSLAN_52, 'update')."
".$frm->admin_button('go_back', ADMSLAN_70)."
</div>
</fieldset>
</form>
";
$ns->tablerender(ADMSLAN_52, $text);
}
/**
2009-11-17 14:50:37 +00:00
* Update user (admin) permissions.
* NOTE: exit if $uid is not an integer or is 0.
*
* @param integer $uid
* @param array $permArray eg. array('A', 'K', '1');
* @return void
*/
2009-11-17 14:50:37 +00:00
function updatePerms($uid, $permArray)
{
global $admin_log;
$sql = e107::getDb();
$tp = e107::getParser();
$modID = intval($uid);
if ($modID == 0)
{
2009-11-17 14:50:37 +00:00
exit();
}
$sql->db_Select("user", "*", "user_id=".$modID);
$row = $sql->db_Fetch();
$a_name = $row['user_name'];
$perm = "";
foreach($permArray as $value)
{
$value = $tp->toDB($value);
if ($value == "0")
{
if (!getperms('0')) { $value = ""; break; }
$perm = "0"; break;
}
if ($value)
{
$perm .= $value.".";
}
2009-11-17 14:50:37 +00:00
}
admin_update($sql->db_Update("user", "user_perms='{$perm}' WHERE user_id='{$modID}' "), 'update', sprintf(ADMSLAN_2, $tp->toDB($_POST['ad_name'])), false, false);
$logMsg = str_replace(array('--ID--', '--NAME--'),array($modID, $a_name),ADMSLAN_72).$perm;
$admin_log->log_event('ADMIN_01',$logMsg,E_LOG_INFORMATIVE,'');
}
2009-11-17 14:50:37 +00:00
}