<?php // ۞// text { encoding:utf-8 ; bom:no ; linebreaks:unix ; tabs:4sp ; }
if (realpath ($_SERVER['SCRIPT_FILENAME'] )   ==   realpath __FILE__ ))  {
    @include 
$_SERVER['DOCUMENT_ROOT'].'/inc/source-dump.php';
                                                    
source_dump(__FILE__); }
/*

    pajamas
    modular authentication system

    For full details, usage instructions, etc, see the accomanying readme.
    If you you got this without a readme, check out the link below.

    If you need help, mail me @ corz.org, or if you think a solution to your
    issue would be valuable to others, drop a comment on the pajamas page..

        http://corz.org/server/security/pajamas.php

    Have fun!

    ;o) Cor

    ps..    Big thanks to PCheese for all the help with the OOP.
            d00D! I get it now!  And I hope you like where I took it. ;o)


    (c) 2004->tomorrow! ~ cor + corz.org ;o)

    Please view the license for this free software, here:

        http://corz.org/free-scripts-licence.nfo

*/

/*
    pajamas authentication..
                                */

class pajamas {

/*
    version

    Currently, we have the bare bones of the thing, and it works great!
    There may yet be bugs, and all bug reports are wholeheartedly welcomed.

    */
    
var $_version            '0.3';



        
/*        public properties..        */


/*
    default module

    (string)    name of module file (minus .php extension)


        current choices are 'plain' or 'pj' (the best)

        If, for some insane reason, you don't have access to a JavaScript-
        capable browser, use 'plain', otherwise, use 'pj'.

        the plain module can be configured in exactly the same way as
        the pajamas module, and has many of its features, too; sessions, IP
        check, time-out, etc., the only difference being that the password is
        sent over the wire in plain text.

        Though unlike HTTP basic authentication, which send the password with
        every single request, with the plain module, the password travels over
        the wires one time only.

    */
    
var $_default_module    'pj';


/*
    password

    (string)    default: 'password';

        a quick and dirty way to store your password..

        or you could keep it in a database, or include from another file,.
        include '/some/other/place/config.php'; and set it externally..

            $auth->_login_password = 'MyPassword';

        Passwords are case-sensitive.

    */
    
var $_login_password    'password';


/*
    IP address check?

    boolean (true/false)    default: true;

        normally, we check the IP address of the authorising browser. However, if the user
        is behind a proxy farm (very unusual), this will break his session, as his IP will
        change with (possibly) each request. If you have users behind proxy farms, (or you
        are) set this to false, or else advise them to use *yet another* proxy (two proxies).

    */
    
var $_check_ip          true;



/*
    do time-out?

    boolean            default: true;

        we can specify a time-out for the session.  if you set this to false,
        the session is live until the client's browser is quit, or they log out.

    */
    
var $_do_time_out       true;


/*
    time-out

    integer    (in minutes)     default: 60;

        an hour is reasonable, anything goes. the demo uses 0.5 (30 seconds)

    */
    
var $_session_time      60;

/*
    big luser

    integer    (max failed attempts)     default: 10;

        they tried and tried, but it just isn't happening. Or else they are taking the p*ss.
        A script perhaps, some brute force. Whatever, it would probably be best for everyone
        if we halted them in their tracks after how many failed login attempts?

    */
    
var $_big_luser         10;

/*
    kick bad users?

    boolean (true/false)    default: false;

        optionally we can prevent even correct logins from browsers that repeatedly sent bad logins..

        If you set this to true, after($_big_luser) failed login attempts, the property
        "$auth->_bad_user" will be set to true. Now, even a correct login will fail to authenticate.

        You can check for bad users, and then do what you like with them..

            if ($auth->_bad_user) { die('go away!');

        If you leave kick_bad_users set to false, a correct login will override all previous bad logins.

        The idea is, someone may be attempting to login from your terminal, and fail, so they receive
        a message informing them of the futility of it, *hopefully* they will stop now. If the *real*
        admin comes along, he should be able to log straight in, and shouldn't have the inconvenience
        of restarting the browser just because some twat was fooling around. But you can disable this
        behaviour by simply setting this to true.

    */
    
var $_kick_bad_users    false;



/*
    show error messages?

    boolean (true/false)    default: true;

        pj generates some messages for the various error conditions, you can use these however
        you like, and latest message is always in "_auth_message"

        If you like, you can have pj display these messages just above the login form,
        so the user is aware that their password was incorrect, or whatever..

    */
    
var $_do_messages       true;

/*
    create containing forms?

    boolean (true/false)    default: true;

        If you are already inside a form, set this to false to avoid nesting forms,
        which will break xhtml valiadation, among other things (including the md5)..

            $auth->_createForms = false;

        Remember you can also pass "true" to your form input function, to have a
        simple, div-less output, like this..

            echo $auth->getLoginForm(true);

    */
    
var $_createForms       true;


/*
    autocomplete="off"

    boolean (true/false)    default: true; (doesn't validate, but hey!)

        a good, mostly supported proprietary Internet Explorer property.

        This will break strict xhtml validation (which is annoying), but you may feel
        that it's worth it. With this set to true, browsers will not annoy you to try
        and save the password (which, at least with the 'pj' module, is a one-shot
        mish-mash that will become useless the instant you logout).

        It will only break your xhtml validation until you login, of course.

        Set this to true to add 'autocomplete="off"' to your password field. TADA!
        One of the rare occasions where Internet Explorer leads the way! If you are
        obsessed with strict xhtml 1.0 validation, screw your users and set this to
        false.

        btw: if you known an xhtml-friendly way to do this, MAIL ME! ;o)

    */
    
var $_no_autocomplete    true;


/*
    code loaction.

    (string)    default: '';

        Some modules may require included code.

        In "pj", this sets the default location of javascript MD5 functions file and
        will be used to create the <script> tag that includes the JavaScript MD5
        functions on your page, like this..

            echo $auth->getAuthCode();

        You can override the location by setting this..

            $auth->_code_location = 'inc/md5.js';

        *before* you echo the code. relative or absolute paths are fine, just like a
        regular javascript include.

    */
    
var $_code_location        '';

/*
    a simple error catcher.
    boolean (true/false)    default: true;

        session errors of level "E_NOTICE" (type 8) will be caught and stored,
        rather than spew onto your page. use..

            echo $auth->getErrors();

        to see them, or pipe that somewhere else. essentially this saves having
        your pages all messed up when you are testing your pj implementation on
        a server with error level E_ALL set (all development servers, yeah?),
        mainly for "session already started" type errors. It was annoying!

        we throw errors into a global variable because a) I use this system for
        errors anyway, (my debug script throws me a pop-up if it finds anything in
        $GLOBALS['errors'], and b) variables inside error handlers are a disaster!

    */
    
var $_error_catcher        true;



    
/*

        Private properties.
        DO NOT CHANGE THESE.

        You shouldn't change anything above either;
        set it externally like so..

        $auth->_do_time_out = false;

    */
    
var $_auth_message        '';
    var 
$_auth_module        ''// a pointer to *real* auth class
    
var $_bad_user            false;
    var 
$_default_uid        'pajamas';
    var 
$_is_authenticated  null;    // start out in unknown (unset) state
    
var $_module_loaded        false;
    var 
$_modules_path        'modules/';
    var 
$_interface            'advanced';    // 'advanced' or 'simple'


