Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Thu, Feb 6, 11:17 PM

in-portal

Index: branches/5.1.x/core/kernel/session/session.php
===================================================================
--- branches/5.1.x/core/kernel/session/session.php (revision 13431)
+++ branches/5.1.x/core/kernel/session/session.php (revision 13432)
@@ -1,1314 +1,1321 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
/*
The session works the following way:
1. When a visitor loads a page from the site the script checks if cookies_on varibale has been passed to it as a cookie.
2. If it has been passed, the script tries to get Session ID (SID) from the request:
3. Depending on session mode the script is getting SID differently.
The following modes are available:
- AUTO
Automatic mode: if cookies are on at the client side, the script relays only on cookies and
ignore all other methods of passing SID. If cookies are off at the client side, the script relays on SID
passed through query string and referal passed by the client. THIS METHOD IS NOT 100% SECURE, as long as
attacker may get SID and substitude referal to gain access to user' session. One of the faults of this method
is that the session is only created when the visitor clicks the first link on the site, so there
is NO session at the first load of the page. (Actually there is a session, but it gets lost after
the first click because we do not use SID in query string while we are not sure if we need it)
- smCOOKIES_ONLY
Cookies only: in this mode the script relays solely on cookies passed from the browser and ignores
all other methods. In this mode there is no way to use sessions for clients without cookies support
or cookies support disabled. The cookies are stored with the full domain name and path to base-directory
of script installation.
- smGET_ONLY
GET only: the script will not set any cookies and will use only SID passed in query string using GET,
it will also check referal. The script will set SID at the first load of the page
- smCOOKIES_AND_GET
Combined mode: the script will use both cookies and GET right from the start. If client has cookies enabled,
the script will check SID stored in cookie and passed in query string, and will use this SID only if both
cookie and query string matches. However if cookies are disabled on the client side, the script will work
the same way as in GET_ONLY mode.
4. After the script has the SID it tries to load it from the Storage (default is database)
5. If such SID is found in the database, the script checks its expiration time. If session is not expired,
it updates its expiration, and resend the cookie (if applicable to session mode)
6. Then the script loads all the data (session variables) pertaining to the SID.
Usage:
$session = new Session(smAUTO); //smAUTO is default, you could just leave the brackets empty, or provide another mode
$session->SetCookieDomain('my.domain.com');
$session->SetCookiePath('/myscript');
$session->SetCookieName('my_sid_cookie');
$session->SetGETName('sid');
$session->InitSession();
...
//link output:
echo "<a href='index.php?'". ( $session->NeedQueryString() ? 'sid='.$session->SID : '' ) .">My Link</a>";
*/
/**
* Implements Session Store in the Database
*
*/
class SessionStorage extends kDBBase {
var $Expiration;
var $SessionTimeout=0;
var $DirectVars = Array();
var $ChangedDirectVars = Array();
var $PersistentVars = Array ();
var $OriginalData=Array();
var $TimestampField;
var $SessionDataTable;
var $DataValueField;
var $DataVarField;
function Init($prefix,$special)
{
parent::Init($prefix,$special);
$this->setTableName('sessions');
$this->setIDField('sid');
$this->TimestampField = 'expire';
$this->SessionDataTable = 'SessionData';
$this->DataValueField = 'value';
$this->DataVarField = 'var';
}
function setSessionTimeout($new_timeout)
{
$this->SessionTimeout = $new_timeout;
}
/**
* Calculates browser signature
*
* @return string
*/
function _getBrowserSignature()
{
$signature_parts = Array(
'HTTP_USER_AGENT', 'SERVER_PROTOCOL',
'HTTP_ACCEPT_CHARSET', 'HTTP_ACCEPT_ENCODING', 'HTTP_ACCEPT_LANGUAGE'
);
$ret = '';
foreach ($signature_parts as $signature_part) {
if (array_key_exists($signature_part, $_SERVER)) {
$ret .= '&|&' . $_SERVER[$signature_part];
}
}
return md5( substr($ret, 3) );
}
function StoreSession(&$session, $additional_fields = Array())
{
if (defined('IS_INSTALL') && IS_INSTALL && !$this->Application->TableFound($this->TableName)) {
return false;
}
$fields_hash = Array (
$this->IDField => $session->SID,
$this->TimestampField => $session->Expiration,
);
if (!defined('IS_INSTALL') || !IS_INSTALL) {
// this column was added only in 5.0.1 version,
// so accessing it while database is not upgraded
// will result in admin's inability to login inside
// installator
$fields_hash['BrowserSignature'] = $this->_getBrowserSignature();
}
// default values + additional values + values set during this script run
$additional_fields = array_merge($additional_fields, $this->DirectVars); // used 2 times later
$fields_hash = array_merge($fields_hash, $additional_fields);
$this->Conn->doInsert($fields_hash, $this->TableName);
foreach ($additional_fields as $field_name => $field_value) {
$this->SetField($session, $field_name, $field_value);
}
}
function DeleteSession(&$session)
{
$query = ' DELETE FROM '.$this->TableName.' WHERE '.$this->IDField.' = '.$this->Conn->qstr($session->SID);
$this->Conn->Query($query);
$query = ' DELETE FROM '.$this->SessionDataTable.' WHERE '.$this->IDField.' = '.$this->Conn->qstr($session->SID);
$this->Conn->Query($query);
$this->DirectVars = $this->ChangedDirectVars = $this->OriginalData = Array();
}
function UpdateSession(&$session, $timeout=0)
{
$this->SetField($session, $this->TimestampField, $session->Expiration);
$query = ' UPDATE '.$this->TableName.' SET '.$this->TimestampField.' = '.$session->Expiration.' WHERE '.$this->IDField.' = '.$this->Conn->qstr($session->SID);
$this->Conn->Query($query);
}
function LocateSession($sid)
{
$sql = 'SELECT *
FROM ' . $this->TableName . '
WHERE ' . $this->IDField . ' = ' . $this->Conn->qstr($sid);
$result = $this->Conn->GetRow($sql);
if ($result === false) {
return false;
}
// perform security checks to ensure, that session is used by it's creator
if ($this->Application->ConfigValue('SessionBrowserSignatureCheck') && ($result['BrowserSignature'] != $this->_getBrowserSignature())) {
return false;
}
if ($this->Application->ConfigValue('SessionIPAddressCheck') && ($result['IpAddress'] != $_SERVER['REMOTE_ADDR'])) {
// most secure, except for cases where NAT (Network Address Translation)
// is used and two or more computers can have same IP address
return false;
}
$this->DirectVars = $result;
$this->Expiration = $result[$this->TimestampField];
return true;
}
function GetExpiration()
{
return $this->Expiration;
}
function LoadData(&$session)
{
$query = 'SELECT '.$this->DataValueField.','.$this->DataVarField.' FROM '.$this->SessionDataTable.' WHERE '.$this->IDField.' = '.$this->Conn->qstr($session->SID);
$this->OriginalData = $this->Conn->GetCol($query, $this->DataVarField);
return $this->OriginalData;
}
/**
* Enter description here...
*
* @param Session $session
* @param string $var_name
* @param mixed $default
*/
function GetField(&$session, $var_name, $default = false)
{
return isset($this->DirectVars[$var_name]) ? $this->DirectVars[$var_name] : $default;
//return $this->Conn->GetOne('SELECT '.$var_name.' FROM '.$this->TableName.' WHERE `'.$this->IDField.'` = '.$this->Conn->qstr($session->GetID()) );
}
function SetField(&$session, $var_name, $value)
{
$value_changed = !isset($this->DirectVars[$var_name]) || ($this->DirectVars[$var_name] != $value);
if ($value_changed) {
$this->DirectVars[$var_name] = $value;
$this->ChangedDirectVars[] = $var_name;
$this->ChangedDirectVars = array_unique($this->ChangedDirectVars);
}
//return $this->Conn->Query('UPDATE '.$this->TableName.' SET '.$var_name.' = '.$this->Conn->qstr($value).' WHERE '.$this->IDField.' = '.$this->Conn->qstr($session->GetID()) );
}
function SaveData(&$session)
{
if(!$session->SID) return false; // can't save without sid
$ses_data = $session->Data->GetParams();
$replace = '';
foreach ($ses_data as $key => $value)
{
if ( isset($this->OriginalData[$key]) && $this->OriginalData[$key] == $value)
{
continue; //skip unchanged session data
}
else
{
$replace .= sprintf("(%s, %s, %s),",
$this->Conn->qstr($session->SID),
$this->Conn->qstr($key),
$this->Conn->qstr($value));
}
}
$replace = rtrim($replace, ',');
if ($replace != '') {
$query = ' REPLACE INTO '.$this->SessionDataTable. ' ('.$this->IDField.', '.$this->DataVarField.', '.$this->DataValueField.') VALUES '.$replace;
$this->Conn->Query($query);
}
if ($this->ChangedDirectVars) {
$changes = array();
foreach ($this->ChangedDirectVars as $var) {
$changes[] = $var.' = '.$this->Conn->qstr($this->DirectVars[$var]);
}
$query = 'UPDATE '.$this->TableName.' SET '.implode(',', $changes).' WHERE '.$this->IDField.' = '.$this->Conn->qstr($session->GetID());
$this->Conn->Query($query);
}
}
function RemoveFromData(&$session, $var)
{
$query = 'DELETE FROM '.$this->SessionDataTable.' WHERE '.$this->IDField.' = '.$this->Conn->qstr($session->SID).
' AND '.$this->DataVarField.' = '.$this->Conn->qstr($var);
$this->Conn->Query($query);
unset($this->OriginalData[$var]);
}
function GetFromData(&$session, $var, $default = false)
{
return array_key_exists($var, $this->OriginalData) ? $this->OriginalData[$var] : $default;
}
function GetExpiredSIDs()
{
- $query = ' SELECT '.$this->IDField.' FROM '.$this->TableName.' WHERE '.$this->TimestampField.' > '.adodb_mktime();
- return $this->Conn->GetCol($query);
+ $sql = 'SELECT ' . $this->IDField . '
+ FROM ' . $this->TableName . '
+ WHERE ' . $this->TimestampField . ' > ' . adodb_mktime();
+
+ return $this->Conn->GetCol($sql);
}
function DeleteExpired()
{
$expired_sids = $this->GetExpiredSIDs();
+
if ($expired_sids) {
$sessionlog_table = $this->Application->getUnitOption('session-log', 'TableName');
- $session_log_sql =
- ' UPDATE '.$sessionlog_table.'
- SET Status = 2, SessionEnd =
- ( SELECT '.$this->TimestampField.' - '.$this->SessionTimeout.'
- FROM '.$this->TableName.'
- WHERE '.$this->IDField.' = '.$sessionlog_table.'.SessionId
- )
- WHERE Status = 0 AND SessionId IN ('.join(',', $expired_sids).')';
+
if ($sessionlog_table) {
+ $sub_select = ' SELECT ' . $this->TimestampField . ' - ' . $this->SessionTimeout . '
+ FROM ' . $this->TableName . '
+ WHERE ' . $this->IDField . ' = ' . $sessionlog_table . '.SessionId';
+
+ $session_log_sql =
+ ' UPDATE ' . $sessionlog_table . '
+ SET Status = ' . SESSION_LOG_EXPIRED . ', SessionEnd = (' . $sub_select . ')
+ WHERE Status = ' . SESSION_LOG_ACTIVE . ' AND SessionId IN (' . implode(',', $expired_sids) . ')';
$this->Conn->Query($session_log_sql);
}
- $where_clause = ' WHERE '.$this->IDField.' IN ("'.implode('","',$expired_sids).'")';
- $sql = 'DELETE FROM '.$this->SessionDataTable.$where_clause;
+ $where_clause = ' WHERE ' . $this->IDField . ' IN ("' . implode('","', $expired_sids) . '")';
+
+ $sql = 'DELETE FROM ' . $this->SessionDataTable . $where_clause;
$this->Conn->Query($sql);
- $sql = 'DELETE FROM '.$this->TableName.$where_clause;
+ $sql = 'DELETE FROM ' . $this->TableName . $where_clause;
$this->Conn->Query($sql);
// delete debugger ouputs left of expired sessions
foreach ($expired_sids as $expired_sid) {
$debug_file = WRITEABLE . '/cache/debug_@' . $expired_sid . '@.txt';
if (file_exists($debug_file)) {
@unlink($debug_file);
}
}
}
+
return $expired_sids;
}
function LoadPersistentVars(&$session)
{
$user_id = $session->RecallVar('user_id');
if ($user_id != -2) {
// root & normal users
$sql = 'SELECT VariableValue, VariableName
FROM '.TABLE_PREFIX.'PersistantSessionData
WHERE PortalUserId = '.$user_id;
$this->PersistentVars = $this->Conn->GetCol($sql, 'VariableName');
}
else {
$this->PersistentVars = Array ();
}
}
/**
* Stores variable to persistent session
*
* @param Session $session
* @param string $var_name
* @param mixed $var_value
*/
function StorePersistentVar(&$session, $var_name, $var_value)
{
$user_id = $session->RecallVar('user_id');
if ($user_id == -2 || $user_id === false) {
// -2 (when not logged in), false (when after u:OnLogout event)
$session->StoreVar($var_name, $var_value);
return ;
}
$this->PersistentVars[$var_name] = $var_value;
$key_clause = 'PortalUserId = '.$user_id.' AND VariableName = '.$this->Conn->qstr($var_name);
$sql = 'SELECT VariableName
FROM '.TABLE_PREFIX.'PersistantSessionData
WHERE '.$key_clause;
$record_found = $this->Conn->GetOne($sql);
$fields_hash = Array (
'PortalUserId' => $user_id,
'VariableName' => $var_name,
'VariableValue' => $var_value,
);
if ($record_found) {
$this->Conn->doUpdate($fields_hash, TABLE_PREFIX.'PersistantSessionData', $key_clause);
}
else {
$this->Conn->doInsert($fields_hash, TABLE_PREFIX.'PersistantSessionData');
}
}
/**
* Gets persistent variable
*
* @param Session $session
* @param string $var_name
* @param mixed $default
* @return mixed
*/
function RecallPersistentVar(&$session, $var_name, $default = false)
{
if ($session->RecallVar('user_id') == -2) {
if ($default == ALLOW_DEFAULT_SETTINGS) {
$default = null;
}
return $session->RecallVar($var_name, $default);
}
if (array_key_exists($var_name, $this->PersistentVars)) {
return $this->PersistentVars[$var_name];
}
elseif ($default == ALLOW_DEFAULT_SETTINGS) {
$default_user_id = $this->Application->ConfigValue('DefaultSettingsUserId');
if (!$default_user_id) {
$default_user_id = -1;
}
$sql = 'SELECT VariableValue, VariableName
FROM '.TABLE_PREFIX.'PersistantSessionData
WHERE VariableName = '.$this->Conn->qstr($var_name).' AND PortalUserId = '.$default_user_id;
$value = $this->Conn->GetOne($sql);
$this->PersistentVars[$var_name] = $value;
if ($value !== false) {
$this->StorePersistentVar($session, $var_name, $value); //storing it, so next time we don't load default user setting
}
return $value;
}
else {
return $default;
}
}
function RemovePersistentVar(&$session, $var_name)
{
unset($this->PersistentVars[$var_name]);
$user_id = $session->RecallVar('user_id');
if ($user_id != -2) {
$sql = 'DELETE FROM '.TABLE_PREFIX.'PersistantSessionData
WHERE PortalUserId = '.$user_id.' AND VariableName = '.$this->Conn->qstr($var_name);
$this->Conn->Query($sql);
}
}
}
define('smAUTO', 1);
define('smCOOKIES_ONLY', 2);
define('smGET_ONLY', 3);
define('smCOOKIES_AND_GET', 4);
class Session extends kBase {
var $Checkers;
var $Mode;
var $OriginalMode = null;
var $GETName = 'sid';
var $CookiesEnabled = true;
var $CookieName = 'sid';
var $CookieDomain;
var $CookiePath;
var $CookieSecure = 0;
var $SessionTimeout = 3600;
var $Expiration;
var $SID;
var $CachedSID;
var $SessionSet = false;
/**
* Session ID is used from GET
*
* @var bool
*/
var $_fromGet = false;
/**
* Enter description here...
*
* @var SessionStorage
*/
var $Storage;
var $CachedNeedQueryString = null;
/**
* Session Data array
*
* @var Params
*/
var $Data;
/**
* Names of optional session keys with their optional values (which does not need to be always stored)
*
* @var Array
*/
var $OptionalData = Array ();
/**
* Session expiration mark
*
* @var bool
*/
var $expired = false;
function Session($mode = smAUTO)
{
parent::kBase();
$this->SetMode($mode);
}
function SetMode($mode)
{
$this->Mode = $mode;
$this->CachedNeedQueryString = null;
$this->CachedSID = null;
}
function SetCookiePath($path)
{
$this->CookiePath = str_replace(' ', '%20', $path);
}
/**
* Setting cookie domain. Set false for local domains, because they don't contain dots in their names.
*
* @param string $domain
*/
function SetCookieDomain($domain)
{
$this->CookieDomain = substr_count($domain, '.') ? '.'.ltrim($domain, '.') : false;
}
function SetGETName($get_name)
{
$this->GETName = $get_name;
}
function SetCookieName($cookie_name)
{
$this->CookieName = $cookie_name;
}
function InitStorage($special)
{
$this->Storage =& $this->Application->recallObject('SessionStorage.'.$special);
$this->Storage->setSessionTimeout($this->SessionTimeout);
}
function Init($prefix,$special)
{
parent::Init($prefix,$special);
$this->CheckIfCookiesAreOn();
if ($this->CookiesEnabled) $_COOKIE['cookies_on'] = 1;
$this->Checkers = Array();
$this->InitStorage($special);
$this->Data = new Params();
$tmp_sid = $this->GetPassedSIDValue();
$check = $this->Check();
if ($this->Application->isAdmin) {
// 1. Front-End session may not be created (SID is present, but no data in database).
// Check expiration LATER from kApplication::Init, because template, used in session
// expiration redirect should be retrieved from mod-rewrite url first.
// 2. Admin sessions are always created, so case when SID is present,
// but session in database isn't is 100% session expired. Check expiration
// HERE because Session::SetSession will create missing session in database
// and when Session::ValidateExpired will be called later from kApplication::Init
// it won't consider such session as expired !!!
$this->ValidateExpired();
}
if ($check) {
$this->SID = $this->GetPassedSIDValue();
$this->Refresh();
$this->LoadData();
}
else {
$this->SetSession();
}
if (!is_null($this->OriginalMode)) $this->SetMode($this->OriginalMode);
}
function ValidateExpired()
{
if (defined('IS_INSTALL') && IS_INSTALL) {
return ;
}
- $this->DeleteExpired();
+// $this->DeleteExpired(); // called from u:OnDeleteExpiredSessions agent now
if ($this->expired || ($this->CachedSID && !$this->_fromGet && !$this->SessionSet)) {
$this->RemoveSessionCookie();
// true was here to force new session creation, but I (kostja) used
// RemoveCookie a line above, to avoid redirect loop with expired sid
// not being removed setSession with true was used before, to set NEW
// session cookie
$this->SetSession();
// case #1: I've OR other site visitor expired my session
// case #2: I have no session in database, but SID is present
$this->expired = false;
$expire_event = new kEvent('u:OnSessionExpire');
$this->Application->HandleEvent($expire_event);
}
}
/**
* This is redirect from https to http or via versa
*
* @return bool
*/
function IsHTTPSRedirect()
{
$http_referer = array_key_exists('HTTP_REFERER', $_SERVER) ? $_SERVER['HTTP_REFERER'] : false;
return (
( PROTOCOL == 'https://' && preg_match('#http:\/\/#', $http_referer) )
||
( PROTOCOL == 'http://' && preg_match('#https:\/\/#', $http_referer) )
);
}
/**
* Helper method for detecting cookie availability
*
* @return bool
*/
function _checkCookieReferer()
{
// removing /admin for compatability with in-portal (in-link/admin/add_link.php)
$path = preg_replace('/admin[\/]{0,1}$/', '', $this->CookiePath);
$reg = '#^'.preg_quote(PROTOCOL.ltrim($this->CookieDomain, '.').$path).'#';
return preg_match($reg, getArrayValue($_SERVER, 'HTTP_REFERER') );
}
function CheckIfCookiesAreOn()
{
if ($this->Mode == smGET_ONLY) {
//we don't need to bother checking if we would not use it
$this->CookiesEnabled = false;
return;
}
$http_query =& $this->Application->recallObject('HTTPQuery');
$cookies_on = array_key_exists('cookies_on', $http_query->Cookie); // not good here
$get_sid = getArrayValue($http_query->Get, $this->GETName);
if ($this->IsHTTPSRedirect() && $get_sid) { // Redirect from http to https on different domain
$this->OriginalMode = $this->Mode;
$this->SetMode(smGET_ONLY);
}
if (!$cookies_on || $this->IsHTTPSRedirect()) {
//If referer is our server, but we don't have our cookies_on, it's definetly off
$is_install = defined('IS_INSTALL') && IS_INSTALL;
if (!$is_install && $this->_checkCookieReferer() && !$this->Application->GetVar('admin') && !$this->IsHTTPSRedirect()) {
$this->CookiesEnabled = false;
}
else {
//Otherwise we still suppose cookies are on, because may be it's the first time user visits the site
//So we send cookies on to get it next time (when referal will tell us if they are realy off
$this->SetCookie('cookies_on', 1, adodb_mktime() + 31104000); //one year should be enough
}
}
else {
$this->CookiesEnabled = true;
}
return $this->CookiesEnabled;
}
/**
* Sets cookie for current site using path and domain
*
* @param string $name
* @param mixed $value
* @param int $expires
*/
function SetCookie($name, $value, $expires = null)
{
if (isset($expires) && $expires < adodb_mktime()) {
unset($this->Application->HttpQuery->Cookie[$name]);
}
else {
$this->Application->HttpQuery->Cookie[$name] = $value;
}
setcookie($name, $value, $expires, $this->CookiePath, $this->CookieDomain, $this->CookieSecure);
}
function Check()
{
// don't check referer here, because it doesn't provide any security option and can be easily falsified
$sid = $this->GetPassedSIDValue();
if (empty($sid)) {
return false;
}
//try to load session by sid, if everything is fine
$result = $this->LoadSession($sid);
$this->SessionSet = $result; // fake front-end session will given "false" here
return $result;
}
function LoadSession($sid)
{
if( $this->Storage->LocateSession($sid) ) {
// if we have session with such SID - get its expiration
$this->Expiration = $this->Storage->GetExpiration();
// If session has expired
if ($this->Expiration < adodb_mktime()) {
// when expired session is loaded, then SID is
// not assigned, but used in Destroy method
$this->SID = $sid;
$this->Destroy();
$this->expired = true;
// when Destory methods calls SetSession inside and new session get created
return $this->SessionSet;
}
// Otherwise it's ok
return true;
}
else {
// fake or deleted due to expiration SID
if (!$this->_fromGet) {
$this->expired = true;
}
return false;
}
}
function GetPassedSIDValue($use_cache = 1)
{
if (!empty($this->CachedSID) && $use_cache) {
return $this->CachedSID;
}
$http_query =& $this->Application->recallObject('HTTPQuery');
$get_sid = getArrayValue($http_query->Get, $this->GETName);
$sid_from_get = $get_sid ? true : false;
if ($this->Application->GetVar('admin') == 1 && $get_sid) {
$sid = $get_sid;
}
else {
switch ($this->Mode) {
case smAUTO:
//Cookies has the priority - we ignore everything else
$sid = $this->CookiesEnabled ? $this->GetSessionCookie() : $get_sid;
if ($this->CookiesEnabled) {
$sid_from_get = false;
}
break;
case smCOOKIES_ONLY:
$sid = $this->GetSessionCookie();
break;
case smGET_ONLY:
$sid = $get_sid;
break;
case smCOOKIES_AND_GET:
$cookie_sid = $this->GetSessionCookie();
//both sids should match if cookies are enabled
if (!$this->CookiesEnabled || ($cookie_sid == $get_sid)) {
$sid = $get_sid; //we use get here just in case cookies are disabled
}
else {
$sid = '';
$sid_from_get = false;
}
break;
}
}
$this->CachedSID = $sid;
$this->_fromGet = $sid_from_get;
return $this->CachedSID;
}
/**
* Returns session id
*
* @return int
* @access public
*/
function GetID()
{
return $this->SID;
}
/**
* Generates new session id
*
* @return int
* @access private
*/
function GenerateSID()
{
list ($usec, $sec) = explode(' ', microtime());
$sid_part_1 = substr($usec, 4, 4);
$sid_part_2 = mt_rand(1, 9);
$sid_part_3 = substr($sec, 6, 4);
$digit_one = substr($sid_part_1, 0, 1);
if ($digit_one == 0) {
$digit_one = mt_rand(1, 9);
$sid_part_1 = preg_replace('/^0/', '', $sid_part_1);
$sid_part_1 = $digit_one . $sid_part_1;
}
$this->setSID($sid_part_1 . $sid_part_2 . $sid_part_3);
return $this->SID;
}
/**
* Set's new session id
*
* @param int $new_sid
* @access private
*/
function setSID($new_sid)
{
$this->SID /*= $this->CachedSID*/ = $new_sid; // don't set cached sid here
$this->Application->SetVar($this->GETName,$new_sid);
}
function NeedSession()
{
$data = $this->Data->GetParams();
$data_keys = array_keys($data);
$optional_keys = array_keys($this->OptionalData);
$real_keys = array_diff($data_keys, $optional_keys);
return $real_keys ? true : false;
}
function SetSession($force = false)
{
if ($this->SessionSet && !$force) {
return true;
}
if (!$force && !($this->Application->isAdmin || $this->Application->GetVar('admin')) && !$this->NeedSession()) {
// don't create session (in db) on Front-End, when sid is present (GPC), but data in db isn't
if ($this->_fromGet) {
// set sid, that was given in GET
$this->setSID( $this->GetPassedSIDValue() );
} else {
// re-generate sid only, when cookies are used
$this->GenerateSID();
}
return false;
}
if (!$this->SID || $force) {
$this->GenerateSID();
}
$this->Expiration = adodb_mktime() + $this->SessionTimeout;
switch ($this->Mode) {
case smAUTO:
if ($this->CookiesEnabled) {
$this->SetSessionCookie();
}
break;
case smGET_ONLY:
break;
case smCOOKIES_ONLY:
case smCOOKIES_AND_GET:
$this->SetSessionCookie();
break;
}
$this->Storage->StoreSession($this);
if ($this->Application->isAdmin || $this->Special == 'admin') {
$this->StoreVar('admin', 1);
}
$this->SessionSet = true; // should be called before SaveData, because SaveData will try to SetSession again
if ($this->Special != '') {
// front-session called from admin or otherwise, then save it's data
$this->SaveData();
}
$this->Application->resetCounters('UserSession');
return true;
}
/**
* Returns SID from cookie.
*
* Use 2 cookies to have 2 expiration:
* - 1. for normal expiration when browser is not closed (30 minutes by default), configurable
* - 2. for advanced expiration when browser is closed
*
* @return int
*/
function GetSessionCookie()
{
$keep_session_on_browser_close = $this->Application->ConfigValue('KeepSessionOnBrowserClose');
if (isset($this->Application->HttpQuery->Cookie[$this->CookieName]) &&
( $keep_session_on_browser_close ||
(
!$keep_session_on_browser_close &&
isset($this->Application->HttpQuery->Cookie[$this->CookieName.'_live'])
&&
$this->Application->HttpQuery->Cookie[$this->CookieName] == $this->Application->HttpQuery->Cookie[$this->CookieName.'_live']
)
)
) {
return $this->Application->HttpQuery->Cookie[$this->CookieName];
}
return false;
}
/**
* Updates SID in cookie with new value
*
*/
function SetSessionCookie()
{
$this->SetCookie($this->CookieName, $this->SID, $this->Expiration);
$this->SetCookie($this->CookieName.'_live', $this->SID);
$_COOKIE[$this->CookieName] = $this->SID; // for compatibility with in-portal
}
function RemoveSessionCookie()
{
$this->SetCookie($this->CookieName, '');
$this->SetCookie($this->CookieName.'_live', '');
$_COOKIE[$this->CookieName] = null; // for compatibility with in-portal
}
/**
* Refreshes session expiration time
*
* @access private
*/
function Refresh()
{
if ($this->Application->GetVar('skip_session_refresh')) {
return ;
}
if ($this->CookiesEnabled) {
// we need to refresh the cookie
$this->SetSessionCookie();
}
$this->Storage->UpdateSession($this);
}
function Destroy()
{
$this->Storage->DeleteSession($this);
$this->Data = new Params();
$this->SID = $this->CachedSID = '';
$this->SessionSet = false;
if ($this->CookiesEnabled) {
$this->SetSessionCookie(); //will remove the cookie due to value (sid) is empty
}
$this->SetSession(true); //will create a new session, true to force
}
function NeedQueryString($use_cache = 1)
{
if ($this->CachedNeedQueryString != null && $use_cache) {
return $this->CachedNeedQueryString;
}
$result = false;
switch ($this->Mode) {
case smAUTO:
if (!$this->CookiesEnabled) {
$result = true;
}
break;
/*case smCOOKIES_ONLY:
break;*/
case smGET_ONLY:
case smCOOKIES_AND_GET:
$result = true;
break;
}
$this->CachedNeedQueryString = $result;
return $result;
}
function LoadData()
{
$this->Data->AddParams($this->Storage->LoadData($this));
}
function PrintSession($comment = '')
{
if (defined('DEBUG_MODE') && $this->Application->isDebugMode() && constOn('DBG_SHOW_SESSIONDATA')) {
// dump session data
$this->Application->Debugger->appendHTML('SessionStorage [' . ($this->RecallVar('admin') == 1 ? 'Admin' : 'Front-End') . '] ('.$comment.'):');
$session_data = $this->Data->GetParams();
ksort($session_data);
foreach ($session_data as $session_key => $session_value) {
if (IsSerialized($session_value)) {
$session_data[$session_key] = unserialize($session_value);
}
}
$this->Application->Debugger->dumpVars($session_data);
if (!$this->RecallVar('admin')) {
// dump real keys (only for front-end)
$data_keys = array_keys($session_data);
$optional_keys = array_keys($this->OptionalData);
$real_keys = array_diff($data_keys, $optional_keys);
if ($real_keys) {
$ret = '';
foreach ($real_keys as $real_key) {
$ret .= '[' . $real_key . '] = [' . $session_data[$real_key] . ']<br/>';
}
$this->Application->Debugger->appendHTML('Real Keys:<br/> ' . $ret);
}
}
}
if (defined('DEBUG_MODE') && $this->Application->isDebugMode() && constOn('DBG_SHOW_PERSISTENTDATA')) {
// dump persistent session data
if ($this->Storage->PersistentVars) {
$this->Application->Debugger->appendHTML('Persistant Session:');
$session_data = $this->Storage->PersistentVars;
ksort($session_data);
foreach ($session_data as $session_key => $session_value) {
if (IsSerialized($session_value)) {
$session_data[$session_key] = unserialize($session_value);
}
}
$this->Application->Debugger->dumpVars($session_data);
}
}
}
function SaveData($params = Array ())
{
if (!$this->SetSession()) { // call it here - it may be not set before, because there was no need; if there is a need, it will be set here
return;
}
if (!$this->Application->GetVar('skip_last_template') && $this->Application->GetVar('ajax') != 'yes') {
$this->SaveLastTemplate( $this->Application->GetVar('t'), $params );
}
$this->PrintSession('after save');
$this->Storage->SaveData($this);
}
/**
* Save last template
*
* @param string $t
* @param Array $params
*/
function SaveLastTemplate($t, $params = Array ())
{
$wid = $this->Application->GetVar('m_wid');
$last_env = $this->getLastTemplateENV($t, Array('m_opener' => 'u'));
$last_template = basename($_SERVER['PHP_SELF']).'|'.mb_substr($last_env, mb_strlen(ENV_VAR_NAME) + 1);
$this->StoreVar(rtrim('last_template_'.$wid, '_'), $last_template);
// prepare last_template for opener stack, module & session could be added later
$last_env = $this->getLastTemplateENV($t, null, false);
$last_template = basename($_SERVER['PHP_SELF']).'|'.mb_substr($last_env, mb_strlen(ENV_VAR_NAME) + 1);
// save last_template in persistant session
if (!$wid) {
if ($this->Application->isAdmin) {
// only for main window, not popups, not login template, not temp mode (used in adm:MainFrameLink tag)
$temp_mode = false;
$passed = explode(',', $this->Application->GetVar('passed'));
foreach ($passed as $passed_prefix) {
if ($this->Application->GetVar($passed_prefix.'_mode')) {
$temp_mode = true;
break;
}
}
if (!$temp_mode) {
if (isset($this->Application->HttpQuery->Get['section'])) {
// check directly in GET, bacause LinkVar (session -> request) used on these vars
$last_template .= '&section='.$this->Application->GetVar('section').'&module='.$this->Application->GetVar('module');
}
$this->StorePersistentVar('last_template_popup', $last_template);
}
}
elseif ($this->Application->GetVar('admin')) {
// admin checking by session data to prevent recursive session save
static $admin_saved = null;
if (!$this->RecallVar('admin') && !isset($admin_saved)) {
// bug: we get recursion in this place, when cookies are disabled in browser and we are browsing
// front-end in admin's frame (front-end session is initialized using admin's sid and they are
// mixed together)
$admin_saved = true;
$admin_session =& $this->Application->recallObject('Session.admin');
/* @var $admin_session Session */
// save to admin last_template too, because when F5 is pressed in frameset Front-End frame should reload as well
$admin_session->StoreVar('last_template_popup', '../' . $last_template);
$admin_session->StorePersistentVar('last_template_popup', '../' . $last_template);
$admin_session->SaveData( Array ('save_last_template' => false) );
}
else {
// don't allow admin=1 & editing_mode=* to get in admin last_template
$last_template = preg_replace('/&(admin|editing_mode)=[\d]/', '', $last_template);
}
}
}
// save other last... variables for mistical purposes (customizations may be)
$this->StoreVar('last_url', $_SERVER['REQUEST_URI']); // needed by ord:StoreContinueShoppingLink
$this->StoreVar('last_env', mb_substr($last_env, mb_strlen(ENV_VAR_NAME)+1));
$save_last_template = array_key_exists('save_last_template', $params) ? $params['save_last_template'] : true;
if ($save_last_template) {
// save last template here, becase section & module could be added before
$this->StoreVar(rtrim('last_template_popup_'.$wid, '_'), $last_template);
}
}
function getLastTemplateENV($t, $params = null, $encode = true)
{
if (!isset($params)) {
$params = Array ();
}
$params['__URLENCODE__'] = 1; // uses "&" instead of "&amp;" for url part concatenation + replaces "\" to "%5C" (works in HTML)
if ($this->Application->GetVar('admin') && !array_key_exists('admin', $params) && !defined('EDITING_MODE')) {
$params['editing_mode'] = ''; // used in kApplication::Run
}
$params = array_merge($this->Application->getPassThroughVariables($params), $params);
$ret = $this->Application->BuildEnv($t, $params, 'all');
if (!$encode) {
// cancels 2nd part of replacements, that URLENCODE does
$ret = str_replace('%5C', '\\', $ret);
}
return $ret;
}
function StoreVar($name, $value, $optional = false)
{
$this->Data->Set($name, $value);
if ($optional) {
// make variable optional, also remember optional value
$this->OptionalData[$name] = $value;
}
elseif (!$optional && array_key_exists($name, $this->OptionalData)) {
if ($this->OptionalData[$name] == $value) {
// same value as optional -> don't remove optional mark
return ;
}
// make variable non-optional
unset($this->OptionalData[$name]);
}
}
function StorePersistentVar($name, $value)
{
$this->Storage->StorePersistentVar($this, $name, $value);
}
function LoadPersistentVars()
{
$this->Storage->LoadPersistentVars($this);
}
function StoreVarDefault($name, $value, $optional=false)
{
$tmp = $this->RecallVar($name);
if($tmp === false || $tmp == '')
{
$this->StoreVar($name, $value, $optional);
}
}
function RecallVar($name, $default = false)
{
$ret = $this->Data->Get($name);
return ($ret === false) ? $default : $ret;
}
function RecallPersistentVar($name, $default = false)
{
return $this->Storage->RecallPersistentVar($this, $name, $default);
}
function RemoveVar($name)
{
$this->Storage->RemoveFromData($this, $name);
$this->Data->Remove($name);
}
function RemovePersistentVar($name)
{
return $this->Storage->RemovePersistentVar($this, $name);
}
/**
* Ignores session varible value set before
*
* @param string $name
*/
function RestoreVar($name)
{
$value = $this->Storage->GetFromData($this, $name, '__missing__');
if ($value === '__missing__') {
// there is nothing to restore (maybe session was not saved), look in optional variable values
$value = array_key_exists($name, $this->OptionalData) ? $this->OptionalData[$name] : false;
}
return $this->StoreVar($name, $value);
}
function GetField($var_name, $default = false)
{
return $this->Storage->GetField($this, $var_name, $default);
}
function SetField($var_name, $value)
{
$this->Storage->SetField($this, $var_name, $value);
}
/**
* Deletes expired sessions
*
* @return Array expired sids if any
* @access private
*/
function DeleteExpired()
{
return $this->Storage->DeleteExpired();
}
/**
* Allows to check if user in this session is logged in or not
*
* @return bool
*/
function LoggedIn()
{
$user_id = $this->RecallVar('user_id');
$ret = $user_id > 0;
if (($this->RecallVar('admin') == 1 || defined('ADMIN')) && ($user_id == -1)) {
$ret = true;
}
return $ret;
}
}
\ No newline at end of file
Index: branches/5.1.x/core/units/users/users_event_handler.php
===================================================================
--- branches/5.1.x/core/units/users/users_event_handler.php (revision 13431)
+++ branches/5.1.x/core/units/users/users_event_handler.php (revision 13432)
@@ -1,1950 +1,1964 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class UsersEventHandler extends kDBEventHandler
{
/**
* Allows to override standart permission mapping
*
*/
function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
// admin
'OnSetPersistantVariable' => Array('self' => 'view'), // because setting to logged in user only
'OnUpdateRootPassword' => Array('self' => true),
'OnUpdatePassword' => Array('self' => true),
// front
'OnRefreshForm' => Array('self' => true),
'OnForgotPassword' => Array('self' => true),
'OnResetPassword' => Array('self' => true),
'OnResetPasswordConfirmed' => Array('self' => true),
'OnSubscribeQuery' => Array('self' => true),
'OnSubscribeUser' => Array('self' => true),
'OnRecommend' => Array('self' => true),
'OnItemBuild' => Array('self' => true),
'OnMassResetSettings' => Array('self' => 'edit'),
'OnMassCloneUsers' => Array('self' => 'add'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Shows only admins when required
*
* @param kEvent $event
*/
function SetCustomQuery(&$event)
{
$object =& $event->getObject();
/* @var $object kDBList */
if ($event->Special == 'admins') {
$object->addFilter('primary_filter', 'ug.GroupId = 11');
}
if ($event->Special == 'regular') {
$object->addFilter('primary_filter', 'ug.GroupId <> 11');
}
if (!$this->Application->isAdminUser) {
$object->addFilter('status_filter', '%1$s.Status = '.STATUS_ACTIVE);
}
if ($event->Special == 'online') {
$object->addFilter('online_users_filter', 's.PortalUserId IS NOT NULL');
}
if ($event->Special == 'group') {
$group_id = $this->Application->GetVar('g_id');
if ($group_id !== false) {
// show only users, that user doesn't belong to current group
$table_name = $this->Application->GetTempName(TABLE_PREFIX.'UserGroup', 'prefix:g');
$sql = 'SELECT PortalUserId
FROM ' . $table_name . '
WHERE GroupId = ' . (int)$group_id;
$user_ids = $this->Conn->GetCol($sql);
// array_push($user_ids); // Guest & Everyone groups are set dynamically
if ($user_ids) {
$object->addFilter('already_member_filter', '%1$s.PortalUserId NOT IN ('.implode(',', $user_ids).')');
}
}
}
}
/**
* Checks permissions of user
*
* @param kEvent $event
*/
function CheckPermission(&$event)
{
if ($event->Name == 'OnLogin' || $event->Name == 'OnLogout') {
// permission is checked in OnLogin event directly
return true;
}
if (!$this->Application->isAdminUser) {
$user_id = $this->Application->RecallVar('user_id');
$items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
if ($event->Name == 'OnCreate' && $user_id == -2) {
// "Guest" can create new users
return true;
}
if ($event->Name == 'OnUpdate' && $user_id > 0) {
$user_dummy =& $this->Application->recallObject($event->Prefix.'.-item', null, Array('skip_autoload' => true));
foreach ($items_info as $id => $field_values) {
if ($id != $user_id) {
// registered users can update their record only
return false;
}
$user_dummy->Load($id);
$status_field = array_shift($this->Application->getUnitOption($event->Prefix, 'StatusField'));
if ($user_dummy->GetDBField($status_field) != STATUS_ACTIVE) {
// not active user is not allowed to update his record (he could not activate himself manually)
return false;
}
if (isset($field_values[$status_field]) && $user_dummy->GetDBField($status_field) != $field_values[$status_field]) {
// user can't change status by himself
return false;
}
}
return true;
}
if ($event->Name == 'OnUpdate' && $user_id <= 0) {
// guests are not allowed to update their record, because they don't have it :)
return false;
}
}
return parent::CheckPermission($event);
}
/**
* Handles session expiration (redirects to valid template)
*
* @param kEvent $event
*/
function OnSessionExpire(&$event)
{
$this->Application->resetCounters('UserSession');
// place 2 of 2 (also in kHTTPQuery::getRedirectParams)
$admin_url_params = Array (
'm_cat_id' => 0, // category means nothing on admin login screen
'm_wid' => '', // remove wid, otherwise parent window may add wid to its name breaking all the frameset (for <a> targets)
'pass' => 'm', // don't pass any other (except "m") prefixes to admin session expiration template
'expired' => 1, // expiration mark to show special error on login screen
'no_pass_through' => 1, // this way kApplication::HREF won't add them again
);
if ($this->Application->isAdmin) {
$this->Application->Redirect('index', $admin_url_params, '', 'index.php');
}
if ($this->Application->GetVar('admin') == 1) {
// Front-End showed in admin's right frame
$session_admin =& $this->Application->recallObject('Session.admin');
/* @var $session_admin Session */
if (!$session_admin->LoggedIn()) {
// front-end session created from admin session & both expired
$this->Application->DeleteVar('admin');
$this->Application->Redirect('index', $admin_url_params, '', 'admin/index.php');
}
}
// Front-End session expiration
$get = $this->Application->HttpQuery->getRedirectParams();
$t = $this->Application->GetVar('t');
$get['js_redirect'] = $this->Application->ConfigValue('UseJSRedirect');
$this->Application->Redirect($t ? $t : 'index', $get);
}
/**
+ * [AGENT] Deletes expired sessions
+ *
+ * @param kEvent $event
+ */
+ function OnDeleteExpiredSessions(&$event)
+ {
+ if (defined('IS_INSTALL') && IS_INSTALL) {
+ return ;
+ }
+
+ $this->Application->Session->DeleteExpired();
+ }
+
+ /**
* Checks user data and logs it in if allowed
*
* OnLogin is called from u:autoLoginUser and password is supplied
* OnLogin is called from u:OnAutoLoginUser supplying cookie with encoded username & password
*
* @param kEvent $event
*/
function OnLogin(&$event)
{
// persistent session data after login is not refreshed, because redirect will follow in any case
$prefix_special = $this->Application->isAdmin ? 'u.current' : 'u'; // "u" used on front not to change theme
$object =& $this->Application->recallObject($prefix_special, null, Array('skip_autoload' => true));
$password = $this->Application->GetVar('password');
$invalid_pseudo = $this->Application->isAdmin ? 'la_invalid_password' : 'lu_invalid_password';
$remember_login_cookie = $this->Application->GetVar('remember_login');
if (!$password && !$remember_login_cookie) {
$object->SetError('ValidateLogin', 'invalid_password', $invalid_pseudo);
$event->status = erFAIL;
return false;
}
$email_as_login = $this->Application->ConfigValue('Email_As_Login');
list ($login_field, $submit_field) = $email_as_login && !$this->Application->isAdmin ? Array('Email', 'email') : Array('Login', 'login');
$login_value = $this->Application->GetVar($submit_field);
// process "Save Username" checkbox
if ($this->Application->isAdmin) {
$save_username = $this->Application->GetVar('cb_save_username') ? $login_value : '';
$this->Application->Session->SetCookie('save_username', $save_username, adodb_mktime() + 31104000); // 1 year expiration
$this->Application->SetVar('save_username', $save_username); // cookie will be set on next refresh, but refresh won't occur if login error present, so duplicate cookie in HTTPQuery
}
$super_admin = ($login_value == 'super-root') && $this->verifySuperAdmin();
if ($this->Application->isAdmin && ($login_value == 'root') || ($super_admin && $login_value == 'super-root')) {
// logging in "root" (admin only)
$login_value = 'root';
$root_password = $this->Application->ConfigValue('RootPass');
$password_formatter =& $this->Application->recallObject('kPasswordFormatter');
$test = $password_formatter->EncryptPassword($password, 'b38');
if ($root_password != $test) {
$object->SetError('ValidateLogin', 'invalid_password', $invalid_pseudo);
$event->status = erFAIL;
return false;
}
elseif ($this->checkLoginPermission($login_value)) {
$user_id = -1;
$object->Load($user_id);
$object->SetDBField('Login', $login_value);
$session =& $this->Application->recallObject('Session');
$session->SetField('PortalUserId', $user_id);
// $session->SetField('GroupList', implode(',', $groups) );
$this->Application->SetVar('u.current_id', $user_id);
$this->Application->StoreVar('user_id', $user_id);
$this->Application->LoadPersistentVars();
if ($super_admin) {
$this->Application->StoreVar('super_admin', 1);
}
$this->Application->HandleEvent($dummy, 'session-log:OnStartSession');
$this->processLoginRedirect($event, $password);
$this->_processInterfaceLanguage($event);
return true;
}
else {
$object->SetError('ValidateLogin', 'invalid_license', 'la_invalid_license');
$event->status = erFAIL;
return false;
}
}
/*$sql = 'SELECT PortalUserId FROM '.$object->TableName.' WHERE (%s = %s) AND (Password = MD5(%s))';
$user_id = $this->Conn->GetOne( sprintf($sql, $login_field, $this->Conn->qstr($login_value), $this->Conn->qstr($password) ) );*/
if ($remember_login_cookie) {
$user_info = explode('|', $remember_login_cookie); // 0 - username, 1 - md5(password)
$sql = 'SELECT PortalUserId
FROM '.$object->TableName.'
WHERE (Email = %1$s OR Login = %1$s) AND (Password = %2$s)';
$user_id = $this->Conn->GetOne( sprintf($sql, $this->Conn->qstr($user_info[0]), $this->Conn->qstr($user_info[1]) ) );
} else {
$sql = 'SELECT PortalUserId
FROM '.$object->TableName.'
WHERE (Email = %1$s OR Login = %1$s) AND (Password = MD5(%2$s))';
$user_id = $this->Conn->GetOne( sprintf($sql, $this->Conn->qstr($login_value), $this->Conn->qstr($password) ) );
}
if ($user_id) {
$object->Load($user_id);
if (!$this->checkBanRules($object)) {
$event->status = erFAIL;
return false;
}
if ($object->GetDBField('Status') == STATUS_ACTIVE) {
$groups = $object->getMembershipGroups(true);
if(!$groups) $groups = Array();
array_push($groups, $this->Application->ConfigValue('User_LoggedInGroup') );
$this->Application->StoreVar( 'UserGroups', implode(',', $groups) );
if ($this->checkLoginPermission($login_value)) {
$session =& $this->Application->recallObject('Session');
$session->SetField('PortalUserId', $user_id);
$session->SetField('GroupList', implode(',', $groups) );
$this->Application->SetVar('u.current_id', $user_id);
$this->Application->StoreVar('user_id', $user_id);
$this->Application->LoadPersistentVars();
if (!$remember_login_cookie) {
// don't change last login time when auto-login is used
$this_login = (int)$this->Application->RecallPersistentVar('ThisLogin');
$this->Application->StorePersistentVar('LastLogin', $this_login);
$this->Application->StorePersistentVar('ThisLogin', adodb_mktime());
}
if ($this->Application->GetVar('cb_remember_login') == 1) {
// remember username & password when "Remember Login" checkbox us checked (when user is using login form on Front-End)
$remember_login_cookie = $login_value . '|' . md5($password);
$this->Application->Session->SetCookie('remember_login', $remember_login_cookie, adodb_mktime() + 2592000); // 30 days
}
$this->Application->HandleEvent($dummy, 'session-log:OnStartSession');
}
else {
$object->Load(-2);
$object->SetError('ValidateLogin', 'no_permission', 'lu_no_permissions');
$event->status = erFAIL;
}
if (!$remember_login_cookie) {
$this->processLoginRedirect($event, $password);
$this->_processInterfaceLanguage($event);
}
}
else {
$event->redirect = $this->Application->GetVar('pending_disabled_template');
}
}
else
{
$object->SetID(-2);
$object->SetError('ValidateLogin', 'invalid_password', $invalid_pseudo);
$event->status = erFAIL;
}
$event->SetRedirectParam('pass', 'all');
// $event->SetRedirectParam('pass_category', 1); // to test
}
/**
* Sets correct interface language after sucessful login, based on user settings
*
* @param kEvent $event
*/
function _processInterfaceLanguage(&$event)
{
if (($event->status != erSUCCESS) || !$this->Application->isAdmin) {
return ;
}
$is_root = $this->Application->RecallVar('user_id') == -1;
$object =& $this->Application->recallObject('u.current');
/* @var $object kDBItem */
$user_language_id = $is_root ? $this->Application->RecallPersistentVar('AdminLanguage') : $object->GetDBField('AdminLanguage');
$sql = 'SELECT LanguageId, IF(LanguageId = ' . (int)$user_language_id . ', 2, AdminInterfaceLang) AS SortKey
FROM ' . TABLE_PREFIX . 'Language
WHERE Enabled = 1
HAVING SortKey <> 0
ORDER BY SortKey DESC';
$language_info = $this->Conn->GetRow($sql);
$language_id = $language_info && $language_info['LanguageId'] ? $language_info['LanguageId'] : $user_language_id;
if ($user_language_id != $language_id) {
// first admin login OR language was delelted or disabled
if ($is_root) {
$this->Application->StorePersistentVar('AdminLanguage', $language_id);
}
else {
$object->SetDBField('AdminLanguage', $language_id);
$object->Update();
}
}
$event->SetRedirectParam('m_lang', $language_id); // data
$this->Application->Session->SetField('Language', $language_id); // interface
}
/**
* [HOOK] Auto-Logins Front-End user when "Remember Login" cookie is found
*
* @param kEvent $event
*/
function OnAutoLoginUser(&$event)
{
$remember_login_cookie = $this->Application->GetVar('remember_login');
if (!$remember_login_cookie || $this->Application->isAdmin || $this->Application->LoggedIn()) {
return ;
}
$event->CallSubEvent('OnLogin');
}
/**
* Checks that user is allowed to use super admin mode
*
* @return bool
*/
function verifySuperAdmin()
{
$sa_mode = ipMatch(defined('SA_IP') ? SA_IP : '');
return $sa_mode || $this->Application->isDebugMode();
}
/**
* Enter description here...
*
* @param string $user_name
* @return bool
*/
function checkLoginPermission($user_name)
{
$ret = true;
if ($this->Application->isAdmin) {
$modules_helper =& $this->Application->recallObject('ModulesHelper');
if ($user_name != 'root') {
// root is virtual user, so allow him to login to admin in any case
$ret = $this->Application->CheckPermission('ADMIN', 1);
}
}
else {
$ret = $this->Application->CheckPermission('LOGIN', 1);
}
return $ret;
}
/**
* Process all required data and redirect logged-in user
*
* @param kEvent $event
*/
function processLoginRedirect(&$event, $password)
{
$prefix_special = $this->Application->isAdmin ? 'u.current' : 'u'; // "u" used on front not to change theme
$object =& $this->Application->recallObject($prefix_special, null, Array('skip_autoload' => true));
$next_template = $this->Application->GetVar('next_template');
if ($next_template == '_ses_redirect') {
$location = $this->Application->BaseURL().$this->Application->RecallVar($next_template);
if( $this->Application->isDebugMode() && constOn('DBG_REDIRECT') )
{
$this->Application->Debugger->appendTrace();
echo "<b>Debug output above!!!</b> Proceed to redirect: <a href=\"$location\">$location</a><br>";
}
else {
header('Location: '.$location);
}
$session =& $this->Application->recallObject('Session');
$session->SaveData();
exit;
}
if ($next_template) {
$event->redirect = $next_template;
}
if ($this->Application->ConfigValue('UseJSRedirect')) {
$event->SetRedirectParam('js_redirect', 1);
}
$sync_manager =& $this->Application->recallObjectP('UsersSyncronizeManager', null, Array(), 'InPortalSyncronize');
$sync_manager->performAction('LoginUser', $object->GetDBField('Login'), $password);
$this->Application->resetCounters('UserSession');
}
/**
* Called when user logs in using old in-portal
*
* @param kEvent $event
*/
function OnInpLogin(&$event)
{
$sync_manager =& $this->Application->recallObjectP('UsersSyncronizeManager', null, Array(), 'InPortalSyncronize');
$sync_manager->performAction('LoginUser', $event->getEventParam('user'), $event->getEventParam('pass') );
if ($event->redirect && is_string($event->redirect)) {
// some real template specified instead of true
$this->Application->Redirect($event->redirect, $event->redirect_params);
}
}
/**
* Called when user logs in using old in-portal
*
* @param kEvent $event
*/
function OnInpLogout(&$event)
{
$sync_manager =& $this->Application->recallObjectP('UsersSyncronizeManager', null, Array(), 'InPortalSyncronize');
$sync_manager->performAction('LogoutUser');
}
function OnLogout(&$event)
{
$sync_manager =& $this->Application->recallObjectP('UsersSyncronizeManager', null, Array(), 'InPortalSyncronize');
$sync_manager->performAction('LogoutUser');
$this->Application->HandleEvent($dummy, 'session-log:OnEndSession');
$this->Application->SetVar('u.current_id', -2);
$object =& $this->Application->recallObject('u.current', null, Array('skip_autoload' => true));
$object->Load(-2);
$this->Application->DestroySession();
$session =& $this->Application->recallObject('Session');
/* @var $session Session */
$group_list = $this->Application->ConfigValue('User_GuestGroup') . ',' . $this->Application->ConfigValue('User_LoggedInGroup');
$session->SetField('PortalUserId', -2);
$session->SetField('GroupList', $group_list);
$this->Application->StoreVar('user_id', -2, true);
$this->Application->StoreVar('UserGroups', $group_list, true);
if ($this->Application->ConfigValue('UseJSRedirect')) {
$event->SetRedirectParam('js_redirect', 1);
}
$this->Application->resetCounters('UserSession');
$this->Application->Session->SetCookie('remember_login', '', adodb_mktime() - 3600);
$event->SetRedirectParam('pass', 'all');
}
/**
* Prefill states dropdown with correct values
*
* @param kEvent $event
* @access public
*/
function OnPrepareStates(&$event)
{
$cs_helper =& $this->Application->recallObject('CountryStatesHelper');
$cs_helper->PopulateStates($event, 'State', 'Country');
$object =& $event->getObject();
if( $object->isRequired('Country') && $cs_helper->CountryHasStates( $object->GetDBField('Country') ) ) $object->setRequired('State', true);
$object->setLogin();
}
/**
* Redirects user after succesfull registration to confirmation template (on Front only)
*
* @param kEvent $event
*/
function OnAfterItemCreate(&$event)
{
$this->saveUserImages($event);
if ($this->Application->GetVar('skip_set_primary')) return;
$is_subscriber = $this->Application->GetVar('IsSubscriber');
if(!$is_subscriber)
{
$object =& $event->getObject();
$ug_table = TABLE_PREFIX.'UserGroup';
if ($object->mode == 't') {
$ug_table = $this->Application->GetTempName($ug_table, 'prefix:'.$event->Prefix);
}
$sql = 'UPDATE '.$ug_table.'
SET PrimaryGroup = 0
WHERE PortalUserId = '.$object->GetDBField('PortalUserId');
$this->Conn->Query($sql);
// set primary group to user
if ($this->Application->isAdminUser && $this->Application->GetVar('user_group')) {
// while in admin you can set any group for new users
$group_id = $this->Application->GetVar('user_group');
}
else {
$group_id = $object->GetDBField('UserGroup');
if ($group_id) {
// check, that group is allowed for Front-End
$sql = 'SELECT GroupId
FROM ' . TABLE_PREFIX . 'PortalGroup
WHERE GroupId = ' . (int)$group_id . ' AND FrontRegistration = 1';
$group_id = $this->Conn->GetOne($sql);
}
if (!$group_id) {
// when group not selected -> use default group
$group_id = $this->Application->ConfigValue('User_NewGroup');
}
}
$sql = 'REPLACE INTO '.$ug_table.'(PortalUserId,GroupId,PrimaryGroup) VALUES (%s,%s,1)';
$this->Conn->Query( sprintf($sql, $object->GetID(), $group_id) );
}
}
/**
* Login user if possible, if not then redirect to corresponding template
*
* @param kEvent $event
*/
function autoLoginUser(&$event)
{
$object =& $event->getObject();
$this->Application->SetVar('u.current_id', $object->GetID() );
if($object->GetDBField('Status') == STATUS_ACTIVE && !$this->Application->ConfigValue('User_Password_Auto'))
{
$email_as_login = $this->Application->ConfigValue('Email_As_Login');
list($login_field, $submit_field) = $email_as_login ? Array('Email', 'email') : Array('Login', 'login');
$this->Application->SetVar($submit_field, $object->GetDBField($login_field) );
$this->Application->SetVar('password', $object->GetDBField('Password_plain') );
$event->CallSubEvent('OnLogin');
}
}
/**
* When creating user & user with such email exists then force to use OnUpdate insted of ?
*
* @param kEvent $event
*/
function OnSubstituteSubscriber(&$event)
{
$ret = false;
$object =& $event->getObject( Array('skip_autoload' => true) );
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if($items_info)
{
list($id, $field_values) = each($items_info);
$user_email = isset($field_values['Email']) ? $field_values['Email'] : false;
if($user_email)
{
// check if is subscriber
$verify_user =& $this->Application->recallObject('u.verify', null, Array('skip_autoload' => true) );
$verify_user->Load($user_email, 'Email');
if( $verify_user->isLoaded() && $verify_user->isSubscriberOnly() )
{
$items_info = Array( $verify_user->GetDBField('PortalUserId') => $field_values );
$this->Application->SetVar($event->getPrefixSpecial(true), $items_info);
$ret = true;
}
}
}
if( isset($event->MasterEvent) )
{
$event->MasterEvent->setEventParam('is_subscriber_only', $ret);
}
else
{
$event->setEventParam('is_subscriber_only', $ret);
}
}
/**
* Enter description here...
*
* @param kEvent $event
* @return bool
*/
function isSubscriberOnly(&$event)
{
$event->CallSubEvent('OnSubstituteSubscriber');
$is_subscriber = false;
if( $event->getEventParam('is_subscriber_only') )
{
$is_subscriber = true;
$object =& $event->getObject( Array('skip_autoload' => true) );
$this->OnUpdate($event);
if($event->status == erSUCCESS)
{
$this->OnAfterItemCreate($event);
$object->SendEmailEvents();
if (!$this->Application->isAdmin && ($event->status == erSUCCESS) && $event->redirect) {
$this->autoLoginUser($event);
}
}
}
return $is_subscriber;
}
/**
* Creates new user
*
* @param kEvent $event
*/
function OnCreate(&$event)
{
if (!$this->Application->isAdminUser) {
$this->setUserStatus($event);
}
if (!$this->isSubscriberOnly($event)) {
$cs_helper =& $this->Application->recallObject('CountryStatesHelper');
$cs_helper->CheckStateField($event, 'State', 'Country');
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
if ($this->Application->ConfigValue('User_Password_Auto')) {
$pass = makepassword4(rand(5,8));
$object->SetField('Password', $pass);
$object->SetField('VerifyPassword', $pass);
$this->Application->SetVar('user_password',$pass);
}
parent::OnCreate($event);
$this->Application->SetVar('u.current_id', $object->getID() ); // for affil:OnRegisterAffiliate after hook
$this->setNextTemplate($event);
if (!$this->Application->isAdmin && ($event->status == erSUCCESS) && $event->redirect) {
$object->SendEmailEvents();
$this->autoLoginUser($event);
}
}
}
/**
* Set's new user status based on config options
*
* @param kEvent $event
*/
function setUserStatus(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
$new_users_allowed = $this->Application->ConfigValue('User_Allow_New');
switch ($new_users_allowed) {
case 1: // Immediate
$object->SetDBField('Status', STATUS_ACTIVE);
$next_template = $this->Application->GetVar('registration_confirm_template');
if ($next_template) {
$event->redirect = $next_template;
}
break;
case 3: // Upon Approval
case 4: // Email Activation
$next_template = $this->Application->GetVar('registration_confirm_pending_template');
if ($next_template) {
$event->redirect = $next_template;
}
$object->SetDBField('Status', STATUS_PENDING);
break;
case 2: // Not Allowed
$object->SetDBField('Status', STATUS_DISABLED);
break;
}
}
/**
* Set's new unique resource id to user
*
* @param kEvent $event
*/
function OnBeforeItemCreate(&$event)
{
$this->_makePasswordRequired($event);
$email_as_login = $this->Application->ConfigValue('Email_As_Login');
$object =& $event->getObject();
if (!$this->checkBanRules($object)) {
$event->status = erFAIL;
return false;
}
if ($email_as_login) {
$object->Fields['Email']['error_msgs']['unique'] = $this->Application->Phrase('lu_user_and_email_already_exist');
}
}
/**
* Set's new unique resource id to user
*
* @param kEvent $event
*/
function OnAfterItemValidate(&$event)
{
$object =& $event->getObject();
$resource_id = $object->GetDBField('ResourceId');
if (!$resource_id)
{
$object->SetDBField('ResourceId', $this->Application->NextResourceId() );
}
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnRecommend(&$event)
{
$friend_email = $this->Application->GetVar('friend_email');
$friend_name = $this->Application->GetVar('friend_email');
// used for error reporting only -> rewrite code + theme (by Alex)
$object =& $this->Application->recallObject('u', null, Array('skip_autoload' => true)); // TODO: change theme too
/* @var $object UsersItem */
if (preg_match('/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', $friend_email))
{
/*$cutoff = adodb_mktime() + (int)$this->Application->ConfigValue('Suggest_MinInterval');
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'SuggestMail
WHERE email = ' . $this->Conn->qstr($friend_email) . ' AND sent < ' . $cutoff;
if ($this->Conn->GetRow($sql) !== false) {
$object->SetError('Email', 'send_error', 'lu_email_already_suggested');
$event->status = erFAIL;
return ;
}*/
$send_params = Array ();
$send_params['to_email'] = $friend_email;
$send_params['to_name'] = $friend_name;
$user_id = $this->Application->RecallVar('user_id');
$email_event =& $this->Application->EmailEventUser('USER.SUGGEST', $user_id, $send_params);
$email_event =& $this->Application->EmailEventAdmin('USER.SUGGEST');
if ($email_event->status == erSUCCESS){
/*$fields_hash = Array (
'email' => $friend_email,
'sent' => adodb_mktime(),
);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'SuggestMail');*/
$event->redirect_params = array('opener' => 's', 'pass' => 'all');
$event->redirect = $this->Application->GetVar('template_success');
}
else {
// $event->redirect_params = array('opener' => 's', 'pass' => 'all');
// $event->redirect = $this->Application->GetVar('template_fail');
$object->SetError('Email', 'send_error', 'lu_email_send_error');
$event->status = erFAIL;
}
}
else {
$object->SetError('Email', 'invalid_email', 'lu_InvalidEmail');
$event->status = erFAIL;
}
}
/**
* Saves address changes and mades no redirect
*
* @param kEvent $event
*/
function OnUpdateAddress(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if($items_info)
{
list($id,$field_values) = each($items_info);
if($id > 0) $object->Load($id);
$object->SetFieldsFromHash($field_values);
$object->setID($id);
$object->Validate();
}
$event->redirect = false;
}
/**
* Validate subscriber's email & store it to session -> redirect to confirmation template
*
* @param kEvent $event
*/
function OnSubscribeQuery(&$event)
{
$user_email = $this->Application->GetVar('subscriber_email');
if (preg_match('/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', $user_email)) {
$object =& $this->Application->recallObject($this->Prefix.'.subscriber', null, Array('skip_autoload' => true));
/* @var $object UsersItem */
$this->Application->StoreVar('SubscriberEmail', $user_email);
$object->Load($user_email, 'Email');
if ($object->isLoaded()) {
$group_info = $this->GetGroupInfo($object->GetID());
$event->redirect = $this->Application->GetVar($group_info ? 'unsubscribe_template' : 'subscribe_template');
}
else {
$event->redirect = $this->Application->GetVar('subscribe_template');
$this->Application->StoreVar('SubscriberEmail', $user_email);
}
}
else {
// used for error reporting only -> rewrite code + theme (by Alex)
$object =& $this->Application->recallObject('u', null, Array('skip_autoload' => true)); // TODO: change theme too
/* @var $object UsersItem */
$object->SetError('SubscribeEmail', 'invalid_email', 'lu_InvalidEmail');
$event->status = erFAIL;
}
}
/**
* Subscribe/Unsubscribe user based on email stored in previous step
*
* @param kEvent $event
*/
function OnSubscribeUser(&$event)
{
$object = &$this->Application->recallObject($this->Prefix.'.subscriber', null, Array('skip_autoload' => true));
/* @var $object UsersItem */
$user_email = $this->Application->RecallVar('SubscriberEmail');
if (preg_match('/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', $user_email)) {
$this->RemoveRequiredFields($object);
$object->Load($user_email, 'Email');
if ($object->isLoaded()) {
$group_info = $this->GetGroupInfo($object->GetID());
if ($group_info){
if ($event->getEventParam('no_unsubscribe')) return;
if ($group_info['PrimaryGroup']){
// delete user
$object->Delete();
}
else {
$this->RemoveSubscriberGroup($object->GetID());
}
$event->redirect = $this->Application->GetVar('unsubscribe_ok_template');
}
else {
$this->AddSubscriberGroup($object->GetID(), 0);
$event->redirect = $this->Application->GetVar('subscribe_ok_template');
}
}
else {
$object->SetField('Email', $user_email);
$object->SetField('Login', $user_email);
$object->SetDBField('dob', 1);
$object->SetDBField('dob_date', 1);
$object->SetDBField('dob_time', 1);
$object->SetDBField('Status', STATUS_ACTIVE); // make user subscriber Active by default
$ip = getenv('HTTP_X_FORWARDED_FOR')?getenv('HTTP_X_FORWARDED_FOR'):getenv('REMOTE_ADDR');
$object->SetDBField('ip', $ip);
$this->Application->SetVar('IsSubscriber', 1);
if ($object->Create()) {
$this->AddSubscriberGroup($object->GetID(), 1);
$event->redirect = $this->Application->GetVar('subscribe_ok_template');
}
$this->Application->SetVar('IsSubscriber', 0);
}
}
}
function AddSubscriberGroup($user_id, $is_primary)
{
$group_id = $this->Application->ConfigValue('User_SubscriberGroup');
$sql = 'INSERT INTO ' . TABLE_PREFIX . 'UserGroup
(PortalUserId, GroupId, PrimaryGroup) VALUES (%s, %s, ' . $is_primary . ')';
$this->Conn->Query( sprintf($sql, $user_id, $group_id) );
$this->Application->EmailEventAdmin('USER.SUBSCRIBE');
$this->Application->EmailEventUser('USER.SUBSCRIBE', $user_id);
}
function RemoveSubscriberGroup($user_id)
{
$group_id = $this->Application->ConfigValue('User_SubscriberGroup');
$sql = 'DELETE FROM ' . TABLE_PREFIX . 'UserGroup
WHERE PortalUserId = ' . $user_id . '
AND GroupId = ' . $this->Application->ConfigValue('User_SubscriberGroup');
$this->Conn->Query($sql);
$this->Application->EmailEventAdmin('USER.UNSUBSCRIBE');
$this->Application->EmailEventUser('USER.UNSUBSCRIBE', $user_id);
}
/**
* Allows to detect user subscription status (subscribed or not)
*
* @param int $user_id
* @return bool
*/
function GetGroupInfo($user_id)
{
$sql = 'SELECT * FROM ' . TABLE_PREFIX . 'UserGroup
WHERE (PortalUserId = ' . $user_id . ')
AND (GroupId = ' . $this->Application->ConfigValue('User_SubscriberGroup') . ')';
return $this->Conn->GetRow($sql);
}
function OnForgotPassword(&$event)
{
$user_object =& $this->Application->recallObject('u.forgot', null, Array('skip_autoload' => true));
/* @var $user_object UsersItem */
// used for error reporting only -> rewrite code + theme (by Alex)
$user_current_object =& $this->Application->recallObject('u', null, Array('skip_autoload' => true)); // TODO: change theme too
/* @var $user_current_object UsersItem */
$username = $this->Application->GetVar('username');
$email = $this->Application->GetVar('email');
$found = false;
$allow_reset = true;
if (strlen($username)) {
$user_object->Load($username, 'Login');
if ($user_object->isLoaded()) {
$found = ($user_object->GetDBField("Login")==$username && $user_object->GetDBField("Status")==1) && strlen($user_object->GetDBField("Password"));
}
}
else if(strlen($email)) {
$user_object->Load($email, 'Email');
if ($user_object->isLoaded()) {
$found = ($user_object->GetDBField("Email")==$email && $user_object->GetDBField("Status")==1) && strlen($user_object->GetDBField("Password"));
}
}
if ($user_object->isLoaded()) {
$PwResetConfirm = $user_object->GetDBField('PwResetConfirm');
$PwRequestTime = $user_object->GetDBField('PwRequestTime');
$PassResetTime = $user_object->GetDBField('PassResetTime');
//$MinPwResetDelay = $user_object->GetDBField('MinPwResetDelay');
$MinPwResetDelay = $this->Application->ConfigValue('Users_AllowReset');
$allow_reset = (strlen($PwResetConfirm) ?
adodb_mktime() > $PwRequestTime + $MinPwResetDelay :
adodb_mktime() > $PassResetTime + $MinPwResetDelay);
}
if ($found && $allow_reset) {
$this->Application->StoreVar('tmp_user_id', $user_object->GetDBField("PortalUserId"));
$this->Application->StoreVar('tmp_email', $user_object->GetDBField("Email"));
$confirm_template = $this->Application->GetVar('reset_confirm_template');
if (!$confirm_template) {
$this->Application->SetVar('reset_confirm_template', 'platform/login/forgotpass_reset');
}
$this->Application->EmailEventUser('USER.PSWDC', $user_object->GetDBField('PortalUserId'));
$event->redirect = $this->Application->GetVar('template_success');
}
else {
if (!strlen($username) && !strlen($email)) {
$user_current_object->SetError('Login', 'forgotpw_nodata', 'lu_ferror_forgotpw_nodata');
$user_current_object->SetError('Email', 'forgotpw_nodata', 'lu_ferror_forgotpw_nodata');
}
else {
if ($allow_reset) {
if (strlen($username)) {
$user_current_object->SetError('Login', 'unknown_username', 'lu_ferror_unknown_username');
}
if (strlen($email)) {
$user_current_object->SetError('Email', 'unknown_email', 'lu_ferror_unknown_email');
}
}
else {
if (strlen($username)) {
$user_current_object->SetError('Login', 'reset_denied', 'lu_ferror_reset_denied');
}
if (strlen($email)) {
$user_current_object->SetError('Email', 'reset_denied', 'lu_ferror_reset_denied');
}
}
}
if($user_current_object->FieldErrors){
$event->redirect = false;
}
}
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnResetPassword(&$event)
{
$user_object =& $this->Application->recallObject('u.forgot');
if($user_object->Load($this->Application->RecallVar('tmp_user_id'))){
$this->Application->EmailEventUser('USER.PSWDC', $user_object->GetDBField("PortalUserId"));
$event->redirect = $this->Application->GetVar('template_success');
$m_cat_id = $this->Application->findModule('Name', 'In-Commerce', 'RootCat');
$this->Application->SetVar('m_cat_id', $m_cat_id);
$event->SetRedirectParam('pass', 'm');
}
}
function OnResetPasswordConfirmed(&$event)
{
// used for error reporting only -> rewrite code + theme (by Alex)
$user_current_object =& $this->Application->recallObject('u', null, Array('skip_autoload' => true));// TODO: change theme too
/* @var $user_current_object UsersItem */
$passed_key = trim($this->Application->GetVar('user_key'));
if (!$passed_key) {
$event->redirect_params = Array('opener' => 's', 'pass' => 'all');
$event->redirect = false;
$user_current_object->SetError('PwResetConfirm', 'code_is_not_valid', 'lu_code_is_not_valid');
}
$user_object =& $this->Application->recallObject('u.forgot', null, Array('skip_autoload' => true));
/* @var $user_object UsersItem */
$user_object->Load($passed_key, 'PwResetConfirm');
if ($user_object->isLoaded()) {
$exp_time = $user_object->GetDBField('PwRequestTime') + 3600;
$user_object->SetDBField('PwResetConfirm', '');
$user_object->SetDBField('PwRequestTime', 0);
if ($exp_time > adodb_mktime()) {
$newpw = makepassword4();
$this->Application->StoreVar('password', $newpw);
$user_object->SetField('Password', $newpw);
$user_object->SetField('VerifyPassword', $newpw);
$user_object->SetDBField('PassResetTime', adodb_mktime());
$user_object->SetDBField('PwResetConfirm', '');
$user_object->SetDBField('PwRequestTime', 0);
$user_object->Update();
$this->Application->SetVar('ForgottenPassword', $newpw);
$email_event_user =& $this->Application->EmailEventUser('USER.PSWD', $user_object->GetDBField('PortalUserId'));
$email_event_admin =& $this->Application->EmailEventAdmin('USER.PSWD');
$this->Application->DeleteVar('ForgottenPassword');
if ($email_event_user->status == erSUCCESS) {
$event->redirect_params = array('opener' => 's', 'pass' => 'all');
$event->redirect = $this->Application->GetVar('template_success');
}
} else {
$user_current_object->SetError('PwResetConfirm', 'code_expired', 'lu_code_expired');
$event->redirect = false;
}
} else {
$user_current_object->SetError('PwResetConfirm', 'code_is_not_valid', 'lu_code_is_not_valid');
$event->redirect = false;
}
}
function OnUpdate(&$event)
{
$cs_helper =& $this->Application->recallObject('CountryStatesHelper');
$cs_helper->CheckStateField($event, 'State', 'Country');
parent::OnUpdate($event);
$this->setNextTemplate($event);
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function setNextTemplate(&$event)
{
if ($this->Application->isAdmin) {
return ;
}
$event->redirect_params['opener'] = 's';
$object =& $event->getObject();
if ($object->GetDBField('Status') == STATUS_ACTIVE) {
$next_template = $this->Application->GetVar('next_template');
if ($next_template) {
$event->redirect = $next_template;
}
}
}
/**
* Delete users from groups if their membership is expired
*
* @param kEvent $event
*/
function OnCheckExpiredMembership(&$event)
{
// send pre-expiration reminders: begin
$pre_expiration = adodb_mktime() + $this->Application->ConfigValue('User_MembershipExpirationReminder') * 3600 * 24;
$sql = 'SELECT PortalUserId, GroupId
FROM '.TABLE_PREFIX.'UserGroup
WHERE (MembershipExpires IS NOT NULL) AND (ExpirationReminderSent = 0) AND (MembershipExpires < '.$pre_expiration.')';
$skip_clause = $event->getEventParam('skip_clause');
if ($skip_clause) {
$sql .= ' AND !('.implode(') AND !(', $skip_clause).')';
}
$records = $this->Conn->Query($sql);
if ($records) {
$conditions = Array();
foreach ($records as $record) {
$email_event_user =& $this->Application->EmailEventUser('USER.MEMBERSHIP.EXPIRATION.NOTICE', $record['PortalUserId']);
$email_event_admin =& $this->Application->EmailEventAdmin('USER.MEMBERSHIP.EXPIRATION.NOTICE');
$conditions[] = '(PortalUserId = '.$record['PortalUserId'].' AND GroupId = '.$record['GroupId'].')';
}
$sql = 'UPDATE '.TABLE_PREFIX.'UserGroup
SET ExpirationReminderSent = 1
WHERE '.implode(' OR ', $conditions);
$this->Conn->Query($sql);
}
// send pre-expiration reminders: end
// remove users from groups with expired membership: begin
$sql = 'SELECT PortalUserId
FROM '.TABLE_PREFIX.'UserGroup
WHERE (MembershipExpires IS NOT NULL) AND (MembershipExpires < '.adodb_mktime().')';
$user_ids = $this->Conn->GetCol($sql);
if ($user_ids) {
foreach ($user_ids as $id) {
$email_event_user =& $this->Application->EmailEventUser('USER.MEMBERSHIP.EXPIRED', $id);
$email_event_admin =& $this->Application->EmailEventAdmin('USER.MEMBERSHIP.EXPIRED');
}
}
$sql = 'DELETE FROM '.TABLE_PREFIX.'UserGroup
WHERE (MembershipExpires IS NOT NULL) AND (MembershipExpires < '.adodb_mktime().')';
$this->Conn->Query($sql);
// remove users from groups with expired membership: end
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnRefreshForm(&$event)
{
$event->redirect = false;
$item_info = $this->Application->GetVar($event->Prefix_Special);
list($id, $fields) = each($item_info);
$object =& $event->getObject( Array('skip_autoload' => true) );
$object->setID($id);
$object->IgnoreValidation = true;
$object->SetFieldsFromHash($fields);
}
/**
* Sets persistant variable
*
* @param kEvent $event
*/
function OnSetPersistantVariable(&$event)
{
$field = $this->Application->GetVar('field');
$value = $this->Application->GetVar('value');
$this->Application->StorePersistentVar($field, $value);
$force_tab = $this->Application->GetVar('SetTab');
if ($force_tab) {
$this->Application->StoreVar('force_tab', $force_tab);
}
}
/**
* Overwritten to return user from order by special .ord
*
* @param kEvent $event
*/
function getPassedID(&$event)
{
switch ($event->Special) {
case 'ord':
$order =& $this->Application->recallObject('ord');
/* @var $order OrdersItem */
$id = $order->GetDBField('PortalUserId');
break;
case 'profile':
$id = $this->Application->GetVar('user_id');
if (!$id) {
// if none user_id given use current user id
$id = $this->Application->RecallVar('user_id');
}
break;
default:
$id = parent::getPassedID($event);
break;
}
return $id;
}
/**
* Allows to change root password
*
* @param kEvent $event
*/
function OnUpdateRootPassword(&$event)
{
return $this->OnUpdatePassword($event);
}
/**
* Allows to change root password
*
* @param kEvent $event
*/
function OnUpdatePassword(&$event)
{
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if (!$items_info) return ;
list ($id, $field_values) = each($items_info);
$user_id = $this->Application->RecallVar('user_id');
if ($id == $user_id && ($user_id > 0 || $user_id == -1)) {
$user_dummy =& $this->Application->recallObject($event->Prefix.'.-item', null, Array('skip_autoload' => true));
/* @var $user_dummy kDBItem */
$user_dummy->Load($id);
$status_field = array_shift($this->Application->getUnitOption($event->Prefix, 'StatusField'));
if ($user_dummy->GetDBField($status_field) != STATUS_ACTIVE) {
// not active user is not allowed to update his record (he could not activate himself manually)
return false;
}
}
if ($user_id == -1) {
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object UsersItem */
// put salt to user's config
$field_options = $object->GetFieldOptions('RootPassword');
$field_options['salt'] = 'b38';
$object->SetFieldOptions('RootPassword', $field_options);
$verify_options = $object->GetFieldOptions('VerifyRootPassword');
$verify_options['salt'] = 'b38';
$object->SetFieldOptions('VerifyRootPassword', $verify_options);
// this is internal hack to allow root/root passwords for dev
if ($this->Application->isDebugMode() && $field_values['RootPassword'] == 'root') {
$this->Application->ConfigHash['Min_Password'] = 4;
}
$this->RemoveRequiredFields($object);
$object->SetDBField('RootPassword', $this->Application->ConfigValue('RootPass'));
$object->SetFieldsFromHash($field_values);
$object->setID(-1);
$status = $object->Validate();
if ($status) {
// validation on, password match too
$fields_hash = Array (
'VariableValue' => $object->GetDBField('RootPassword')
);
$conf_table = $this->Application->getUnitOption('conf', 'TableName');
$this->Conn->doUpdate($fields_hash, $conf_table, 'VariableName = "RootPass"');
$event->SetRedirectParam('opener', 'u');
}
else {
$event->status = erFAIL;
$event->redirect = false;
return;
}
}
else {
$object =& $event->getObject();
$object->SetFieldsFromHash($field_values);
if (!$object->Update()) {
$event->status = erFAIL;
$event->redirect = false;
}
}
$event->SetRedirectParam('opener', 'u');
$event->redirect == true;
}
/**
* Apply custom processing to item
*
* @param kEvent $event
*/
function customProcessing(&$event, $type)
{
if ($event->Name == 'OnCreate' && $type == 'before') {
$object =& $event->getObject();
/* @var $object kDBItem */
// if auto password has not been set already - store real one - to be used in email events
if (!$this->Application->GetVar('user_password')) {
$this->Application->SetVar('user_password', $object->GetDirtyField('Password'));
$object->SetDBField('Password_plain', $object->GetDirtyField('Password'));
}
// validate here, because subscribing procedure should not validate captcha code
if ($this->Application->ConfigValue('RegistrationCaptcha')) {
$captcha_helper =& $this->Application->recallObject('CaptchaHelper');
/* @var $captcha_helper kCaptchaHelper */
$captcha_helper->validateCode($event, false);
}
}
}
function OnMassResetSettings(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
$event->status = erFAIL;
return;
}
$ids = $this->StoreSelectedIDs($event);
$default_user_id = $this->Application->ConfigValue('DefaultSettingsUserId');
if (in_array($default_user_id, $ids)) {
array_splice($ids, array_search($default_user_id, $ids), 1);
}
if ($ids) {
$q = 'DELETE FROM '.TABLE_PREFIX.'PersistantSessionData WHERE PortalUserId IN ('.join(',', $ids).') AND
(VariableName LIKE "%_columns_%"
OR
VariableName LIKE "%_filter%"
OR
VariableName LIKE "%_PerPage%")';
$this->Conn->Query($q);
}
$this->clearSelectedIDs($event);
}
/**
* Checks, that currently loaded item is allowed for viewing (non permission-based)
*
* @param kEvent $event
* @return bool
*/
function checkItemStatus(&$event)
{
$object =& $event->getObject();
if (!$object->isLoaded()) {
return true;
}
$virtual_users = Array (-1, -2); // root, Guest
return ($object->GetDBField('Status') == STATUS_ACTIVE) || in_array($object->GetID(), $virtual_users);
}
/**
* Sends approved/declined email event on user status change
*
* @param kEvent $event
*/
function OnAfterItemUpdate(&$event)
{
$this->saveUserImages($event);
$object =& $event->getObject();
/* @var $object UsersItem */
if (!$this->Application->isAdmin || $object->IsTempTable()) {
return ;
}
$this->sendStatusChangeEvent($object->GetID(), $object->GetOriginalField('Status'), $object->GetDBField('Status'));
}
/**
* Stores user's original Status before overwriting with data from temp table
*
* @param kEvent $event
*/
function OnBeforeDeleteFromLive(&$event)
{
$user_status = $this->Application->GetVar('user_status');
if (!$user_status) {
$user_status = Array ();
}
$user_id = $event->getEventParam('id');
if ($user_id > 0) {
$user_status[$user_id] = $this->getUserStatus($user_id);
$this->Application->SetVar('user_status', $user_status);
}
}
/**
* Sends approved/declined email event on user status change (in temp tables during editing)
*
* @param kEvent $event
*/
function OnAfterCopyToLive(&$event)
{
$temp_id = $event->getEventParam('temp_id');
if ($temp_id == 0) {
// this is new user create, don't send email events
return ;
}
$new_status = $this->getUserStatus($temp_id);
$user_status = $this->Application->GetVar('user_status');
$this->sendStatusChangeEvent($temp_id, $user_status[$temp_id], $new_status);
}
/**
* Returns user status (active, pending, disabled) based on ID and temp mode setting
*
* @param int $user_id
* @return int
*/
function getUserStatus($user_id)
{
$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
$sql = 'SELECT Status
FROM '.$table_name.'
WHERE '.$id_field.' = '.$user_id;
return $this->Conn->GetOne($sql);
}
/**
* Sends approved/declined email event on user status change
*
* @param int $user_id
* @param int $prev_status
* @param int $new_status
*/
function sendStatusChangeEvent($user_id, $prev_status, $new_status)
{
$status_events = Array (
STATUS_ACTIVE => 'USER.APPROVE',
STATUS_DISABLED => 'USER.DENY',
);
$email_event = isset($status_events[$new_status]) ? $status_events[$new_status] : false;
if (($prev_status != $new_status) && $email_event) {
$this->Application->EmailEventUser($email_event, $user_id);
$this->Application->EmailEventAdmin($email_event);
}
}
/**
* OnAfterConfigRead for users
*
* @param kEvent $event
*/
function OnAfterConfigRead(&$event)
{
parent::OnAfterConfigRead($event);
// 1. arrange user registration countries
$first_country = $this->Application->ConfigValue('User_Default_Registration_Country');
if ($first_country) {
// update user country dropdown sql
$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
$fields['Country']['options_sql'] = preg_replace('/ORDER BY (.*)/', 'ORDER BY IF (DestId = '.$first_country.', 1, 0) DESC, \\1', $fields['Country']['options_sql']);
$this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
}
// 2. set default user registration group
$virtual_fields = $this->Application->getUnitOption($event->Prefix, 'VirtualFields');
$virtual_fields['UserGroup']['default'] = $this->Application->ConfigValue('User_NewGroup');
$this->Application->setUnitOption($event->Prefix, 'VirtualFields', $virtual_fields);
// 3. allow avatar upload on Front-End
$file_helper =& $this->Application->recallObject('FileHelper');
/* @var $file_helper FileHelper */
$file_helper->createItemFiles($event->Prefix, true); // create image fields
if ($this->Application->isAdminUser) {
// 4. when in administrative console, then create all users with Active status
$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
// $fields['Password']['required'] = 1; // set password required (will broke approve/decline buttons)
$fields['Status']['default'] = STATUS_ACTIVE;
$this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
// 5. remove groups tab on editing forms when AdvancedUserManagement config variable not set
if (!$this->Application->ConfigValue('AdvancedUserManagement')) {
$edit_tab_presets = $this->Application->getUnitOption($event->Prefix, 'EditTabPresets');
foreach ($edit_tab_presets as $preset_name => $preset_tabs) {
if (array_key_exists('groups', $preset_tabs)) {
unset($edit_tab_presets[$preset_name]['groups']);
if (count($edit_tab_presets[$preset_name]) == 1) {
// only 1 tab left -> remove it too
$edit_tab_presets[$preset_name] = Array ();
}
}
}
$this->Application->setUnitOption($event->Prefix, 'EditTabPresets', $edit_tab_presets);
}
}
}
/**
* OnMassCloneUsers
*
* @param kEvent $event
*/
function OnMassCloneUsers(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
$event->status = erFAIL;
return;
}
$event->status=erSUCCESS;
$ids = $this->StoreSelectedIDs($event);
$this->Application->SetVar('skip_set_primary', 1); // otherwise it will default primary group, search for skip_set_primary above
$temp_handler =& $this->Application->recallObject($event->Prefix.'_TempHandler', 'kTempTablesHandler');
/* @var $temp_handler kTempTablesHandler */
$cloned_users = $temp_handler->CloneItems($event->Prefix, '', $ids);
$this->clearSelectedIDs($event);
}
/**
* When cloning users, reset password (set random)
*
* @param kEvent $event
*/
function OnBeforeClone(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$object->setRequired('Password', 0);
$object->setRequired('VerifyPassword', 0);
$object->SetDBField('Password', rand(100000000, 999999999));
$object->SetDBField('CreatedOn', adodb_mktime());
$object->SetDBField('ResourceId', false); // this will reset it
// change email cause it should be unique
$object->NameCopy(array(), $object->GetID(), 'Email', 'copy%1$s.%2$s');
$object->UpdateFormattersSubFields();
}
/**
* Copy user groups after copying user
*
* @param kEvent $event
*/
function OnAfterClone(&$event)
{
$id = $event->getEventParam('id');
$original_id = $event->getEventParam('original_id');
$sql = 'INSERT '.TABLE_PREFIX."UserGroup SELECT $id, GroupId, MembershipExpires, PrimaryGroup, 0 FROM ".TABLE_PREFIX."UserGroup WHERE PortalUserId = $original_id";
$this->Conn->Query($sql);
}
/**
* Saves selected ids to session
*
* @param kEvent $event
*/
function OnSaveSelected(&$event)
{
$this->StoreSelectedIDs($event);
// remove current ID, otherwise group selector will use it in filters
$this->Application->DeleteVar($event->getPrefixSpecial(true).'_id');
}
/**
* Adds selected link to listing
*
* @param kEvent $event
*/
function OnProcessSelected(&$event)
{
$event->SetRedirectParam('opener', 'u');
$user_ids = $this->getSelectedIDs($event, true);
$this->clearSelectedIDs($event);
$dst_field = $this->Application->RecallVar('dst_field');
if ($dst_field != 'PrimaryGroupId') {
return ;
}
$group_ids = $this->Application->GetVar('g');
$primary_group_id = $group_ids ? array_shift( array_keys($group_ids) ) : false;
if (!$user_ids || !$primary_group_id) {
return ;
}
$table_name = $this->Application->getUnitOption('ug', 'TableName');
$sql = 'SELECT PortalUserId
FROM '.$table_name.'
WHERE (GroupId = '.$primary_group_id.') AND (PortalUserId IN ('.implode(',', $user_ids).'))';
$existing_members = $this->Conn->GetCol($sql);
// 1. reset primary group mark
$sql = 'UPDATE '.$table_name.'
SET PrimaryGroup = 0
WHERE PortalUserId IN ('.implode(',', $user_ids).')';
$this->Conn->Query($sql);
foreach ($user_ids as $user_id) {
if (in_array($user_id, $existing_members)) {
// 2. already member of that group -> just make primary
$sql = 'UPDATE '.$table_name.'
SET PrimaryGroup = 1
WHERE (PortalUserId = '.$user_id.') AND (GroupId = '.$primary_group_id.')';
$this->Conn->Query($sql);
}
else {
// 3. not member of that group -> make member & make primary
$fields_hash = Array (
'GroupId' => $primary_group_id,
'PortalUserId' => $user_id,
'PrimaryGroup' => 1,
);
$this->Conn->doInsert($fields_hash, $table_name);
}
}
}
/**
* Loads user images
*
* @param kEvent $event
*/
function OnAfterItemLoad(&$event)
{
parent::OnAfterItemLoad($event);
// linking existing images for item with virtual fields
$image_helper =& $this->Application->recallObject('ImageHelper');
/* @var $image_helper ImageHelper */
$object =& $event->getObject();
/* @var $object kDBItem */
$image_helper->LoadItemImages($object);
}
/**
* Save user images
*
* @param kEvent $event
*/
function saveUserImages(&$event)
{
if (!$this->Application->isAdmin) {
$image_helper =& $this->Application->recallObject('ImageHelper');
/* @var $image_helper ImageHelper */
$object =& $event->getObject();
/* @var $object kDBItem */
// process image upload in virtual fields
$image_helper->SaveItemImages($object);
}
}
/**
* Checks, if given user fields matches at least one of defined ban rules
*
* @param kDBItem $object
* @return bool
*/
function checkBanRules(&$object)
{
$table = $this->Application->getUnitOption('ban-rule', 'TableName');
if (!$this->Conn->TableFound($table)) {
// when ban table not found -> assume user is ok by default
return true;
}
$sql = 'SELECT *
FROM '.$table.'
WHERE ItemType = 6 AND Status = ' . STATUS_ACTIVE . '
ORDER BY Priority DESC';
$rules = $this->Conn->Query($sql);
$found = false;
foreach ($rules as $rule) {
$field = $rule['ItemField'];
$this_value = strtolower( $object->GetDBField($field) );
$test_value = strtolower( $rule['ItemValue'] );
switch ($rule['ItemVerb']) {
/*case 0: // any
$found = true;
break;*/
case 1: // is
if ($this_value == $test_value) {
$found = true;
}
break;
/*case 2: // is not
if ($this_value != $test_value) {
$found = true;
}
break;*/
case 3: // contains
if (strstr($this_value, $test_value)) {
$found = true;
}
break;
/*case 4: // not contains
if (!strstr($this_value, $test_value)) {
$found = true;
}
break;
case 5: // Greater Than
if ($test_value > $this_value) {
$found = true;
}
break;
case 6: // Less Than
if ($test_value < $this_value) {
$found = true;
}
break;
case 7: // exists
if (strlen($this_value) > 0) {
$found = true;
}
break;
case 8: // unique
if ($this->ValueExists($field, $this_value)) {
$found = true;
}
break;*/
}
if ($found) {
break;
}
}
return !$found;
}
/**
* Makes password required for new users
*
* @param kEvent $event
*/
function OnPreCreate(&$event)
{
parent::OnPreCreate($event);
if ($event->status == erSUCCESS) {
$this->_makePasswordRequired($event);
}
}
/**
* Makes password required for new users
*
* @param kEvent $event
*/
function OnNew(&$event)
{
parent::OnNew($event);
if ($event->status == erSUCCESS) {
$this->_makePasswordRequired($event);
}
}
/**
* Makes password required for new users
*
* @param kEvent $event
*/
function _makePasswordRequired(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$required_fields = Array ('Password', 'Password_plain', 'VerifyPassword', 'VerifyPassword_plain');
foreach ($required_fields as $required_field) {
$object->setRequired($required_field);
}
}
/**
* Load item if id is available
*
* @param kEvent $event
*/
function LoadItem(&$event)
{
$id = $this->getPassedID($event);
if ($id < 0) {
// when root, guest and so on
$object =& $event->getObject();
/* @var $object kDBItem */
$object->Clear($id);
return ;
}
parent::LoadItem($event);
}
}
Index: branches/5.1.x/core/units/users/users_config.php
===================================================================
--- branches/5.1.x/core/units/users/users_config.php (revision 13431)
+++ branches/5.1.x/core/units/users/users_config.php (revision 13432)
@@ -1,486 +1,487 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
$config = Array(
'Prefix' => 'u',
'ItemClass' => Array('class'=>'UsersItem','file'=>'users_item.php','build_event'=>'OnItemBuild'),
'ListClass' => Array('class'=>'kDBList','file'=>'','build_event'=>'OnListBuild'),
'EventHandlerClass' => Array('class'=>'UsersEventHandler','file'=>'users_event_handler.php','build_event'=>'OnBuild'),
'TagProcessorClass' => Array('class'=>'UsersTagProcessor','file'=>'users_tag_processor.php','build_event'=>'OnBuild'),
'RegisterClasses' => Array(
Array('pseudo' => 'UsersSyncronizeManager', 'class' => 'UsersSyncronizeManager', 'file' => 'users_syncronize.php', 'build_event' => ''),
),
'AutoLoad' => true,
'ConfigPriority' => 0,
'Hooks' => Array (
Array (
'Mode' => hAFTER,
'Conditional' => false,
'HookToPrefix' => 'u',
'HookToSpecial' => '*',
'HookToEvent' => Array('OnAfterItemLoad', 'OnBeforeItemCreate', 'OnBeforeItemUpdate', 'OnUpdateAddress'),
'DoPrefix' => '',
'DoSpecial' => '*',
'DoEvent' => 'OnPrepareStates',
),
Array (
'Mode' => hBEFORE,
'Conditional' => false,
'HookToPrefix' => 'affil',
'HookToSpecial' => '*',
'HookToEvent' => Array('OnCheckAffiliateAgreement'),
'DoPrefix' => '',
'DoSpecial' => '*',
'DoEvent' => 'OnSubstituteSubscriber',
),
Array (
'Mode' => hBEFORE,
'Conditional' => false,
'HookToPrefix' => '',
'HookToSpecial' => '*',
'HookToEvent' => Array('OnAfterConfigRead'),
'DoPrefix' => 'cdata',
'DoSpecial' => '*',
'DoEvent' => 'OnDefineCustomFields',
),
Array (
'Mode' => hAFTER,
'Conditional' => false,
'HookToPrefix' => 'adm',
'HookToSpecial' => '*',
'HookToEvent' => Array('OnStartup'),
'DoPrefix' => '',
'DoSpecial' => '*',
'DoEvent' => 'OnAutoLoginUser',
),
// Captcha processing
Array (
'Mode' => hAFTER,
'Conditional' => false,
'HookToPrefix' => '',
'HookToSpecial' => '*',
'HookToEvent' => Array('OnAfterConfigRead'),
'DoPrefix' => 'captcha',
'DoSpecial' => '*',
'DoEvent' => 'OnPrepareCaptcha',
),
/*Array (
'Mode' => hAFTER,
'Conditional' => false,
'HookToPrefix' => '',
'HookToSpecial' => '*',
'HookToEvent' => Array('OnBeforeItemCreate'),
'DoPrefix' => 'captcha',
'DoSpecial' => '*',
'DoEvent' => 'OnValidateCode',
),*/
),
'QueryString' => Array(
1 => 'id',
2 => 'Page',
3 => 'PerPage',
4 => 'event',
5 => 'mode',
),
- 'RegularEvents' => Array(
- 'membership_expiration' => Array('EventName' => 'OnCheckExpiredMembership', 'RunInterval' => 1800, 'Type' => reAFTER),
- ),
+ 'RegularEvents' => Array(
+ 'membership_expiration' => Array('EventName' => 'OnCheckExpiredMembership', 'RunInterval' => 1800, 'Type' => reAFTER),
+ 'delete_expired_sessions' => Array('EventName' => 'OnDeleteExpiredSessions', 'RunInterval' => 43200, 'Type' => reAFTER),
+ ),
'IDField' => 'PortalUserId',
'StatusField' => Array('Status'),
'TitleField' => 'Login',
'ItemType' => 6, // used for custom fields only (on user's case)
'StatisticsInfo' => Array(
'pending' => Array(
'icon' => 'icon16_user_pending.gif',
'label' => 'la_Text_Users',
'js_url' => '#url#',
'url' => Array('t' => 'users/users_list', 'pass' => 'm,u', 'u_event' => 'OnSetFilterPattern', 'u_filters' => 'show_active=0,show_pending=1,show_disabled=0'),
'status' => STATUS_PENDING,
),
),
'TitlePresets' => Array (
'default' => Array (
'new_status_labels' => Array ('u' => '!la_title_Adding_User!'),
'edit_status_labels' => Array ('u' => '!la_title_Editing_User!'),
),
'users_list' => Array (
'prefixes' => Array ('u_List'), 'format' => "!la_title_Users!",
'toolbar_buttons' => Array ('new_item', 'edit', 'delete', 'approve', 'decline', 'e-mail', 'export', 'view', 'dbl-click'),
),
'users_edit' => Array (
'prefixes' => Array ('u'), 'format' => "#u_status# #u_titlefield#",
'toolbar_buttons' => Array ('select', 'cancel', 'reset_edit', 'prev', 'next'),
),
'user_edit_images' => Array (
'prefixes' => Array ('u', 'u-img_List'), 'format' => "#u_status# '#u_titlefield#' - !la_title_Images!",
'toolbar_buttons' => Array ('select', 'cancel', 'prev', 'next', 'new_item', 'edit', 'delete', 'approve', 'decline', 'setprimary', 'move_up', 'move_down', 'view', 'dbl-click'),
),
'user_edit_groups' => Array (
'prefixes' => Array ('u', 'u-ug_List'), 'format' => "#u_status# '#u_titlefield#' - !la_title_Groups!",
'toolbar_buttons' => Array ('select', 'cancel', 'prev', 'next', 'select_user', 'edit', 'delete', 'setprimary', 'view', 'dbl-click'),
),
'user_edit_items' => Array (
'prefixes' => Array ('u'), 'format' => "#u_status# '#u_titlefield#' - !la_title_Items!",
'toolbar_buttons' => Array ('select', 'cancel', 'prev', 'next', 'edit', 'delete', 'view', 'dbl-click'),
),
'user_edit_custom' => Array (
'prefixes' => Array ('u'), 'format' => "#u_status# '#u_titlefield#' - !la_title_Custom!",
'toolbar_buttons' => Array ('select', 'cancel', 'prev', 'next'),
),
'admin_list' => Array (
'prefixes' => Array ('u.admins_List'), 'format' => "!la_title_Administrators!",
'toolbar_buttons' => Array ('new_item', 'edit', 'delete', 'clone', 'refresh', 'view', 'dbl-click'),
),
'admins_edit' => Array (
'prefixes' => Array ('u'), 'format' => "#u_status# #u_titlefield#",
'toolbar_buttons' => Array ('select', 'cancel', 'reset_edit', 'prev', 'next'),
),
'regular_users_list' => Array (
'prefixes' => Array ('u.regular_List'), 'format' => "!la_title_Users!",
'toolbar_buttons' => Array (),
),
'root_edit' => Array (
'prefixes' => Array ('u'), 'format' => "!la_title_Editing_User! 'root'",
'toolbar_buttons' => Array ('select', 'cancel'),
),
'user_edit_group' => Array (
'prefixes' => Array ('u', 'u-ug'),
'edit_status_labels' => Array ('u-ug' => '!la_title_EditingMembership!'),
'format' => "#u_status# '#u_titlefield#' - #u-ug_status# '#u-ug_titlefield#'",
'toolbar_buttons' => Array ('select', 'cancel'),
),
'user_image_edit' => Array (
'prefixes' => Array ('u', 'u-img'),
'new_status_labels' => Array ('u-img' => '!la_title_Adding_Image!'),
'edit_status_labels' => Array ('u-img' => '!la_title_Editing_Image!'),
'new_titlefield' => Array ('u-img' => '!la_title_New_Image!'),
'format' => "#u_status# '#u_titlefield#' - #u-img_status# '#u-img_titlefield#'",
'toolbar_buttons' => Array ('select', 'cancel'),
),
'user_select' => Array (
'prefixes' => Array ('u_List'), 'format' => "!la_title_Users! - !la_title_SelectUser!",
'toolbar_buttons' => Array ('select', 'cancel', 'dbl-click'),
),
'group_user_select' => Array (
'prefixes' => Array ('u.group_List'), 'format' => "!la_title_Users! - !la_title_SelectUser!",
'toolbar_buttons' => Array ('select', 'cancel', 'view', 'dbl-click'),
),
'tree_users' => Array('format' => '!la_section_overview!'),
),
'EditTabPresets' => Array (
'Default' => Array (
'general' => Array ('title' => 'la_tab_General', 't' => 'users/users_edit', 'priority' => 1),
'groups' => Array ('title' => 'la_tab_Groups', 't' => 'users/users_edit_groups', 'priority' => 2),
'images' => Array ('title' => 'la_tab_Images', 't' => 'users/user_edit_images', 'priority' => 3),
'items' => Array ('title' => 'la_tab_Items', 't' => 'users/user_edit_items', 'priority' => 4),
'custom' => Array ('title' => 'la_tab_Custom', 't' => 'users/users_edit_custom', 'priority' => 5),
),
'Admins' => Array (
'general' => Array ('title' => 'la_tab_General', 't' => 'users/admins_edit', 'priority' => 1),
'groups' => Array ('title' => 'la_tab_Groups', 't' => 'users/admins_edit_groups', 'priority' => 2),
),
),
'PermSection' => Array('main' => 'in-portal:user_list', 'email' => 'in-portal:user_email', 'custom' => 'in-portal:user_custom'),
'Sections' => Array (
'in-portal:user_list' => Array (
'parent' => 'in-portal:users',
'icon' => 'users',
'label' => 'la_title_Users', // 'la_tab_User_List',
'url' => Array ('t' => 'users/users_list', 'pass' => 'm'),
'permissions' => Array ('view', 'add', 'edit', 'delete', 'advanced:ban', 'advanced:send_email', /*'advanced:add_favorite', 'advanced:remove_favorite',*/),
'priority' => 1,
'type' => stTREE,
),
'in-portal:admins' => Array (
'parent' => 'in-portal:users',
'icon' => 'administrators',
'label' => 'la_title_Administrators',
'url' => Array ('t' => 'users/admins_list', 'pass' => 'm'),
'permissions' => Array ('view', 'add', 'edit', 'delete'),
'perm_prefix' => 'u',
'priority' => 2,
'type' => stTREE,
),
// user settings
'in-portal:user_setting_folder' => Array (
'parent' => 'in-portal:system',
'icon' => 'conf_users',
'label' => 'la_title_Users',
'use_parent_header' => 1,
'url' => Array ('t' => 'index', 'pass_section' => true, 'pass' => 'm'),
'permissions' => Array ('view'),
'priority' => 2,
'container' => true,
'type' => stTREE,
),
'in-portal:configure_users' => Array (
'parent' => 'in-portal:user_setting_folder',
'icon' => 'conf_users_general',
'label' => 'la_tab_ConfigSettings',
'url' => Array ('t' => 'config/config_universal', 'module' => 'In-Portal:Users', 'pass_section' => true, 'pass' => 'm'),
'permissions' => Array ('view', 'edit'),
'priority' => 1,
'type' => stTREE,
),
'in-portal:user_email' => Array (
'parent' => 'in-portal:user_setting_folder',
'icon' => 'conf_email',
'label' => 'la_tab_ConfigE-mail',
'url' => Array ('t' => 'config/config_email', 'module' => 'Core:Users', 'pass_section' => true, 'pass' => 'm'),
'permissions' => Array ('view', 'edit'),
'priority' => 2,
'type' => stTREE,
),
'in-portal:user_custom' => Array (
'parent' => 'in-portal:user_setting_folder',
'icon' => 'conf_customfields',
'label' => 'la_tab_ConfigCustom',
'url' => Array ('t' => 'custom_fields/custom_fields_list', 'cf_type' => 6, 'pass_section' => true, 'pass' => 'm,cf'),
'permissions' => Array ('view', 'add', 'edit', 'delete'),
'priority' => 3,
'type' => stTREE,
),
),
'TableName' => TABLE_PREFIX.'PortalUser',
'ListSQLs' => Array( '' => ' SELECT %1$s.* %2$s FROM %1$s
LEFT JOIN '.TABLE_PREFIX.'UserGroup ug ON %1$s.PortalUserId = ug.PortalUserId AND ug.PrimaryGroup = 1
LEFT JOIN '.TABLE_PREFIX.'PortalGroup g ON ug.GroupId = g.GroupId
LEFT JOIN '.TABLE_PREFIX.'%3$sPortalUserCustomData cust ON %1$s.ResourceId = cust.ResourceId',
'online' => ' SELECT %1$s.* %2$s FROM %1$s
LEFT JOIN '.TABLE_PREFIX.'UserSession s ON s.PortalUserId = %1$s.PortalUserId
LEFT JOIN '.TABLE_PREFIX.'UserGroup ug ON %1$s.PortalUserId = ug.PortalUserId AND ug.PrimaryGroup = 1
LEFT JOIN '.TABLE_PREFIX.'PortalGroup g ON ug.GroupId = g.GroupId
LEFT JOIN '.TABLE_PREFIX.'%3$sPortalUserCustomData cust ON %1$s.ResourceId = cust.ResourceId',
),
'ItemSQLs' => Array( '' => ' SELECT %1$s.* %2$s FROM %1$s
LEFT JOIN '.TABLE_PREFIX.'UserGroup ug ON %1$s.PortalUserId = ug.PortalUserId AND ug.PrimaryGroup = 1
LEFT JOIN '.TABLE_PREFIX.'PortalGroup g ON ug.GroupId = g.GroupId
LEFT JOIN '.TABLE_PREFIX.'%3$sPortalUserCustomData cust ON %1$s.ResourceId = cust.ResourceId',
),
'ListSortings' => Array (
'' => Array (
'Sorting' => Array ('Login' => 'asc'),
)
),
'SubItems' => Array('addr', 'u-cdata', 'u-ug', 'u-img', 'fav', 'user-profile'),
'FilterMenu' => Array(
'Groups' => Array(
Array('mode' => 'AND', 'filters' => Array('show_active','show_disabled','show_pending'), 'type' => WHERE_FILTER),
),
'Filters' => Array(
'show_active' => Array('label' =>'la_Enabled', 'on_sql' => '', 'off_sql' => '%1$s.Status != 1' ),
'show_disabled' => Array('label' => 'la_Disabled', 'on_sql' => '', 'off_sql' => '%1$s.Status != 0' ),
'show_pending' => Array('label' => 'la_Pending', 'on_sql' => '', 'off_sql' => '%1$s.Status != 2' ),
)
),
'CalculatedFields' => Array(
'' => Array(
'PrimaryGroup' => 'g.Name',
'FullName' => 'CONCAT(FirstName, " ", LastName)',
),
),
'Fields' => Array
(
'PortalUserId' => Array ('type' => 'int', 'not_null' => 1, 'default' => 0),
'Login' => Array ('type' => 'string', 'unique'=>Array('Login'), 'default' => null,'required'=>1, 'error_msgs' => Array('unique'=>'!lu_user_already_exist!')),
'Password' => Array ('type' => 'string', 'formatter' => 'kPasswordFormatter', 'encryption_method' => 'md5', 'verify_field' => 'VerifyPassword', 'skip_empty' => 1, 'default' => md5('')),
'FirstName' => Array ('type' => 'string', 'not_null' => 1, 'default' => ''),
'LastName' => Array ('type' => 'string', 'not_null' => 1, 'default' => ''),
'Company' => Array ('type' => 'string','not_null' => '1','default' => ''),
'Email' => Array (
'type' => 'string', 'formatter' => 'kFormatter',
'regexp'=>'/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i',
'sample_value' => 'email@domain.com', 'unique' => Array ('Email'), 'not_null' => 1,
'required' => 1,
'default' => '',
'error_msgs' => Array (
'invalid_format'=>'!la_invalid_email!', 'unique'=>'!lu_email_already_exist!'
),
),
'CreatedOn' => Array('type'=>'int', 'formatter' => 'kDateFormatter', 'default' => '#NOW#'),
'Phone' => Array('type' => 'string','default' => null),
'Fax' => Array('type' => 'string', 'not_null' => 1, 'default' => ''),
'Street' => Array('type' => 'string', 'default' => null),
'Street2' => Array('type' => 'string', 'not_null' => '1', 'default' => ''),
'City' => Array('type' => 'string','default' => null),
'State' => Array(
'type' => 'string',
'formatter' => 'kOptionsFormatter', 'options' => Array(),
'not_null' => 1,
'default' => ''
),
'Zip' => Array('type' => 'string','default' => null),
'Country' => Array(
'type' => 'string',
'formatter' => 'kOptionsFormatter',
'options_sql' => ' SELECT %1$s
FROM '.TABLE_PREFIX.'StdDestinations
LEFT JOIN '.TABLE_PREFIX.'Phrase ON '.TABLE_PREFIX.'Phrase.Phrase = '.TABLE_PREFIX.'StdDestinations.DestName
WHERE DestType = 1
ORDER BY l%2$s_Translation',
'option_key_field' => 'DestAbbr', 'option_title_field' => 'l%2$s_Translation',
'not_null' => 1, 'default' => ''
),
'ResourceId' => Array('type' => 'int','not_null' => 1, 'default' => 0),
'Status' => Array('type' => 'int', 'formatter'=>'kOptionsFormatter', 'options'=>Array(1=>'la_Enabled', 0=>'la_Disabled', 2=>'la_Pending'), 'use_phrases'=>1, 'not_null' => '1','default' => 1),
'Modified' => Array('type' => 'int', 'formatter' => 'kDateFormatter', 'default' => '#NOW#'),
'dob' => Array('type'=>'int', 'formatter' => 'kDateFormatter', 'default' => null),
'tz' => Array('type' => 'int','default' => 0),
'ip' => Array('type' => 'string','default' => null),
'IsBanned' => Array('type' => 'int','not_null' => 1, 'default' => 0),
'PassResetTime' => Array('type' => 'int','default' => null),
'PwResetConfirm' => Array('type' => 'string','default' => null),
'PwRequestTime' => Array('type' => 'int','default' => null),
'MinPwResetDelay' => Array('type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array(300 => '5', 600 => '10', 900 => '15', 1800 => '30', 3600 => '60'), 'use_phrases' => 0, 'not_null' => '1', 'default' => 1800),
'AdminLanguage' => Array (
'type' => 'int',
'formatter' => 'kOptionsFormatter', 'options_sql' => 'SELECT %s FROM ' . TABLE_PREFIX . 'Language ORDER BY PackName', 'option_key_field' => 'LanguageId', 'option_title_field' => 'LocalName',
'default' => NULL
),
),
'VirtualFields' => Array(
'ValidateLogin' => Array('type'=>'string','default'=>''),
'SubscribeEmail' => Array('type'=>'string','default'=>''),
'PrimaryGroup' => Array('type' => 'string', 'default' => ''),
'RootPassword' => Array('type' => 'string', 'formatter' => 'kPasswordFormatter', 'encryption_method' => 'md5', 'verify_field' => 'VerifyRootPassword', 'skip_empty' => 1, 'default' => md5('') ),
'FullName' => Array ('type' => 'string', 'default' => ''),
'UserGroup' => Array (
'type' => 'int',
'formatter' => 'kOptionsFormatter', 'options_sql' => 'SELECT %1$s FROM ' . TABLE_PREFIX . 'PortalGroup WHERE Enabled = 1 AND FrontRegistration = 1', 'option_key_field' => 'GroupId', 'option_title_field' => 'Name',
'not_null' => 1, 'default' => 0,
),
),
'Grids' => Array(
// not in use
'Default' => Array(
'Icons' => Array(
0 => 'icon16_user_disabled.png',
1 => 'icon16_user.png',
2 => 'icon16_user_pending.png'
),
'Fields' => Array(
'Login' => Array('title' => 'la_col_Username', 'data_block' => 'grid_checkbox_td', 'filter_block' => 'grid_like_filter'),
'LastName' => Array( 'title'=>'la_col_LastName', 'filter_block' => 'grid_like_filter'),
'FirstName' => Array( 'title'=>'la_col_FirstName', 'filter_block' => 'grid_like_filter'),
'Email' => Array( 'title'=>'la_col_Email', 'filter_block' => 'grid_like_filter'),
'PrimaryGroup' => Array( 'title'=>'la_col_PrimaryGroup', 'filter_block' => 'grid_like_filter'),
'CreatedOn' => Array('title' => 'la_col_CreatedOn', 'filter_block' => 'grid_date_range_filter'),
),
),
// used
'UserSelector' => Array(
'Icons' => Array(
0 => 'icon16_user_disabled.png',
1 => 'icon16_user.png',
2 => 'icon16_user_pending.png'
),
'Selector' => 'radio',
'Fields' => Array(
'Login' => Array ('title' => 'la_col_Username', 'filter_block' => 'grid_like_filter', 'width' => 150, ),
'FirstName' => Array ('title' => 'la_col_FirstName', 'filter_block' => 'grid_like_filter', 'width' => 150, ),
'LastName' => Array ('title' => 'la_col_LastName', 'filter_block' => 'grid_like_filter', 'width' => 150, ),
'Email' => Array ('title' => 'la_col_Email', 'filter_block' => 'grid_like_filter', 'width' => 200, ),
'PrimaryGroup' => Array( 'title'=>'la_col_PrimaryGroup', 'filter_block' => 'grid_like_filter', 'width' => 100, ),
'CreatedOn' => Array('title' => 'la_col_CreatedOn', 'filter_block' => 'grid_date_range_filter', 'width' => 150, ),
),
),
// used
'Admins' => Array (
'Icons' => Array(
0 => 'icon16_admin_disabled.png',
1 => 'icon16_admin.png',
2 => 'icon16_admin_disabled.png',
),
'Fields' => Array (
'PortalUserId' => Array ('title' => 'la_col_Id', 'data_block' => 'grid_checkbox_td', 'filter_block' => 'grid_range_filter', 'width' => 70),
'Login' => Array ('title' => 'la_col_Username', 'filter_block' => 'grid_like_filter', 'width' => 150, ),
'FirstName' => Array ('title' => 'la_col_FirstName', 'filter_block' => 'grid_like_filter', 'width' => 150, ),
'LastName' => Array ('title' => 'la_col_LastName', 'filter_block' => 'grid_like_filter', 'width' => 150, ),
'Email' => Array ('title' => 'la_col_Email', 'filter_block' => 'grid_like_filter', 'width' => 200, ),
),
),
// used
'RegularUsers' => Array (
'Icons' => Array(
0 => 'icon16_user_disabled.png',
1 => 'icon16_user.png',
2 => 'icon16_user_pending.png'
),
'Fields' => Array(
'PortalUserId' => Array ('title' => 'la_col_Id', 'data_block' => 'grid_checkbox_td', 'filter_block' => 'grid_range_filter', 'width' => 70),
'Login' => Array ('title' => 'la_col_Username', 'filter_block' => 'grid_like_filter', 'width' => 150, ),
'FirstName' => Array ('title' => 'la_col_FirstName', 'filter_block' => 'grid_like_filter', 'width' => 150, ),
'LastName' => Array ('title' => 'la_col_LastName', 'filter_block' => 'grid_like_filter', 'width' => 150, ),
'Email' => Array ('title' => 'la_col_Email', 'filter_block' => 'grid_like_filter', 'width' => 200, ),
'Status' => Array ('title' => 'la_col_Status', 'filter_block' => 'grid_options_filter', 'width' => 100, ),
),
),
),
);
\ No newline at end of file

Event Timeline