/kernel/classes/datatypes/ezuser/ezuser.php
PHP | 2814 lines | 2017 code | 245 blank | 552 comment | 279 complexity | 6b6800fc5d1a48bc2a093bb996a441f7 MD5 | raw file
Possible License(s): GPL-2.0
Large files files are truncated, but you can click here to view the full file
- <?php
- //
- // Definition of eZUser class
- //
- // Created on: <10-Jun-2002 17:03:15 bf>
- //
- // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
- // SOFTWARE NAME: eZ Publish
- // SOFTWARE RELEASE: 4.1.x
- // COPYRIGHT NOTICE: Copyright (C) 1999-2011 eZ Systems AS
- // SOFTWARE LICENSE: GNU General Public License v2.0
- // NOTICE: >
- // This program is free software; you can redistribute it and/or
- // modify it under the terms of version 2.0 of the GNU General
- // Public License as published by the Free Software Foundation.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of version 2.0 of the GNU General
- // Public License along with this program; if not, write to the Free
- // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- // MA 02110-1301, USA.
- //
- //
- // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
- //
- /*!
- \class eZUser ezuser.php
- \brief eZUser handles eZ Publish user accounts
- \ingroup eZDatatype
- */
- class eZUser extends eZPersistentObject
- {
- /// MD5 of password
- const PASSWORD_HASH_MD5_PASSWORD = 1;
- /// MD5 of user and password
- const PASSWORD_HASH_MD5_USER = 2;
- /// MD5 of site, user and password
- const PASSWORD_HASH_MD5_SITE = 3;
- /// Legacy support for mysql hashed passwords
- const PASSWORD_HASH_MYSQL = 4;
- /// Passwords in plaintext, should not be used for real sites
- const PASSWORD_HASH_PLAINTEXT = 5;
- // Crypted passwords
- const PASSWORD_HASH_CRYPT = 6;
- /// Authenticate by matching the login field
- const AUTHENTICATE_LOGIN = 1;
- /// Authenticate by matching the email field
- const AUTHENTICATE_EMAIL = 2;
- const AUTHENTICATE_ALL = 3; //EZ_USER_AUTHENTICATE_LOGIN | EZ_USER_AUTHENTICATE_EMAIL;
- protected static $anonymousId = null;
- function eZUser( $row = array() )
- {
- $this->eZPersistentObject( $row );
- $this->OriginalPassword = false;
- $this->OriginalPasswordConfirm = false;
- }
- static function definition()
- {
- static $definition = array( 'fields' => array( 'contentobject_id' => array( 'name' => 'ContentObjectID',
- 'datatype' => 'integer',
- 'default' => 0,
- 'required' => true,
- 'foreign_class' => 'eZContentObject',
- 'foreign_attribute' => 'id',
- 'multiplicity' => '0..1' ),
- 'login' => array( 'name' => 'Login',
- 'datatype' => 'string',
- 'default' => '',
- 'required' => true ),
- 'email' => array( 'name' => 'Email',
- 'datatype' => 'string',
- 'default' => '',
- 'required' => true ),
- 'password_hash' => array( 'name' => 'PasswordHash',
- 'datatype' => 'string',
- 'default' => '',
- 'required' => true ),
- 'password_hash_type' => array( 'name' => 'PasswordHashType',
- 'datatype' => 'integer',
- 'default' => 1,
- 'required' => true ) ),
- 'keys' => array( 'contentobject_id' ),
- 'sort' => array( 'contentobject_id' => 'asc' ),
- 'function_attributes' => array( 'contentobject' => 'contentObject',
- 'groups' => 'groups',
- 'has_stored_login' => 'hasStoredLogin',
- 'original_password' => 'originalPassword',
- 'original_password_confirm' => 'originalPasswordConfirm',
- 'roles' => 'roles',
- 'role_id_list' => 'roleIDList',
- 'limited_assignment_value_list' => 'limitValueList',
- 'is_logged_in' => 'isLoggedIn',
- 'is_enabled' => 'isEnabled',
- 'is_locked' => 'isLocked',
- 'last_visit' => 'lastVisit',
- 'login_count' => 'loginCount',
- 'has_manage_locations' => 'hasManageLocations' ),
- 'relations' => array( 'contentobject_id' => array( 'class' => 'ezcontentobject',
- 'field' => 'id' ) ),
- 'class_name' => 'eZUser',
- 'name' => 'ezuser' );
- return $definition;
- }
- /*!
- \return a textual identifier for the hash type $id
- */
- static function passwordHashTypeName( $id )
- {
- switch ( $id )
- {
- case self::PASSWORD_HASH_MD5_PASSWORD:
- {
- return 'md5_password';
- } break;
- case self::PASSWORD_HASH_MD5_USER:
- {
- return 'md5_user';
- } break;
- case self::PASSWORD_HASH_MD5_SITE:
- {
- return 'md5_site';
- } break;
- case self::PASSWORD_HASH_MYSQL:
- {
- return 'mysql';
- } break;
- case self::PASSWORD_HASH_PLAINTEXT:
- {
- return 'plaintext';
- } break;
- case self::PASSWORD_HASH_CRYPT:
- {
- return 'crypt';
- } break;
- }
- }
- /*!
- \return the hash type for the textual identifier $identifier
- */
- static function passwordHashTypeID( $identifier )
- {
- switch ( $identifier )
- {
- case 'md5_password':
- {
- return self::PASSWORD_HASH_MD5_PASSWORD;
- } break;
- default:
- case 'md5_user':
- {
- return self::PASSWORD_HASH_MD5_USER;
- } break;
- case 'md5_site':
- {
- return self::PASSWORD_HASH_MD5_SITE;
- } break;
- case 'mysql':
- {
- return self::PASSWORD_HASH_MYSQL;
- } break;
- case 'plaintext':
- {
- return self::PASSWORD_HASH_PLAINTEXT;
- } break;
- case 'crypt':
- {
- return self::PASSWORD_HASH_CRYPT;
- } break;
- }
- }
- /*!
- Check if current user has "content/manage_locations" access
- */
- function hasManageLocations()
- {
- $accessResult = $this->hasAccessTo( 'content', 'manage_locations' );
- if ( $accessResult['accessWord'] != 'no' )
- {
- return true;
- }
- return false;
- }
- static function create( $contentObjectID )
- {
- $row = array(
- 'contentobject_id' => $contentObjectID,
- 'login' => null,
- 'email' => null,
- 'password_hash' => null,
- 'password_hash_type' => null
- );
- return new eZUser( $row );
- }
- function store( $fieldFilters = null )
- {
- $this->Email = trim( $this->Email );
- $userID = $this->attribute( 'contentobject_id' );
- // Clear memory cache
- unset( $GLOBALS['eZUserObject_' . $userID] );
- $GLOBALS['eZUserObject_' . $userID] = $this;
- self::purgeUserCacheByUserId( $userID );
- eZPersistentObject::store( $fieldFilters );
- }
- function originalPassword()
- {
- return $this->OriginalPassword;
- }
- function setOriginalPassword( $password )
- {
- $this->OriginalPassword = $password;
- }
- function originalPasswordConfirm()
- {
- return $this->OriginalPasswordConfirm;
- }
- function setOriginalPasswordConfirm( $password )
- {
- $this->OriginalPasswordConfirm = $password;
- }
- function hasStoredLogin()
- {
- $db = eZDB::instance();
- $contentObjectID = $this->attribute( 'contentobject_id' );
- $sql = "SELECT * FROM ezuser WHERE contentobject_id='$contentObjectID' AND LENGTH( login ) > 0";
- $rows = $db->arrayQuery( $sql );
- return !empty( $rows );
- }
- /*!
- Fills in the \a $id, \a $login, \a $email and \a $password for the user
- and creates the proper password hash.
- */
- function setInformation( $id, $login, $email, $password, $passwordConfirm = false )
- {
- $this->setAttribute( "contentobject_id", $id );
- $this->setAttribute( "email", $email );
- $this->setAttribute( "login", $login );
- if ( eZUser::validatePassword( $password ) and
- $password == $passwordConfirm ) // Cannot change login or password_hash without login and password
- {
- $this->setAttribute( "password_hash", eZUser::createHash( $login, $password, eZUser::site(),
- eZUser::hashType() ) );
- $this->setAttribute( "password_hash_type", eZUser::hashType() );
- }
- else
- {
- $this->setOriginalPassword( $password );
- $this->setOriginalPasswordConfirm( $passwordConfirm );
- }
- }
- static function fetch( $id, $asObject = true )
- {
- if ( !$id )
- return null;
- return eZPersistentObject::fetchObject( eZUser::definition(),
- null,
- array( 'contentobject_id' => $id ),
- $asObject );
- }
- static function fetchByName( $login, $asObject = true )
- {
- return eZPersistentObject::fetchObject( eZUser::definition(),
- null,
- array( 'LOWER( login )' => strtolower( $login ) ),
- $asObject );
- }
- static function fetchByEmail( $email, $asObject = true )
- {
- return eZPersistentObject::fetchObject( eZUser::definition(),
- null,
- array( 'LOWER( email )' => strtolower( $email ) ),
- $asObject );
- }
- /*!
- \static
- \return a list of the logged in users.
- \param $asObject If false it will return a list with only the names of the users as elements and user ID as key,
- otherwise each entry is a eZUser object.
- \sa fetchLoggedInCount
- */
- static function fetchLoggedInList( $asObject = false, $offset = false, $limit = false, $sortBy = false )
- {
- $db = eZDB::instance();
- $time = time() - eZINI::instance()->variable( 'Session', 'ActivityTimeout' );
- $parameters = array();
- if ( $offset )
- $parameters['offset'] =(int) $offset;
- if ( $limit )
- $parameters['limit'] =(int) $limit;
- $sortText = '';
- if ( $asObject )
- {
- $selectArray = array( "distinct ezuser.*" );
- }
- else
- {
- $selectArray = array( "ezuser.contentobject_id as user_id", "ezcontentobject.name" );
- }
- if ( $sortBy !== false )
- {
- $sortElements = array();
- if ( !is_array( $sortBy ) )
- {
- $sortBy = array( array( $sortBy, true ) );
- }
- else if ( !is_array( $sortBy[0] ) )
- $sortBy = array( $sortBy );
- $sortColumns = array();
- foreach ( $sortBy as $sortElements )
- {
- $sortColumn = $sortElements[0];
- $sortOrder = $sortElements[1];
- $orderText = $sortOrder ? 'asc' : 'desc';
- switch ( $sortColumn )
- {
- case 'user_id':
- {
- $sortColumn = "ezuser.contentobject_id $orderText";
- } break;
- case 'login':
- {
- $sortColumn = "ezuser.login $orderText";
- } break;
- case 'activity':
- {
- $selectArray[] = "ezuservisit.current_visit_timestamp AS activity";
- $sortColumn = "activity $orderText";
- } break;
- case 'email':
- {
- $sortColumn = "ezuser.email $orderText";
- } break;
- default:
- {
- eZDebug::writeError( "Unkown sort column '$sortColumn'", __METHOD__ );
- $sortColumn = false;
- } break;
- }
- if ( $sortColumn )
- $sortColumns[] = $sortColumn;
- }
- if ( !empty( $sortColumns ) )
- $sortText = "ORDER BY " . implode( ', ', $sortColumns );
- }
- if ( $asObject )
- {
- $selectText = implode( ', ', $selectArray );
- $sql = "SELECT $selectText
- FROM ezuservisit, ezuser
- WHERE ezuservisit.user_id != '" . self::anonymousId() . "' AND
- ezuservisit.current_visit_timestamp > '$time' AND
- ezuser.contentobject_id = ezuservisit.user_id
- $sortText";
- $rows = $db->arrayQuery( $sql, $parameters );
- $list = array();
- foreach ( $rows as $row )
- {
- $list[] = new eZUser( $row );
- }
- }
- else
- {
- $selectText = implode( ', ', $selectArray );
- $sql = "SELECT $selectText
- FROM ezuservisit, ezuser, ezcontentobject
- WHERE ezuservisit.user_id != '" . self::anonymousId() . "' AND
- ezuservisit.current_visit_timestamp > '$time' AND
- ezuser.contentobject_id = ezuservisit.user_id AND
- ezcontentobject.id = ezuser.contentobject_id
- $sortText";
- $rows = $db->arrayQuery( $sql, $parameters );
- $list = array();
- foreach ( $rows as $row )
- {
- $list[$row['user_id']] = $row['name'];
- }
- }
- return $list;
- }
- /*!
- \return the number of logged in users in the system.
- \note The count will be cached for the current page if caching is allowed.
- \sa fetchAnonymousCount
- */
- static function fetchLoggedInCount()
- {
- if ( isset( $GLOBALS['eZSiteBasics']['no-cache-adviced'] ) and
- !$GLOBALS['eZSiteBasics']['no-cache-adviced'] and
- isset( $GLOBALS['eZUserLoggedInCount'] ) )
- return $GLOBALS['eZUserLoggedInCount'];
- $db = eZDB::instance();
- $time = time() - eZINI::instance()->variable( 'Session', 'ActivityTimeout' );
- $sql = "SELECT count( DISTINCT user_id ) as count
- FROM ezuservisit
- WHERE user_id != '" . self::anonymousId() . "' AND
- user_id > 0 AND
- current_visit_timestamp > '$time'";
- $rows = $db->arrayQuery( $sql );
- $count = isset( $rows[0] ) ? $rows[0]['count'] : 0;
- $GLOBALS['eZUserLoggedInCount'] = $count;
- return $count;
- }
- /**
- * Return the number of anonymous users in the system.
- *
- * @deprecated As of 4.4 since default session handler does not support this.
- * @return int
- */
- static function fetchAnonymousCount()
- {
- if ( isset( $GLOBALS['eZSiteBasics']['no-cache-adviced'] ) and
- !$GLOBALS['eZSiteBasics']['no-cache-adviced'] and
- isset( $GLOBALS['eZUserAnonymousCount'] ) )
- return $GLOBALS['eZUserAnonymousCount'];
- $db = eZDB::instance();
- $time = time();
- $ini = eZINI::instance();
- $activityTimeout = $ini->variable( 'Session', 'ActivityTimeout' );
- $sessionTimeout = $ini->variable( 'Session', 'SessionTimeout' );
- $time = $time + $sessionTimeout - $activityTimeout;
- $sql = "SELECT count( session_key ) as count
- FROM ezsession
- WHERE user_id = '" . self::anonymousId() . "' AND
- expiration_time > '$time'";
- $rows = $db->arrayQuery( $sql );
- $count = isset( $rows[0] ) ? $rows[0]['count'] : 0;
- $GLOBALS['eZUserAnonymousCount'] = $count;
- return $count;
- }
- /*!
- \static
- \return true if the user with ID $userID is currently logged into the system.
- \note The information will be cached for the current page if caching is allowed.
- \sa fetchLoggedInList
- */
- static function isUserLoggedIn( $userID )
- {
- $userID = (int)$userID;
- if ( isset( $GLOBALS['eZSiteBasics']['no-cache-adviced'] ) and
- !$GLOBALS['eZSiteBasics']['no-cache-adviced'] and
- isset( $GLOBALS['eZUserLoggedInMap'][$userID] ) )
- return $GLOBALS['eZUserLoggedInMap'][$userID];
- $db = eZDB::instance();
- $time = time() - eZINI::instance()->variable( 'Session', 'ActivityTimeout' );
- $sql = "SELECT DISTINCT user_id
- FROM ezuservisit
- WHERE user_id = '" . $userID . "' AND
- current_visit_timestamp > '$time'";
- $rows = $db->arrayQuery( $sql, array( 'limit' => 2 ) );
- $isLoggedIn = isset( $rows[0] );
- $GLOBALS['eZUserLoggedInMap'][$userID] = $isLoggedIn;
- return $isLoggedIn;
- }
- /*!
- \static
- Removes any cached session information, this is:
- - logged in user count
- - anonymous user count
- - logged in user map
- */
- static function clearSessionCache()
- {
- unset( $GLOBALS['eZUserLoggedInCount'] );
- unset( $GLOBALS['eZUserAnonymousCount'] );
- unset( $GLOBALS['eZUserLoggedInMap'] );
- }
- /**
- * Remove session data for user \a $userID.
- * @todo should use eZSession api (needs to be created) so
- * callbacks (like preference / basket..) is cleared as well.
- *
- * @params int $userID
- */
- static function removeSessionData( $userID )
- {
- eZUser::clearSessionCache();
- eZSession::getHandlerInstance()->deleteByUserIDs( array( $userID ) );
- }
- /*!
- Removes the user from the ezuser table.
- \note Will also remove any notifications and session related to the user.
- */
- static function removeUser( $userID )
- {
- $user = eZUser::fetch( $userID );
- if ( !$user )
- {
- eZDebug::writeError( "unable to find user with ID $userID", __METHOD__ );
- return false;
- }
- eZUser::removeSessionData( $userID );
- eZSubtreeNotificationRule::removeByUserID( $userID );
- eZCollaborationNotificationRule::removeByUserID( $userID );
- eZUserSetting::removeByUserID( $userID );
- eZUserAccountKey::removeByUserID( $userID );
- eZForgotPassword::removeByUserID( $userID );
- eZWishList::removeByUserID( $userID );
- // only remove general digest setting if there are no other users with the same e-mail
- $email = $user->attribute( 'email' );
- $usersWithEmailCount = eZPersistentObject::count( eZUser::definition(), array( 'email' => $email ) );
- if ( $usersWithEmailCount == 1 )
- {
- eZGeneralDigestUserSettings::removeByAddress( $email );
- }
- eZPersistentObject::removeObject( eZUser::definition(),
- array( 'contentobject_id' => $userID ) );
- return true;
- }
- /*!
- \return a list of valid and enabled users, the data returned is an array
- with ezcontentobject database data.
- */
- static function fetchContentList()
- {
- $contentObjectStatus = eZContentObject::STATUS_PUBLISHED;
- $query = "SELECT ezcontentobject.*
- FROM ezuser, ezcontentobject, ezuser_setting
- WHERE ezcontentobject.status = '$contentObjectStatus' AND
- ezuser_setting.is_enabled = 1 AND
- ezcontentobject.id = ezuser.contentobject_id AND
- ezuser_setting.user_id = ezuser.contentobject_id";
- $db = eZDB::instance();
- $rows = $db->arrayQuery( $query );
- return $rows;
- }
- /*!
- \static
- \return the default hash type which is specified in UserSettings/HashType in site.ini
- */
- static function hashType()
- {
- $ini = eZINI::instance();
- $type = strtolower( $ini->variable( 'UserSettings', 'HashType' ) );
- if ( $type == 'md5_site' )
- return self::PASSWORD_HASH_MD5_SITE;
- else if ( $type == 'md5_user' )
- return self::PASSWORD_HASH_MD5_USER;
- else if ( $type == 'plaintext' )
- return self::PASSWORD_HASH_PLAINTEXT;
- else if ( $type == 'crypt' )
- return self::PASSWORD_HASH_CRYPT;
- else
- return self::PASSWORD_HASH_MD5_PASSWORD;
- }
- /*!
- \static
- \return the site name used in password hashing.
- */
- static function site()
- {
- $ini = eZINI::instance();
- return $ini->variable( 'UserSettings', 'SiteName' );
- }
- /*!
- Fetches a builtin user and returns it, this helps avoid special cases where
- user is not logged in.
- */
- static function fetchBuiltin( $id )
- {
- if ( !in_array( $id, $GLOBALS['eZUserBuiltins'] ) )
- $id = self::anonymousId();
- if ( empty( $GLOBALS["eZUserBuilitinInstance-$id"] ) )
- {
- $GLOBALS["eZUserBuilitinInstance-$id"] = eZUser::fetch( self::anonymousId() );
- }
- return $GLOBALS["eZUserBuilitinInstance-$id"];
- }
- /*!
- \return the user id.
- */
- function id()
- {
- return $this->ContentObjectID;
- }
- /*!
- \return a bitfield which decides the authenticate methods.
- */
- static function authenticationMatch()
- {
- $ini = eZINI::instance();
- $matchArray = $ini->variableArray( 'UserSettings', 'AuthenticateMatch' );
- $match = 0;
- foreach ( $matchArray as $matchItem )
- {
- switch ( $matchItem )
- {
- case "login":
- {
- $match = ( $match | self::AUTHENTICATE_LOGIN );
- } break;
- case "email":
- {
- $match = ( $match | self::AUTHENTICATE_EMAIL );
- } break;
- }
- }
- return $match;
- }
- /*!
- \return \c true if there can only be one instance of an email address on the site.
- */
- static function requireUniqueEmail()
- {
- $ini = eZINI::instance();
- return $ini->variable( 'UserSettings', 'RequireUniqueEmail' ) == 'true';
- }
- /**
- * Logs in the user if applied username and password is valid.
- *
- * @param string $login
- * @param string $password
- * @param bool $authenticationMatch
- * @return mixed eZUser on success, bool false on failure
- */
- public static function loginUser( $login, $password, $authenticationMatch = false )
- {
- $user = self::_loginUser( $login, $password, $authenticationMatch );
- if ( is_object( $user ) )
- {
- self::loginSucceeded( $user );
- return $user;
- }
- else
- {
- self::loginFailed( $user, $login );
- return false;
- }
- }
- /**
- * Does some house keeping work once a log in has succeeded.
- *
- * @param eZUser $user
- */
- protected static function loginSucceeded( $user )
- {
- $userID = $user->attribute( 'contentobject_id' );
- // if audit is enabled logins should be logged
- eZAudit::writeAudit( 'user-login', array( 'User id' => $userID, 'User login' => $user->attribute( 'login' ) ) );
- eZUser::updateLastVisit( $userID, true );
- eZUser::setCurrentlyLoggedInUser( $user, $userID );
- // Reset number of failed login attempts
- eZUser::setFailedLoginAttempts( $userID, 0 );
- }
- /**
- * Does some house keeping work when a log in has failed.
- *
- * @param mixed $userID
- * @param string $login
- */
- protected static function loginFailed( $userID = false, $login )
- {
- $loginEscaped = eZDB::instance()->escapeString( $login );
- // Failed login attempts should be logged
- eZAudit::writeAudit( 'user-failed-login', array( 'User login' => $loginEscaped,
- 'Comment' => 'Failed login attempt: eZUser::loginUser()' ) );
- // Increase number of failed login attempts.
- if ( $userID )
- eZUser::setFailedLoginAttempts( $userID );
- }
- /**
- * Logs in an user if applied login and password is valid.
- *
- * This method does not do any house keeping work anymore (writing audits, etc).
- * When you call this method make sure to call loginSucceeded() or loginFailed()
- * depending on the success of the login.
- *
- * @param string $login
- * @param string $password
- * @param bool $authenticationMatch
- * @return mixed eZUser object on log in success, int userID if the username
- * exists but log in failed, or false if the username doesn't exists.
- */
- protected static function _loginUser( $login, $password, $authenticationMatch = false )
- {
- $http = eZHTTPTool::instance();
- $db = eZDB::instance();
- if ( $authenticationMatch === false )
- $authenticationMatch = eZUser::authenticationMatch();
- $loginEscaped = $db->escapeString( $login );
- $passwordEscaped = $db->escapeString( $password );
- $loginArray = array();
- if ( $authenticationMatch & self::AUTHENTICATE_LOGIN )
- $loginArray[] = "login='$loginEscaped'";
- if ( $authenticationMatch & self::AUTHENTICATE_EMAIL )
- {
- if ( eZMail::validate( $login ) )
- {
- $loginArray[] = "email='$loginEscaped'";
- }
- }
- if ( empty( $loginArray ) )
- $loginArray[] = "login='$loginEscaped'";
- $loginText = implode( ' OR ', $loginArray );
- $contentObjectStatus = eZContentObject::STATUS_PUBLISHED;
- $ini = eZINI::instance();
- $databaseName = $db->databaseName();
- // if mysql
- if ( $databaseName === 'mysql' )
- {
- $query = "SELECT contentobject_id, password_hash, password_hash_type, email, login
- FROM ezuser, ezcontentobject
- WHERE ( $loginText ) AND
- ezcontentobject.status='$contentObjectStatus' AND
- ezcontentobject.id=contentobject_id AND
- ( ( password_hash_type!=4 ) OR
- ( password_hash_type=4 AND
- ( $loginText ) AND
- password_hash=PASSWORD('$passwordEscaped') ) )";
- }
- else
- {
- $query = "SELECT contentobject_id, password_hash,
- password_hash_type, email, login
- FROM ezuser, ezcontentobject
- WHERE ( $loginText )
- AND ezcontentobject.status='$contentObjectStatus'
- AND ezcontentobject.id=contentobject_id";
- }
- $users = $db->arrayQuery( $query );
- $exists = false;
- if ( $users !== false && isset( $users[0] ) )
- {
- $ini = eZINI::instance();
- foreach ( $users as $userRow )
- {
- $userID = $userRow['contentobject_id'];
- $hashType = $userRow['password_hash_type'];
- $hash = $userRow['password_hash'];
- $exists = eZUser::authenticateHash( $userRow['login'], $password, eZUser::site(),
- $hashType,
- $hash );
- // If hash type is MySql
- if ( $hashType == self::PASSWORD_HASH_MYSQL and $databaseName === 'mysql' )
- {
- $queryMysqlUser = "SELECT contentobject_id, password_hash, password_hash_type, email, login
- FROM ezuser, ezcontentobject
- WHERE ezcontentobject.status='$contentObjectStatus' AND
- password_hash_type=4 AND ( $loginText ) AND password_hash=PASSWORD('$passwordEscaped') ";
- $mysqlUsers = $db->arrayQuery( $queryMysqlUser );
- if ( isset( $mysqlUsers[0] ) )
- $exists = true;
- }
- eZDebugSetting::writeDebug( 'kernel-user', eZUser::createHash( $userRow['login'], $password, eZUser::site(),
- $hashType, $hash ), "check hash" );
- eZDebugSetting::writeDebug( 'kernel-user', $hash, "stored hash" );
- // If current user has been disabled after a few failed login attempts.
- $canLogin = eZUser::isEnabledAfterFailedLogin( $userID );
- if ( $exists )
- {
- // We should store userID for warning message.
- $GLOBALS['eZFailedLoginAttemptUserID'] = $userID;
- $userSetting = eZUserSetting::fetch( $userID );
- $isEnabled = $userSetting->attribute( "is_enabled" );
- if ( $hashType != eZUser::hashType() and
- strtolower( $ini->variable( 'UserSettings', 'UpdateHash' ) ) == 'true' )
- {
- $hashType = eZUser::hashType();
- $hash = eZUser::createHash( $userRow['login'], $password, eZUser::site(),
- $hashType );
- $db->query( "UPDATE ezuser SET password_hash='$hash', password_hash_type='$hashType' WHERE contentobject_id='$userID'" );
- }
- break;
- }
- }
- }
- if ( $exists and $isEnabled and $canLogin )
- {
- return new eZUser( $userRow );
- }
- else
- {
- return isset( $userID ) ? $userID : false;
- }
- }
- /*!
- \static
- Checks if IP address of current user is in \a $ipList.
- */
- static function isUserIPInList( $ipList )
- {
- $ipAddress = eZSys::serverVariable( 'REMOTE_ADDR', true );
- if ( $ipAddress )
- {
- $result = false;
- foreach( $ipList as $itemToMatch )
- {
- if ( preg_match("/^(([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+))(\/([0-9]+)$|$)/", $itemToMatch, $matches ) )
- {
- if ( $matches[6] )
- {
- if ( eZDebug::isIPInNet( $ipAddress, $matches[1], $matches[7] ) )
- {
- $result = true;
- break;
- }
- }
- else
- {
- if ( $matches[1] == $ipAddress )
- {
- $result = true;
- break;
- }
- }
- }
- }
- }
- else
- {
- $result = (
- in_array( 'commandline', $ipList ) &&
- ( php_sapi_name() == 'cli' )
- );
- }
- return $result;
- }
- /*!
- \static
- Returns true if current user is trusted user.
- */
- static function isTrusted()
- {
- $ini = eZINI::instance();
- // Check if current user is trusted user.
- $trustedIPs = $ini->hasVariable( 'UserSettings', 'TrustedIPList' ) ? $ini->variable( 'UserSettings', 'TrustedIPList' ) : array();
- // Check if IP address of current user is in $trustedIPs array.
- $trustedUser = eZUser::isUserIPInList( $trustedIPs );
- if ( $trustedUser )
- return true;
- return false;
- }
- /*!
- \static
- Returns max number of failed login attempts.
- */
- static function maxNumberOfFailedLogin()
- {
- $ini = eZINI::instance();
- $maxNumberOfFailedLogin = $ini->hasVariable( 'UserSettings', 'MaxNumberOfFailedLogin' ) ? $ini->variable( 'UserSettings', 'MaxNumberOfFailedLogin' ) : '0';
- return $maxNumberOfFailedLogin;
- }
- /*
- \static
- Returns true if the user can login
- If user has number of failed login attempts more than eZUser::maxNumberOfFailedLogin()
- and user is not trusted
- the user will not be allowed to login.
- */
- static function isEnabledAfterFailedLogin( $userID, $ignoreTrusted = false )
- {
- if ( !is_numeric( $userID ) )
- return true;
- $userObject = eZUser::fetch( $userID );
- if ( !$userObject )
- return true;
- $trustedUser = eZUser::isTrusted();
- // If user is trusted we should stop processing
- if ( $trustedUser and !$ignoreTrusted )
- return true;
- $maxNumberOfFailedLogin = eZUser::maxNumberOfFailedLogin();
- if ( $maxNumberOfFailedLogin == '0' )
- return true;
- $failedLoginAttempts = $userObject->failedLoginAttempts();
- if ( $failedLoginAttempts > $maxNumberOfFailedLogin )
- return false;
- return true;
- }
- /*!
- \protected
- Makes sure the user \a $user is set as the currently logged in user by
- updating the session and setting the necessary global variables.
- All login handlers should use this function to ensure that the process
- is executed properly.
- */
- static function setCurrentlyLoggedInUser( $user, $userID )
- {
- $GLOBALS["eZUserGlobalInstance_$userID"] = $user;
- // Set/overwrite the global user, this will be accessed from
- // instance() when there is no ID passed to the function.
- $GLOBALS["eZUserGlobalInstance_"] = $user;
- eZSession::setUserID( $userID );
- eZSession::set( 'eZUserLoggedInID', $userID );
- self::cleanup();
- eZSession::regenerate();
- }
- /*!
- \virtual
- Used by login handler to clean up session variables
- */
- function sessionCleanup()
- {
- }
- /**
- * Cleanup user related session values, for use by login / logout code
- *
- * @internal
- */
- static function cleanup()
- {
- $http = eZHTTPTool::instance();
- $http->removeSessionVariable( 'CanInstantiateClassList' );
- $http->removeSessionVariable( 'ClassesCachedForUser' );
- // Note: This must be done more generic with an internal
- // callback system.
- eZPreferences::sessionCleanup();
- }
- /*!
- \return logs in the current user object
- */
- function loginCurrent()
- {
- self::setCurrentlyLoggedInUser( $this, $this->ContentObjectID );
- }
- /*!
- \static
- Logs out the current user
- */
- static function logoutCurrent()
- {
- $http = eZHTTPTool::instance();
- $id = false;
- $GLOBALS["eZUserGlobalInstance_$id"] = false;
- $contentObjectID = $http->sessionVariable( 'eZUserLoggedInID' );
- // reset session data
- $newUserID = self::anonymousId();
- eZSession::setUserID( $newUserID );
- $http->setSessionVariable( 'eZUserLoggedInID', $newUserID );
- // Clear current basket if necessary
- $db = eZDB::instance();
- $db->begin();
- eZBasket::cleanupCurrentBasket();
- $db->commit();
- if ( $contentObjectID )
- self::cleanup();
- // give user new session id
- eZSession::regenerate();
- // set the property used to prevent SSO from running again
- self::$userHasLoggedOut = true;
- }
- /**
- * Returns a shared instance of the eZUser class pr $id value.
- * If user can not be fetched, then anonymous user is returned and
- * a warning trown, if anonymous user can not be fetched, then NoUser
- * is returned and another warning is thrown.
- *
- * @param int|false $id On false: Gets current user id from session
- * or from {@link eZUser::anonymousId()} if not set.
- * @return eZUser
- */
- static function instance( $id = false )
- {
- if ( !empty( $GLOBALS["eZUserGlobalInstance_$id"] ) )
- {
- return $GLOBALS["eZUserGlobalInstance_$id"];
- }
- $userId = $id;
- $currentUser = null;
- $http = eZHTTPTool::instance();
- $anonymousUserID = self::anonymousId();
- $sessionHasStarted = eZSession::hasStarted();
- // If not specified get the current user
- if ( $userId === false )
- {
- if ( $sessionHasStarted )
- {
- $userId = $http->sessionVariable( 'eZUserLoggedInID' );
- if ( !is_numeric( $userId ) )
- {
- $userId = $anonymousUserID;
- eZSession::setUserID( $userId );
- $http->setSessionVariable( 'eZUserLoggedInID', $userId );
- }
- }
- else
- {
- $userId = $anonymousUserID;
- eZSession::setUserID( $userId );
- }
- }
- // Check user cache (this effectivly fetches user from cache)
- // user not found if !isset( isset( $userCache['info'][$userId] ) )
- $userCache = self::getUserCacheByUserId( $userId );
- if ( isset( $userCache['info'][$userId] ) )
- {
- $userArray = $userCache['info'][$userId];
- if ( is_numeric( $userArray['contentobject_id'] ) )
- {
- $currentUser = new eZUser( $userArray );
- $currentUser->setUserCache( $userCache );
- }
- }
- $ini = eZINI::instance();
- // Check if:
- // - the user has not logged out,
- // - the user is not logged in,
- // - and if a automatic single sign on plugin is enabled.
- if ( !self::$userHasLoggedOut and is_object( $currentUser ) and !$currentUser->isLoggedIn() )
- {
- $ssoHandlerArray = $ini->variable( 'UserSettings', 'SingleSignOnHandlerArray' );
- if ( !empty( $ssoHandlerArray ) )
- {
- $ssoUser = false;
- foreach ( $ssoHandlerArray as $ssoHandler )
- {
- // Load handler
- $handlerFile = 'kernel/classes/ssohandlers/ez' . strtolower( $ssoHandler ) . 'ssohandler.php';
- if ( file_exists( $handlerFile ) )
- {
- include_once( $handlerFile );
- $className = 'eZ' . $ssoHandler . 'SSOHandler';
- $impl = new $className();
- $ssoUser = $impl->handleSSOLogin();
- }
- else // check in extensions
- {
- $extensionDirectories = $ini->variable( 'UserSettings', 'ExtensionDirectory' );
- $directoryList = eZExtension::expandedPathList( $extensionDirectories, 'sso_handler' );
- foreach( $directoryList as $directory )
- {
- $handlerFile = $directory . '/ez' . strtolower( $ssoHandler ) . 'ssohandler.php';
- if ( file_exists( $handlerFile ) )
- {
- include_once( $handlerFile );
- $className = 'eZ' . $ssoHandler . 'SSOHandler';
- $impl = new $className();
- $ssoUser = $impl->handleSSOLogin();
- }
- }
- }
- }
- // If a user was found via SSO, then use it
- if ( $ssoUser !== false )
- {
- $currentUser = $ssoUser;
- $userId = $currentUser->attribute( 'contentobject_id' );
- $userInfo = array();
- $userInfo[$userId] = array( 'contentobject_id' => $userId,
- 'login' => $currentUser->attribute( 'login' ),
- 'email' => $currentUser->attribute( 'email' ),
- 'password_hash' => $currentUser->attribute( 'password_hash' ),
- 'password_hash_type' => $currentUser->attribute( 'password_hash_type' )
- );
- eZSession::setUserID( $userId );
- $http->setSessionVariable( 'eZUserLoggedInID', $userId );
- eZUser::updateLastVisit( $userId );
- eZUser::setCurrentlyLoggedInUser( $currentUser, $userId );
- eZHTTPTool::redirect( eZSys::wwwDir() . eZSys::indexFile( false ) . eZSys::requestURI(), array(), 302 );
- eZExecution::cleanExit();
- }
- }
- }
- if ( $userId <> $anonymousUserID )
- {
- $sessionInactivityTimeout = $ini->variable( 'Session', 'ActivityTimeout' );
- if ( !isset( $GLOBALS['eZSessionIdleTime'] ) )
- {
- eZUser::updateLastVisit( $userId );
- }
- else
- {
- $sessionIdle = $GLOBALS['eZSessionIdleTime'];
- if ( $sessionIdle > $sessionInactivityTimeout )
- {
- eZUser::updateLastVisit( $userId );
- }
- }
- }
- if ( !$currentUser )
- {
- $currentUser = eZUser::fetch( self::anonymousId() );
- eZDebug::writeWarning( 'User not found, returning anonymous' );
- }
- if ( !$currentUser )
- {
- $currentUser = new eZUser( array( 'id' => -1, 'login' => 'NoUser' ) );
- eZDebug::writeWarning( 'Anonymous user not found, returning NoUser' );
- }
- $GLOBALS["eZUserGlobalInstance_$id"] = $currentUser;
- return $currentUser;
- }
- /**
- * Get User cache from cache file
- *
- * @since 4.4
- * @return array( 'info' => array, 'groups' => array, 'roles' => array, 'role_limitations' => array, 'access_array' => array)
- */
- public function getUserCache()
- {
- if ( $this->UserCache === null )
- {
- $this->setUserCache( self::getUserCacheByUserId( $this->ContentObjectID ) );
- }
- return $this->UserCache;
- }
- /**
- * Delete User cache from locale var and cache file for current user.
- *
- * @since 4.4
- */
- public function purgeUserCache()
- {
- $this->UserCache = null;
- self::purgeUserCacheByUserId( $this->ContentObjectID );
- }
- /**
- * Set User cache from cache file
- * Needs to be in excact same format as {@link eZUser::getUserCache()}!
- *
- * @since 4.4
- * @param array $userCache
- */
- public function setUserCache( array $userCache )
- {
- $this->UserCache = $userCache;
- }
- /**
- * Delete User cache from cache file for Anonymous user(usefull for sessionless users)
- *
- * @since 4.4
- * @see eZUser::purgeUserCacheByUserId()
- */
- static public function purgeUserCacheByAnonymousId()
- {
- self::purgeUserCacheByUserId( self::anonymousId() );
- }
- /**
- * Delete User cache pr user
- *
- * @since 4.4
- * @param int $userId
- */
- static public function purgeUserCacheByUserId( $userId )
- {
- $cacheFilePath = eZUser::getCacheDir( $userId ). "/user-data-{$userId}.cache.php" ;
- eZClusterFileHandler::instance()->fileDelete( $cacheFilePath );
- }
- /**
- * Get User cache from cache file for Anonymous user(usefull for sessionless users)
- *
- * @since 4.4
- * @see eZUser::getUserCacheByUserId()
- * @return array
- */
- static public function getUserCacheByAnonymousId()
- {
- return self::getUserCacheByUserId( self::anonymousId() );
- }
- /**
- * Get User cache from cache file (usefull for sessionless users)
- *
- * @since 4.4
- * @see eZUser::getUserCache()
- * @param int $userId
- * @return array
- */
- static protected function getUserCacheByUserId( $userId )
- {
- $cacheFilePath = eZUser::getCacheDir( $userId ). "/user-data-{$userId}.cache.php" ;
- $cacheFile = eZClusterFileHandler::instance( $cacheFilePath );
- return $cacheFile->processCache( array( 'eZUser', 'retrieveUserCacheFromFile' ),
- array( 'eZUser', 'generateUserCacheForFile' ),
- null,
- self::userInfoExpiry(),
- $userId );
- }
- /**
- * Callback which fetches user cache from local file.
- *
- * @internal
- * @since 4.4
- * @see eZUser::getUserCacheByUserId()
- */
- static function retrieveUserCacheFromFile( $filePath, $mtime, $userId )
- {
- return include( $filePath );
- }
- /**
- * Callback which generates user cache for user
- *
- * @internal
- * @since 4.4
- * @see eZUser::getUserCacheByUserId()
- */
- static function generateUserCacheForFile( $filePath, $userId )
- {
- $data = array( 'info' => array(),
- 'groups' => array(),
- 'roles' => array(),
- 'role_limitations' => array(),
- 'access_array' => array(),
- 'discount_rules' => array() );
- $user = eZUser::fetch( $userId );
- if ( $user instanceOf eZUser )
- {
- // user info (session: eZUserInfoCache)
- $data['info'][$userId] = array( 'contentobject_id' => $user->attribute( 'contentobject_id' ),
- 'login' => $user->attribute( 'login' ),
- 'email' => $user->attribute( 'email' ),
- 'password_hash' => $user->attribute( 'password_hash' ),
- 'password_hash_type' => $user->attribute( 'password_hash_type' ) );
- // user groups list (session: eZUserGroupsCache)
- $groups = $user->generateGroupIdList();
- $data['groups'] = $groups;
- // role list (session: eZRoleIDList)
- $groups[] = $userId;
- $data['roles'] = eZRole::fetchIDListByUser( $groups );
- // role limitation list (session: eZRoleLimitationValueList)
- $limitList = $user->limitList( false );
- foreach ( $limitList as $limit )
- {
- $data['role_limitations'][] = $limit['limit_value'];
- }
- // access array (session: AccessArray)
- $data['access_array'] = $user->generateAccessArray();
- // discount rules (session: eZUserDiscountRules<userId>)
- $data['discount_rules'] = eZUserDiscountRule::generateIDListByUserID( $userId );
- }
- return array( 'content' => $data,
- 'scope' => 'user-info-cache',
- 'datatype' => 'php',
- 'store' => true );
- }
- /*!
- Updates the user's last visit timestamp
- Optionally updates user login count by setting $updateLoginCount to true
- */
- static function updateLastVisit( $userID, $updateLoginCount = false )
- {
- if ( isset( $GLOBALS['eZUserUpdatedLastVisit'] ) )
- return;
- $db = eZDB::instance();
- $userID = (int) $userID;
- $userVisitArray = $db->arrayQuery( "SELECT 1 FROM ezuservisit WHERE user_id=$userID" );
- $time = time();
- if ( isset( $userVisitArray[0] ) )
- {
- $loginCountSQL = $updateLoginCount ? ', login_count=login_count+1' : '';
- $db->query( "UPDATE ezuservisit SET last_visit_timestamp=current_visit_timestamp, current_visit_timestamp=$time$loginCountSQL WHERE user_id=$userID" );
- }
- else
- {
- $intialLoginCount = $updateLoginCount ? 1 : 0;
- $db->query( "INSERT INTO ezuservisit ( current_visit_timestamp, last_visit_timestamp, user_id, login_count ) VALUES ( $time, $time, $userID, $intialLoginCount )" );
- }
- $GLOBALS['eZUserUpdatedLastVisit'] = true;
- }
- …
Large files files are truncated, but you can click here to view the full file