    // constructor..
    
function pajamas ($uniqueid='') {
        if (!empty(
$uniqueid) and ctype_alnum($uniqueid)) {
            
$this->_unique_id $uniqueid;
        } else {
            
$this->_unique_id $this->_default_uid;
        }
        if (
$this->_error_catcher) {
            
$this->startErrorHandler();
        }
    }

    function 
authModule() {

        include 
$this->_modules_path.$this->_default_module.'.php';
        
$this->_auth_module = new authModule($this->_unique_id);

        
// setup its preferences..
        // (we could perhaps check module's capabilities and only set those)
        
if ($this->_interface != 'simple') {
            
$this->_auth_module->_login_password        $this->_login_password;
            
$this->_auth_module->_check_ip                $this->_check_ip;
            
$this->_auth_module->_do_time_out            $this->_do_time_out;
            
$this->_auth_module->_session_time            $this->_session_time;
            
$this->_auth_module->_big_luser                $this->_big_luser;
            
$this->_auth_module->_kick_bad_users        $this->_kick_bad_users;
            
$this->_auth_module->_do_messages            $this->_do_messages;
            
$this->_auth_module->_createForms            $this->_createForms;
            
$this->_auth_module->_no_autocomplete        $this->_no_autocomplete;
        }
        
$this->_module_loaded true;
    }

