Subversion Repositories Applications.papyrus

Rev

Rev 1087 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
320 jpm 1
<?php
2
/* vim: set expandtab tabstop=4 shiftwidth=4: */
3
// +----------------------------------------------------------------------+
4
// | PHP Version 4                                                        |
5
// +----------------------------------------------------------------------+
6
// | Copyright (c) 1997-2003 The PHP Group                                |
7
// +----------------------------------------------------------------------+
8
// | This source file is subject to version 2.02 of the PHP license,      |
9
// | that is bundled with this package in the file LICENSE, and is        |
10
// | available at through the world-wide-web at                           |
11
// | http://www.php.net/license/2_02.txt.                                 |
12
// | If you did not receive a copy of the PHP license and are unable to   |
13
// | obtain it through the world-wide-web, please send a note to          |
14
// | license@php.net so we can mail you a copy immediately.               |
15
// +----------------------------------------------------------------------+
16
// | Authors: Martin Jansen <mj@php.net>                                  |
17
// +----------------------------------------------------------------------+
18
//
19
// $Id: Auth.php,v 1.1 2005-03-30 08:50:19 jpm Exp $
20
//
21
 
22
require_once 'PEAR.php';
23
 
24
define('AUTH_IDLED',       -1);
25
define('AUTH_EXPIRED',     -2);
26
define('AUTH_WRONG_LOGIN', -3);
27
 
28
/**
29
 * PEAR::Auth
30
 *
31
 * The PEAR::Auth class provides methods for creating an
32
 * authentication system using PHP.
33
 *
34
 * @author  Martin Jansen <mj@php.net>
35
 * @package Auth
36
 * @version $Revision: 1.1 $
37
 */
