Seditio Source
Root |
./othercms/ips_4.3.4/system/Session/Store/Database.php
<?php
/**
 * @brief        Database Session Handler
 * @author        <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
 * @copyright    (c) Invision Power Services, Inc.
 * @license        https://www.invisioncommunity.com/legal/standards/
 * @package        Invision Community
 * @since        6 September 2017
 */

namespace IPS\Session\Store;

/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
   
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
    exit;
}

/**
 * Database Session Handler
 */
class _Database extends \IPS\Session\Store
{
   
/**
     * Load the session from the storage engine
     *
     * @param    string    $sessionId    Session ID
     * @return    array
     */
   
public function loadSession( $sessionId )
    {
       
$session = NULL;
       
/* Get from the database */
       
try
        {
           
/* If it looks like we're logged in, join the member row to save a query later */
           
if ( \IPS\Session\Front::loggedIn() )
            {
               
$session = \IPS\Db::i()->select( '*', 'core_sessions', array( 'id=?', $sessionId ), NULL, NULL, NULL, NULL, \IPS\Db::SELECT_MULTIDIMENSIONAL_JOINS )->join( 'core_members', 'core_members.member_id=core_sessions.member_id' )->first();
                if (
$session['core_members']['member_id'] )
                {
                    \
IPS\Member::constructFromData( $session['core_members'], FALSE );
                }
               
$session = $session['core_sessions'];
            }
           
/* If we're not logged in, just look at the session */
           
else
            {
               
$userAgent = \IPS\Http\Useragent::parse();
               
               
/* Spiders match by IP and useragent */
               
if ( $userAgent->spider )
                {
                   
$session = \IPS\Db::i()->select( '*', 'core_sessions', array( 'id=? OR ( ip_address=? AND browser=? )', $sessionId, \IPS\Request::i()->ipAddress(), $_SERVER['HTTP_USER_AGENT'] ) )->first();
                }
               
/* Normal users don't */
               
else
                {
                   
$session = \IPS\Db::i()->select( '*', 'core_sessions', array( 'id=?', $sessionId ) )->first();
                }
            }
        }
        catch ( \
UnderflowException $e ) { }
       
        return
$session;
    }
       
   
/**
     * Update the session storage engine
     *
     * @param    string    $data        Session Data
     * @return void
     */
   
public function updateSession( $data )
    {
        \
IPS\Db::i()->replace( 'core_sessions', $data, TRUE );
    }
   
   
/**
     * Delete from the session engine
     *
     * @param    string    $sessionId    Session ID
     * @return    void
     */
   
public function deleteSession( $sessionId )
    {
        \
IPS\Db::i()->delete( 'core_sessions', array( 'id=?', $sessionId ) );
    }
   
   
/**
     * Delete from the session engine
     *
     * @param    int            $memberId    You can probably figure this out right?
     * @param    string|NULL    $userAgent    User Agent [optional]
     * @param    array|NULL    $keepSessionIds    Array of session ids to keep [optional]
     * @return    void
     */
   
public function deleteByMember( $memberId, $userAgent=NULL, $keepSessionIds=NULL )
    {
       
$where = array( array( 'member_id=?', $memberId ) );
       
        if (
$userAgent )
        {
           
$where[] = array( 'browser=?', $userAgent );
        }
       
        if (
$keepSessionIds )
        {
           
$where[] = array( \IPS\Db::i()->in( 'id', $keepSessionIds, TRUE ) );
        }
       
        \
IPS\Db::i()->delete( 'core_sessions', $where );
    }
   
   
/**
     * Delete from the session engine
     *
     * @param    int        $memberId    You can probably figure this out right?
     * @return    array|FALSE
     */
   
public function getLatestMemberSession( $memberId )
    {
        try
        {
            return \
IPS\Db::i()->select( '*', 'core_sessions', array( 'member_id=?', $memberId ), 'running_time DESC' )->first();
        }
        catch ( \
UnderflowException $e )
        {
            return
FALSE;
        }
    }
   
   
/**
     * Fetch all active session keys
     *
     * @return    array or session IDs
     */
   
public function getSessionIds()
    {
        return
iterator_to_array( \IPS\Db::i()->select( 'id', 'core_sessions' ) );
    }
   
   
/**
     * Clear sessions - abstracted so it can be called externally without initiating a session
     *
     * @param    int        $timeout    Sessions older than the number of seconds provided will be deleted
     * @return void
     */
   
public static function clearSessions( $timeout )
    {
        \
IPS\Db::i()->delete( 'core_sessions', array( 'running_time<?', ( time() - $timeout ) ) );
    }
   
   
/**
     * Fetch all online users (but not spiders)
     *
     * @param    int            $flags                Bitwise flags
     * @param    string        $sort                Sort direction
     * @param    array|NULL    $limit                Limit [ offset, limit ]
     * @param    int            $memberGroup        Limit by a specific member group ID
     * @param    boolean        $showAnonymous        Show anonymously logged in peoples?    
     * @return array
     */
   
public function getOnlineUsers( $flags=0, $sort='desc', $limit=NULL, $memberGroup=NULL, $showAnonymous=FALSE )
    {
       
/* Query */
       
$where = array(
            array(
's.running_time>?', \IPS\DateTime::create()->sub( new \DateInterval( 'PT30M' ) )->getTimeStamp() ),
            array(
"s.login_type!=?", \IPS\Session\Front::LOGIN_TYPE_SPIDER )
        );
       
        if ( !
$showAnonymous )
        {
           
$where[] = array( "s.login_type!=?", \IPS\Session\Front::LOGIN_TYPE_ANONYMOUS );
        }
       
        if ( !
$flags and ! $limit )
        {
           
/* Simple query for PHP processing */
           
return iterator_to_array( \IPS\Db::i()->select( 's.id,s.member_id,s.member_name,s.seo_name,s.member_group,s.login_type', array( 'core_sessions', 's' ), $where, 's.running_time ' . $sort )->setKeyField('id') );
        }
        else
        {
           
/* Complex group by mode with all the lovely trimmings yum */
           
$subWhere = $where;
           
           
/* Ok, this looks odd, but the ONLY_FULL_GROUP_BY bites us here, so selecting max(id) allows us to return a session ID even though we're grouping on member_id */
           
$where = array( array( "( core_sessions.id IN(?) OR ( core_sessions.member_id IS NULL AND core_sessions.login_type != ? AND core_sessions.running_time > ?) )", \IPS\Db::i()->select( 'MAX(id)', array( 'core_sessions', 's' ), $subWhere, NULL, NULL, 'member_id' ), \IPS\Session\Front::LOGIN_TYPE_SPIDER, \IPS\DateTime::create()->sub( new \DateInterval( 'PT30M' ) )->getTimeStamp() ) );
           
           
/* Limiting to a user group? */
           
if ( $memberGroup )
            {
               
$where[] = array( 'core_sessions.member_group=?', $memberGroup );
            }
           
           
/* Just looking for guests? */
           
if ( $flags AND ! ( $flags & static::ONLINE_MEMBERS ) )
            {
               
$where[] = array( '( core_sessions.member_id IS NULL )' );
            }
           
            if (
$flags AND ! ( $flags & static::ONLINE_GUESTS ) )
            {
               
/* No guests */
               
$where[] = array( 'core_sessions.member_id IS NOT NULL' );
            }

           
/* Just fetching a count? */
           
if ( $flags & static::ONLINE_COUNT_ONLY )
            {
                return \
IPS\Db::i()->select( 'COUNT(*)', 'core_sessions', $where )->first();
            }

            return
iterator_to_array( \IPS\Db::i()->select( '*', 'core_sessions', $where, 'core_sessions.running_time ' . $sort, $limit )->setKeyField('id') );
        }
    }
   
   
/**
     * Fetch all members active at a specific location
     *
     * @param    string    $app        Application directory (core, forums, etc)
     * @param    string    $module        Module
     * @param    string    $controller Controller
     * @param    int        $id            Current item ID (empty if none)
     * @param    string    $url        Current viewing URL
     * @return array
     */
   
public function getOnlineMembersByLocation( $app, $module, $controller, $id, $url )
    {
       
$members = array();
       
$where = array(
            array(
'core_sessions.login_type=' . \IPS\Session\Front::LOGIN_TYPE_MEMBER ),
            array(
'core_sessions.current_appcomponent=?', $app ),
            array(
'core_sessions.current_module=?', $module ),
            array(
'core_sessions.current_controller=?', $controller ),
            array(
'core_sessions.running_time>' . \IPS\DateTime::create()->sub( new \DateInterval( 'PT30M' ) )->getTimeStamp() ),
            array(
'core_sessions.location_url IS NOT NULL AND location_url LIKE ?', "{$url}%" ),
            array(
'core_sessions.member_id IS NOT NULL' )
        );

        if(
$id )
        {
           
$where[] = array( 'core_sessions.current_id = ?', \IPS\Request::i()->id );
        }
               
        foreach( \
IPS\Db::i()->select( 'core_sessions.member_id,core_sessions.member_name,core_sessions.seo_name,core_sessions.member_group,core_sessions.login_type,core_sessions.in_editor', 'core_sessions', $where, 'core_sessions.running_time DESC' ) as $row )
        {
            if(
$row['login_type'] == \IPS\Session\Front::LOGIN_TYPE_MEMBER and $row['member_name'] )
            {
               
$members[ $row['member_id'] ] = $row;
            }
        }
       
        return
$members;
    }
}