    function 
auth_user() {

        if (!
$this->_module_loaded) { $this->authModule(); }
        if (
$this->_is_authenticated) { return true; }

        
$auth_status $this->_auth_module->auth_user();
        
$this->_auth_message $this->_auth_module->_auth_message;

        if (
$auth_status) {
            
$this->_is_authenticated true;
            return 
true;
        } else {
            
$this->_is_authenticated false;
            return 
false;
        }
    }

    function 
getAuthCode() {
        
// this will need to load before authentication,
        // so we set it here, and now overriding works as expected.
        
$this->_auth_module->_code_location    $this->_code_location;
        
$html $this->_auth_module->getAuthCode();
        if (!empty(
$html)) { return $html; }
            else { return 
''; }
    }

    function 
getLoginForm($simple=false) {
        return 
$this->_auth_module->getLoginForm($simple);
    }

    function 
getLogoutButton($simple=false) {
        return 
$this->_auth_module->getLogoutButton($simple);
    }

    function 
getSelf() {
        return 
$_SERVER['SCRIPT_NAME'];
    }

    function 
getBadUser() {
        return 
$this->_auth_module->_bad_user;
    }

    function 
remainingTime() {
        if (
$this->_do_time_out) {
            
$now explode(' ',microtime());
            
$time $now[1].substr($now[0],2,2);
            
settype($time'double'); // 100th/second..
            
return (($this->_session_time 6000) - ($time $_SESSION['auth'.$this->_unique_id]['login_at'])) / 100;
        } else { return 
false; }
    }

/*
    a simple session error catcher..
    */
    
function getErrors() {
        if (!empty(
$GLOBALS['errors']['pajamas'])) {
            return 
$GLOBALS['errors']['pajamas'];
        }
    }
    function 
startErrorHandler() {
        
set_error_handler(array($this'handle_error'));
    }
    function 
handle_error($type$string$file$line$vars) {
        switch (
TRUE) {
            case (
$type == and stristr($string'session')): // doesn't look so clever with only one case!
                
if (empty($GLOBALS['errors']['pajamas'])) { $GLOBALS['errors']['pajamas'] = ''; }
                
$GLOBALS['errors']['pajamas'] .= 'NOTICE! session error on line '.$line.' of '.$file.': '.$string;
                return 
true;
                break; 
// *ahem*
            
default:
                return 
false// better let php handle this one.
        
}
    }

// end class pajamas()



class pajamasSimple extends pajamas {

    function 
pajamasSimple($uniqueid='') {

        if (!empty(
$uniqueid) and strstr($uniqueid'-')) {
            
$simple_prefs explode('-'$uniqueid);
            
$uniqueid trim($simple_prefs[0]);
            if (!empty(
$simple_prefs[1])) { $my_module trim($simple_prefs[1]); }
        }
        
parent::pajamas($uniqueid);
        
$this->_interface 'simple';

        if (!empty(
$my_module)) { $this->_default_module $my_module; }
        if (!
$this->_module_loaded) { $this->authModule(); }

        if (!empty(
$this->_auth_module->_code_location)) {
            
$this->_code_location $this->_auth_module->_code_location;
        }
        echo 
$this->getAuthCode();

        if (
$this->_auth_module->auth_user()) {
            echo 
$this->_auth_module->getLogoutButton();
        } else {
            echo 
$this->_auth_module->getLoginForm();
        }
    }

}


/*

    version history

    0.3
    fixed bug, not passing variables through to getLogoutButton() and getLoginForm()

    0.2
    first public release of pajamas engine

    0.1
    basic authentication module loader. almost works.

*/



?>