38
class Auth {
39
 
40
    /**
41
     * Auth lifetime in seconds
42
     *
43
     * If this variable is set to 0, auth never expires
44
     *
45
     * @var  integer
46
     * @see  setExpire(), checkAuth()
47
     */
48
    var $expire = 0;
49
 
50
    /**
51
     * Has the auth session expired?
52
     *
53
     * @var   bool
54
     * @see   checkAuth(), drawLogin()
55
     */
56
    var $expired = false;
57
 
58
    /**
59
     * Maximum time of idleness in seconds
60
     *
61
     * The difference to $expire is, that the idletime gets
62
     * refreshed each time, checkAuth() is called. If this
63
     * variable is set to 0, idle time is never checked.
64
     *
65
     * @var integer
66
     * @see setIdle(), checkAuth()
67
     */
68
    var $idle = 0;
69
 
70
    /**
71
     * Is the maximum idletime over?
72
     *
73
     * @var boolean
74
     * @see checkAuth(), drawLogin();
75
     */
76
    var $idled = false;
77
 
78
    /**
79
     * Storage object
80
     *
81
     * @var object
82
     * @see Auth(), validateLogin()
83
     */
84
    var $storage = '';
85
 
86
    /**
87
     * Function defined by the user, that creates the login screen
88
     *
89
     * @var string
90
     */
91
    var $loginFunction = '';
92
 
93
    /**
94
     * Should the login form be displayed?
95
     *
96
     * @var   bool
97
     * @see   setShowlogin()
98
     */
99
    var $showLogin = true;
100
 
101
    /**
102
     * Current authentication status
103
     *
104
     * @var string
105
     */
106
    var $status = '';
107
 
108
    /**
109
     * Username
110
     *
111
     * @var string
112
     */
113
    var $username = '';
114
 
115
    /**
116
     * Password
117
     *
118
     * @var string
119
     */
120
    var $password = '';
121
 
122
    /**
123
     * Login callback function name
124
     *
125
     * @var string
126
     * @see setLoginCallback()
127
     */
128
    var $loginCallback = '';
129
 
130
    /**
131
     * Failed Login callback function name
132
     *
133
     * @var string
134
     * @see setLoginFailedCallback()
135
     */
136
    var $loginFailedCallback = '';
137
 
138
    /**
139
     * Logout callback function name
140
     *
141
     * @var string
142
     * @see setLogoutCallback()
143
     */
144
    var $logoutCallback = '';
145
 
146
    /**
147
     * Auth session-array name
148
     *
149
     * @var string
150
     */
151
    var $_sessionName = '_authsession';
152
 
153
    /**
154
     * Package Version
155
     *
156
     * @var string
157
     */
158
    var $version = "1.2.3";
159
 
160
    // {{{ Constructor
161
 
162
    /**
163
     * Constructor
164
     *
165
     * Set up the storage driver.
166
     *
167
     * @param string    Type of the storage driver
168
     * @param mixed     Additional options for the storage driver
169
     *                  (example: if you are using DB as the storage
170
     *                   driver, you have to pass the dsn string here)
171
     *
172
     * @param string    Name of the function that creates the login form
173
     * @param boolean   Should the login form be displayed if neccessary?
174
     * @return void
175
     */
176
    function Auth($storageDriver, $options = '', $loginFunction = '', $showLogin = true)
177
    {
178
        if (!empty($options['sessionName'])) {
179
            $this->_sessionName = $options['sessionName'];
180
            unset($options['sessionName']);
181
        }
182
 
183
        if ($loginFunction != '' && is_callable($loginFunction)) {
184
            $this->loginFunction = $loginFunction;
185
        }
186
 
187
        if (is_bool($showLogin)) {
188
            $this->showLogin = $showLogin;
189
        }
190
 
191
        if (is_object($storageDriver)) {
192
            $this->storage =& $storageDriver;
193
        } else {
194
            $this->storage = $this->_factory($storageDriver, $options);
195
        }
196
        // Pass a reference to auth to the container, ugly but works
197
        // this is used by the DB container to use method setAuthData not staticaly.
198
        $this->storage->_auth_obj =& $this;
199
    }
200
 
201
    // }}}
202
    // {{{ _factory()
203
 
204
    /**
205
     * Return a storage driver based on $driver and $options
206
     *
207
     * @access private
208
     * @static
209
     * @param  string $driver  Type of storage class to return
210
     * @param  string $options Optional parameters for the storage class
211
     * @return object Object   Storage object
212
     */
213
    function _factory($driver, $options = '')
214
    {
215
        $storage_path = 'Auth/Container/' . $driver . '.php';
216
        $storage_class = 'Auth_Container_' . $driver;
217
 
218
        require_once $storage_path;
219
 
220
        return new $storage_class($options);
221
    }
222
 
223
    // }}}
224
    // {{{ assignData()
225
 
226
    /**
227
     * Assign data from login form to internal values
228
     *
229
     * This function takes the values for username and password
230
     * from $HTTP_POST_VARS and assigns them to internal variables.
231
     * If you wish to use another source apart from $HTTP_POST_VARS,
232
     * you have to derive this function.
233
     *
234
     * @access private
235
     * @global $HTTP_POST_VARS
236
     * @see    Auth
237
     * @return void
238
     */
239
    function assignData()
240
    {
241
        $post = &$this->_importGlobalVariable('post');
242
 
243
        if (isset($post['username']) && $post['username'] != '') {
244
            $this->username = (get_magic_quotes_gpc() == 1 ? stripslashes($post['username']) : $post['username']);
245
        }
246
 
247
        if (isset($post['password']) && $post['password'] != '') {
248
            $this->password = (get_magic_quotes_gpc() == 1 ? stripslashes($post['password']) : $post['password'] );
249
        }
250
 
251
    }
252
 
253
    // }}}
254
    // {{{ start()
255
 
256
    /**
257
     * Start new auth session
258
     *
259
     * @access public
260
     * @return void
261
     */
262
    function start()
263
    {
264
        $this->assignData();
265
 
266
        @session_start();
267
 
268
        if (!$this->checkAuth()) {
269
            $this->login();
270
        }
271
    }
272
 
273
    // }}}
274
    // {{{ login()
275
 
276
    /**
277
     * Login function
278
     *
279
     * @access private
280
     * @return void
281
     */
282
    function login()
283
    {
284
        $login_ok = false;
285
 
286
        /**
287
         * When the user has already entered a username,
288
         * we have to validate it.
289
         */
290
        if (!empty($this->username)) {
291
            if (true === $this->storage->fetchData($this->username, $this->password)) {
292
                $login_ok = true;
293
            } else {
294
                if (is_callable($this->loginFailedCallback)) {
295
                    call_user_func($this->loginFailedCallback,$this->username, $this);
296
                }
297
            }
298
        }
299
 
300
        if (!empty($this->username) && $login_ok) {
301
            $this->setAuth($this->username);
302
            if (is_callable($this->loginCallback)) {
303
                call_user_func($this->loginCallback,$this->username, $this);
304
            }
305
        }
306
 
307
        /**
308
         * If the login failed or the user entered no username,
309
         * output the login screen again.
310
         */
311
        if (!empty($this->username) && !$login_ok) {
312
            $this->status = AUTH_WRONG_LOGIN;
313
        }
314
 
315
        if ((empty($this->username) || !$login_ok) && $this->showLogin) {
316
            $this->drawLogin($this->storage->activeUser);
317
            return;
318
        }
319
    }
320
 
321
    // }}}
322
    // {{{ setExpire()
323
 
324
    /**
325
     * Set the maximum expire time
326
     *
327
     * @access public
328
     * @param  integer time in seconds
329
     * @param  bool    add time to current expire time or not
330
     * @return void
331
     */
332
    function setExpire($time, $add = false)
333
    {
334
        if ($add) {
335
            $this->expire += $time;
336
        } else {
337
            $this->expire = $time;
338
        }
339
    }
340
 
341
    // }}}
342
    // {{{ setIdle()
343
 
344
    /**
345
     * Set the maximum idle time
346
     *
347
     * @access public
348
     * @param  integer time in seconds
349
     * @param  bool    add time to current maximum idle time or not
350
     * @return void
351
     */
352
    function setIdle($time, $add = false)
353
    {
354
        if ($add) {
355
            $this->idle += $time;
356
        } else {
357
            $this->idle = $time;
358
        }
359
    }
360
 
361
    // }}}
362
    // {{{ setSessionname()
363
 
364
    /**
365
     * Set name of the session to a customized value.
366
     *
367
     * If you are using multiple instances of PEAR::Auth
368
     * on the same domain, you can change the name of
369
     * session per application via this function.
370
     *
371
     * @access public
372
     * @param  string New name for the session
373
     * @return void
374
     */
375
    function setSessionname($name = 'PHPSESSID')
376
    {
377
        @session_name($name);
378
    }
379
 
380
    // }}}
381
    // {{{ setShowLogin()
382
 
383
    /**
384
     * Should the login form be displayed if neccessary?
385
     *
386
     * @access public
387
     * @param  bool    show login form or not
388
     * @return void
389
     */
390
    function setShowLogin($showLogin = true)
391
    {
392
        $this->showLogin = $showLogin;
393
    }
394
 
395
    /**
396
     * Register a callback function to be called on user login.
397
     * The function will receive two parameters, the username and a reference to the auth object.
398
     *
399
     * @access public
400
     * @param  string  callback function name
401
     * @return void
402
     * @see    setLogoutCallback()
403
     */
404
    function setLoginCallback($loginCallback)
405
    {
406
        $this->loginCallback = $loginCallback;
407
    }
408
 
409
    /**
410
     * Register a callback function to be called on failed user login.
411
     * The function will receive a single parameter, the username and a reference to the auth object.
412
     *
413
     * @access public
414
     * @param  string  callback function name
415
     * @return void
416
     */
417
    function setFailedLoginCallback($loginFailedCallback)
418
    {
419
        $this->loginFailedCallback = $loginFailedCallback;
420
    }
421
 
422
    /**
423
     * Register a callback function to be called on user logout.
424
     * The function will receive three parameters, the username and a reference to the auth object.
425
     *
426
     * @access public
427
     * @param  string  callback function name
428
     * @return void
429
     * @see    setLoginCallback()
430
     */
431
    function setLogoutCallback($logoutCallback)
432
    {
433
        $this->logoutCallback = $logoutCallback;
434
    }
435
 
436
    // }}}
437
    // {{{ setAuthData()
438
 
439
    /**
440
     * Register additional information that is to be stored
441
     * in the session.
442
     *
443
     * @access public
444
     * @param  string  Name of the data field
445
     * @param  mixed   Value of the data field
446
     * @param  boolean Should existing data be overwritten? (default
447
     *                 is true)
448
     * @return void
449
     */
450
    function setAuthData($name, $value, $overwrite = true)
451
    {
452
        $session = &Auth::_importGlobalVariable('session');
453
 
454
        if (!empty($session[$this->_sessionName]['data'][$name]) && $overwrite == false) {
455
            return;
456
        }
457
        $session[$this->_sessionName]['data'][$name] = $value;
458
    }
459
 
460
    // }}}
461
    // {{{ getAuthData()
462
 
463
    /**
464
     * Get additional information that is stored in the session.
465
     *
466
     * If no value for the first parameter is passed, the method will
467
     * return all data that is currently stored.
468
     *
469
     * @access public
470
     * @param  string Name of the data field
471
     * @return mixed  Value of the data field.
472
     */
473
    function getAuthData($name = null)
474
    {
475
        $session = &Auth::_importGlobalVariable('session');
476
        if(!isset($session[$this->_sessionName]['data'])){
477
            return(null);
478
        }
479
 
480
        if (is_null($name)) {
481
            if(isset($session[$this->_sessionName]['data'])) {
482
                return $session[$this->_sessionName]['data'];
483
            } else {
484
                return null;
485
            }
486
        }
487
        if (isset($session[$this->_sessionName]['data'][$name])) {
488
            return $session[$this->_sessionName]['data'][$name];
489
        } else {
490
            return null;
491
        }
492
    }
493
 
494
    // }}}
495
    // {{{ setAuth()
496
 
497
    /**
498
     * Register variable in a session telling that the user
499
     * has logged in successfully
500
     *
501
     * @access public
502
     * @param  string Username
503
     * @return void
504
     */
505
    function setAuth($username)
506
    {
507
        $session = &Auth::_importGlobalVariable('session');
508
 
509
        if (!isset($session[$this->_sessionName]) && !isset($_SESSION)) {
510
            session_register($this->_sessionName);
511
        }
512
 
513
        if (!isset($session[$this->_sessionName]) || !is_array($session[$this->_sessionName])) {
514
            $session[$this->_sessionName] = array();
515
        }
516
 
517
        if(!isset($session[$this->_sessionName]['data'])){
518
            $session[$this->_sessionName]['data']       = array();
519
        }
520
        $session[$this->_sessionName]['registered'] = true;
521
        $session[$this->_sessionName]['username']   = $username;
522
        $session[$this->_sessionName]['timestamp']  = time();
523
        $session[$this->_sessionName]['idle']       = time();
524
    }
525
 
526
    // }}}
527
    // {{{ checkAuth()
528
 
529
    /**
530
     * Checks if there is a session with valid auth information.
531
     *
532
     * @access private
533
     * @return boolean  Whether or not the user is authenticated.
534
     */
535
    function checkAuth()
536
    {
537
        $session = &$this->_importGlobalVariable('session');
538
 
539
        if (isset($session[$this->_sessionName])) {
540
            // Check if authentication session is expired
541
            if ($this->expire > 0 &&
542
                isset($session[$this->_sessionName]['timestamp']) &&
543
                ($session[$this->_sessionName]['timestamp'] + $this->expire) < time()) {
544
 
545
                $this->logout();
546
                $this->expired = true;
547
                $this->status = AUTH_EXPIRED;
548
 
549
                return false;
550
            }
551
 
552
            // Check if maximum idle time is reached
553
            if ($this->idle > 0 &&
554
                isset($session[$this->_sessionName]['idle']) &&
555
                ($session[$this->_sessionName]['idle'] + $this->idle) < time()) {
556
 
557
                $this->logout();
558
                $this->idled = true;
559
                $this->status = AUTH_IDLED;
560
 
561
                return false;
562
            }
563
 
564
            if (isset($session[$this->_sessionName]['registered']) &&
565
                isset($session[$this->_sessionName]['username']) &&
566
                $session[$this->_sessionName]['registered'] == true &&
567
                $session[$this->_sessionName]['username'] != '') {
568
 
569
                Auth::updateIdle();
570
 
571
                return true;
572
            }
573
        }
574
 
575
        return false;
576
    }
577
 
578
    // }}}
579
    // {{{ getAuth()
580
 
581
    /**
582
     * Has the user been authenticated?
583
     *
584
     * @access public
585
     * @return bool  True if the user is logged in, otherwise false.
586
     */
587
    function getAuth()
588
    {
589
        $session = &$this->_importGlobalVariable('session');
590
 
591
        if (!empty($session) &&
592
            (isset($session[$this->_sessionName]['registered']) &&
593
             $session[$this->_sessionName]['registered'] === true))
594
        {
595
            return true;
596
        } else {
597
            return false;
598
        }
599
    }
600
 
601
    // }}}
602
    // {{{ drawLogin()
603
 
604
    /**
605
     * Draw the login form
606
     *
607
     * Normally you will not use this output in your application,
608
     * because you can pass a different function name to the
609
     * constructor. For more information on this, please
610
     * consult the documentation.
611
     *
612
     * @access private
613
     * @param  string  Username if already entered
614
     * @return void
615
     */
616
    function drawLogin($username = '')
617
    {
618
        if (is_callable($this->loginFunction)) {
619
            call_user_func($this->loginFunction, $username, $this->status, $this);
620
        } else {
621
            $server = &$this->_importGlobalVariable('server');
622
 
623
            echo '<center>'."\n";
624
 
625
            if (!empty($this->status) && $this->status == AUTH_EXPIRED) {
626
                echo '<i>Your session expired. Please login again!</i>'."\n";
627
            } else if (!empty($this->status) && $this->status == AUTH_IDLED) {
628
                echo '<i>You have been idle for too long. Please login again!</i>'."\n";
629
            } else if (!empty ($this->status) && $this->status == AUTH_WRONG_LOGIN) {
630
                echo '<i>Wrong login data!</i>'."\n";
631
            }
632
 
633
            PEAR::raiseError('You are using the built-in login screen of PEAR::Auth.<br />See the <a href="http://pear.php.net/manual/">manual</a> for details on how to create your own login function.', null);
634
 
635
            echo '<form method="post" action="' . $server['PHP_SELF'] . '">'."\n";
636
            echo '<table border="0" cellpadding="2" cellspacing="0" summary="login form">'."\n";
637
            echo '<tr>'."\n";
638
            echo '    <td colspan="2" bgcolor="#eeeeee"><b>Login:</b></td>'."\n";
639
            echo '</tr>'."\n";
640
            echo '<tr>'."\n";
641
            echo '    <td>Username:</td>'."\n";
642
            echo '    <td><input type="text" name="username" value="' . $username . '" /></td>'."\n";
643
            echo '</tr>'."\n";
644
            echo '<tr>'."\n";
645
            echo '    <td>Password:</td>'."\n";
646
            echo '    <td><input type="password" name="password" /></td>'."\n";
647
            echo '</tr>'."\n";
648
            echo '<tr>'."\n";
649
            echo '    <td colspan="2" bgcolor="#eeeeee"><input type="submit" /></td>'."\n";
650
            echo '</tr>'."\n";
651
            echo '</table>'."\n";
652
            echo '</form>'."\n";
653
            echo '</center>'."\n\n";
654
        }
655
    }
656
 
657
    // }}}
658
    // {{{ logout()
659
 
660
    /**
661
     * Logout function
662
     *
663
     * This function clears any auth tokens in the currently
664
     * active session and executes the logout callback function,
665
     * if any
666
     *
667
     * @access public
668
     * @return void
669
     */
670
    function logout()
671
    {
672
        $session = &$this->_importGlobalVariable('session');
673
 
674
        if (is_callable($this->logoutCallback)) {
675
            call_user_func($this->logoutCallback, $session[$this->_sessionName]['username'], $this);
676
        }
677
 
678
        $this->username = '';
679
        $this->password = '';
680
 
681
        $session[$this->_sessionName] = array();
682
        if (isset($_SESSION)) {
683
            unset($session[$this->_sessionName]);
684
        } else {
685
            session_unregister($this->_sessionName);
686
        }
687
    }
688
 
689
    // }}}
690
    // {{{ updateIdle()
691
 
692
    /**
693
     * Update the idletime
694
     *
695
     * @access private
696
     * @return void
697
     */
698
    function updateIdle()
699
    {
700
        $session = &$this->_importGlobalVariable('session');
701
       $session[$this->_sessionName]['idle'] = time();
702
    }
703
 
704
    // }}}
705
    // {{{ getUsername()
706
 
707
    /**
708
     * Get the username
709
     *
710
     * @access public
711
     * @return string
712
     */
713
    function getUsername()
714
    {
715
        $session = &$this->_importGlobalVariable('session');
716
        if (!isset($session[$this->_sessionName]['username'])) {
717
            return '';
718
        }
719
        return $session[$this->_sessionName]['username'];
720
    }
721
 
722
    // }}}
723
    // {{{ getStatus()
724
 
725
    /**
726
     * Get the current status
727
     *
728
     * @access public
729
     * @return string
730
     */
731
    function getStatus()
732
    {
733
        return $this->status;
734
    }
735
 
736
    // }}}
737
    // {{{ sessionValidThru()
738
 
739
    /**
740
     * Returns the time up to the session is valid
741
     *
742
     * @access public
743
     * @return integer
744
     */
745
    function sessionValidThru()
746
    {
747
        $session = &$this->_importGlobalVariable('session');
748
        if (!isset($session[$this->_sessionName]['idle'])) {
749
            return 0;
750
        }
751
        return ($session[$this->_sessionName]['idle'] + $this->idle);
752
    }
753
 
754
    // }}}
755
    // {{{ listUsers()
756
 
757
    /**
758
     * List all users that are currently available in the storage
759
     * container
760
     *
761
     * @access public
762
     * @return array
763
     */
764
    function listUsers()
765
    {
766
        return $this->storage->listUsers();
767
    }
768
 
769
    // }}}
770
    // {{{ addUser()
771
 
772
    /**
773
     * Add user to the storage container
774
     *
775
     * @access public
776
     * @param  string Username
777
     * @param  string Password
778
     * @param  mixed  Additional parameters
779
     * @return mixed  True on success, PEAR error object on error
780
     *                and AUTH_METHOD_NOT_SUPPORTED otherwise.
781
     */
782
    function addUser($username, $password, $additional = '')
783
    {
784
        return $this->storage->addUser($username, $password, $additional);
785
    }
786
 
787
    // }}}
788
    // {{{ removeUser()
789
 
790
    /**
791
     * Remove user from the storage container
792
     *
793
     * @access public
794
     * @param  string Username
795
     * @return mixed  True on success, PEAR error object on error
796
     *                and AUTH_METHOD_NOT_SUPPORTED otherwise.
797
     */
798
    function removeUser($username)
799
    {
800
        return $this->storage->removeUser($username);
801
    }
802
 
803
    // }}}
804
    // {{{ _importGlobalVariable()
805
 
806
    /**
807
     * Import variables from special namespaces.
808
     *
809
     * @access private
810
     * @param string Type of variable (server, session, post)
811
     * @return array
812
     */
813
    function &_importGlobalVariable($variable)
814
    {
815
        $var = null;
816
 
817
        switch (strtolower($variable)) {
818
 
819
            case 'server' :
820
                if (isset($_SERVER)) {
821
                    $var = &$_SERVER;
822
                } else {
823
                    $var = &$GLOBALS['HTTP_SERVER_VARS'];
824
                }
825
                break;
826
 
827
            case 'session' :
828
                if (isset($_SESSION)) {
829
                    $var = &$_SESSION;
830
                } else {
831
                    $var = &$GLOBALS['HTTP_SESSION_VARS'];
832
                }
833
                break;
834
 
835
            case 'post' :
836
                if (isset($_POST)) {
837
                    $var = &$_POST;
838
                } else {
839
                    $var = &$GLOBALS['HTTP_POST_VARS'];
840
                }
841
                break;
842
 
843
            case 'cookie' :
844
                if (isset($_COOKIE)) {
845
                    $var = &$_COOKIE;
846
                } else {
847
                    $var = &$GLOBALS['HTTP_COOKIE_VARS'];
848
                }
849
                break;
850
 
851
            case 'get' :
852
                if (isset($_GET)) {
853
                    $var = &$_GET;
854
                } else {
855
                    $var = &$GLOBALS['HTTP_GET_VARS'];
856
                }
857
                break;
858
 
859
            default:
860
                break;
861
 
862
        }
863
 
864
        return $var;
865
    }
866
 
867
    // }}}
868
}
869
?>