Sources for file plugins/class/session.php in version 4.0 Beta 1



Click on a comment to hide it. Click here to show all comments.

/**
 * Project:     Xnyo 4: Bubbles
 * File:        plugins/class/session.php
 *
 * Version:     4.0-dev
 * SVN Id:      $Id: session.php 5 2007-05-18 03:49:07Z bok $
 * SVN URL:     $HeadURL:
http://svn.syd.wholesalebroadband.com.au/xnyo/trunk/plugins/class/session.php $
 * Authors:     Robert Amos <bok[at]odynia.org>
 *
 * Copyright (c) 2001-2007 Robert Amos <bok[at]odynia.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/

/**
 * This file implements the session and authentication modules of Xnyo
**/
class XnyoSession implements XnyoClassPlugin
{
    
// Plugin Information
    
public $_plugin_info = array
    (
        
'name' => 'Xnyo Session/Authentication Plugin',
        
'description' => 'Controls and manages sessions',
        
'action' => XNYO_PLUGIN_ACTION_STORAGE,
        
'varname' => 'session'
    
);

    
// information storage
    
private $ip;
    private 
$browser;
    private 
$lastactivity;
    private 
$expiry;
    private 
$subnet;
    private 
$xnyo;


    
/**
     * Constructor
     *
     * Check current session to ensure it hasnt become invalid
    **/
    
public function __construct ()
    {
        
$this->xnyo $GLOBALS['xnyo_parent'];

        try
        {

            
// have they logged in previously?
            
if (isset($_SESSION['_xnyo_auth']) && is_object($_SESSION['_xnyo_auth']))
            {
                
// store a reference in the Xnyo Object
                
$this->xnyo->user = &$_SESSION['_xnyo_auth'];
                
$this->xnyo->smartyvar->user = (array)$this->xnyo->user;

                
// store a reference to the session timers etc
                
if (!is_array($_SESSION['_xnyo_session']))
                    throw new 
XnyoError('Session Timers not found in $_SESSION, forcing session timeout.');
                
$this->browser =& $_SESSION['_xnyo_session']['browser'];
                
$this->expiry =& $_SESSION['_xnyo_session']['expiry'];
                
$this->subnet =& $_SESSION['_xnyo_session']['subnet'];

                
// check the session expiration
                
if ($this->expiry !== 0)
                {
                    if (
XNYO_DEBUG$this->xnyo->d('Checking session expiration.');

                    
// check to see if now is greater than the timestamp we were supposed to expire
                    
if (time() > $this->expiry)
                        throw new 
XnyoClient($this->xnyo->session->errors['session_timeout'], (time() -
$this->expiry), $this->xnyo->user->email);

                    
// update timer
                    
if (XNYO_DEBUG$this->xnyo->d('Session not expired. Updating session time.');
                    
$this->expiry time() + $this->xnyo->session->lifetime;
                }

                
// check the subnet is still in the same /24
                
if (XNYO_DEBUG$this->xnyo->d('Checking session subnet.');
                if (
$this->subnet != $this->subnet())
                    throw new 
XnyoClient($this->xnyo->session->errors['subnet_change'], $this->subnet,
$this->subnet(), $this->xnyo->user->email);

                
// check the browser is still the same
                
if ($this->browser != $_SERVER['HTTP_USER_AGENT'])
                    throw new 
XnyoClient($this->xnyo->session->errors['browser_change'], $this->browser,
$_SERVER['HTTP_USER_AGENT'], $this->xnyo->user->email);
            }

        } catch (
Exception $e)
        {
            
$this->xnyo->storage->error->raise($e);
            
$this->logout();
        }
    }
    
    
/**
     * Login
     *
     * Opens a session for the current user.
    **/
    
public function login ($user$pass$domain=null)
    {
        try
        {
            
// Authenticating user
            
if (XNYO_DEBUG$this->xnyo->d('Authenticating new user.');

            
// filter both, just in case
            
$user XnyoInput::username($user);
            
$pass XnyoInput::password($pass);

            
// blank username?
            
if (empty($user))
                throw new 
XnyoClient($this->xnyo->session->errors['blank_username']);

            
// blank password?
            
if (empty($pass))
                throw new 
XnyoClient($this->xnyo->session->errors['blank_password']);

            
// no authentication handler?
            
if (!isset($this->xnyo->session->handler))
                throw new 
XnyoError('No authentication plugin configured.');

            
// load plugin
            
$this->handler $this->xnyo->load($this->xnyo->session->handlerXNYO_PLUGIN_AUTH);

            
// call the auth
            
$details $this->handler->login($user$pass$domain);

            
// store details
            
$_SESSION['_xnyo_auth'] = $details;
            
$this->xnyo->user =& $_SESSION['_xnyo_auth'];
            
$this->xnyo->smartyvar->user = (array)$this->xnyo->user;
            
            
// store session information
            
$_SESSION['_xnyo_session'] = array
            (
                
'expiry' => time() + $this->xnyo->session->lifetime,
                
'subnet' => $this->subnet(),
                
'browser' => $_SERVER['HTTP_USER_AGENT']
            );
            
$this->expiry =& $_SESSION['_xnyo_session']['expiry'];
            
$this->subnet =& $_SESSION['_xnyo_session']['subnet'];
            
$this->browser =& $_SESSION['_xnyo_session']['browser'];

            
// all done
            
return true;
            
        } catch (
XnyoClient $e)
        {
            
$this->xnyo->storage->error->raise($e);
            return 
false;
        }
    }
    
    
/**
     * Logout
     *
     * Closes the current session.
    **/
    
public function logout ()
    {
        if (
XNYO_DEBUG$this->xnyo->d('Closing session for user <b>%s</b>.'$this->xnyo->user->email);


        
// destroy the user data
        
$user = clone $_SESSION['_xnyo_auth'];
        unset(
$_SESSION['_xnyo_auth'], $_SESSION['_xnyo_session']);

        
// call the logout handler
        
if (!is_null($this->xnyo->session->logout_handler))
        {
            
$c $this->xnyo->session->logout_handler;
            
$x = new $c($user);
        }

    }
    
    
/**
     * Check current session against the supplied access list
    **/
    
public function check ($acl=null)
    {
        
// no supplied groups? default allow
        
if (is_null($acl) || empty($acl))
            return 
true;

        
// a string? make into an array - has to be a comma or semi-colon delimited list
        
if (!is_array($acl))
            
$acl explode(','str_replace(';'','$acl));

        
// spaces
        
array_walk($acl'trim');

        
// the special "none" ACL overrides all others, indicating they are not allowed to be logged in,
at all
        
if (in_array('none'$acl) && !isset($this->xnyo->user->email))
            return 
true;

        
// likewise the "required" special ACL indicates that they only need to be logged in.
        
if (in_array('required'$acl) && isset($this->xnyo->user->email))
            return 
true;

        
// loop over the group list
        
foreach ($acl as $a)
        {
            
// we can specify usernames in an ACL, is this theirs?
            
if (strtolower($a) == strtolower($this->xnyo->user->email))
                return 
true;

            
// is this a language?
            
if (substr($a05) == 'lang:' && is_array($this->xnyo->session->languages))
            {
                
$l substr($a5);

                
// in the supported language list?
                
if (isset($this->xnyo->session->languages[$l]) || in_array($l$this->xnyo->session->languages))
                    return 
true;
            }

            
// we have a groups list
            
if (is_array($this->xnyo->user->groups))
            {
                
// make the group specified into a regexp - we do allow wildcards though
                
$a '/'.preg_quote($a'/').'/';
                
$a str_replace('\*''.*?'$a);

                
// does this match any of the groups listed?
                
if (count(preg_grep($a$this->xnyo->user->groups)) > 0)
                    return 
true;
            }            
        }

        
// nothing matches
        
return false;
    }
    
    
/**
     * Subnet
     *
     * Make a /24 subnet
    **/
    
public function subnet()
    {
        
// make sure its a legal ip :)
        
$ip XnyoInput::ip($_SERVER['REMOTE_ADDR']);
        
        
// replace the last segment
        
return substr($ip0strrpos($ip'.').'0/24');
    }

    
/**
     * Set an ACL
     *
     * Specifies an ACL for the page being accessed
    **/
    
public function setacl ($acl$redirect=null)
    {
        if (
XNYO_DEBUG$this->xnyo->d('Settings ACL for current page load to <b>%s</b>', (is_array($acl)
join(','$acl) : $acl));

        
// check it
        
try
        {
            if (!
$this->check($acl))
                throw new 
XnyoClient('<b>%s</b> attempted to access page requiring ACL <b>%s</b>',
(isset(
$this->xnyo->user->email) ? 'User '.$this->xnyo->user->email 'Unauthenticated user'),
(
is_array($acl) ? join(','$acl) : $acl));
        } catch (
XnyoClient $e)
        {
            
$this->xnyo->storage->error->raise($e);
            if (!
is_null($redirect))
                
header('Location: '.$redirect);
        }
    }
}

Website is Copyright © Odynia.org 2000-2005 - Xnyo is released under a BSD license.