LiveUser
[ class tree: LiveUser ] [ index: LiveUser ] [ all elements ]

Source for file Common.php

Documentation is available at Common.php

  1. <?php
  2. // LiveUser: A framework for authentication and authorization in PHP applications
  3. // Copyright (C) 2002-2003 Markus Wolff
  4. //
  5. // This library is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU Lesser General Public
  7. // License as published by the Free Software Foundation; either
  8. // version 2.1 of the License, or (at your option) any later version.
  9. //
  10. // This library is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13. // Lesser General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU Lesser General Public
  16. // License along with this library; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  
  19. /**
  20.  * Description:
  21.  * This class provides a set of functions for implementing a user
  22.  * authorisation system on live websites. All authorisation
  23.  * backends/containers must be extensions of this base class.
  24.  *
  25.  * Requirements:
  26.  * - When using "DB" backend:
  27.  *   PEAR::DB database abstraction layer
  28.  * - LiveUser admin GUI for easy user administration and setup of
  29.  *   authorisation areas and rights
  30.  *
  31.  * @author   Markus Wolff <wolff@21st.de>
  32.  * @version  $Id: Common.php,v 1.40 2004/04/23 18:58:31 dufuz Exp $
  33.  * @package  LiveUser
  34.  * @category authentication
  35.  */
  36. {
  37.     /**
  38.      * The handle (username) of the current user
  39.      *
  40.      * @var string 
  41.      */
  42.     var $handle = '';
  43.  
  44.     /**
  45.      * The password of the current user as given to the
  46.      * login() method.
  47.      *
  48.      * @var string 
  49.      */
  50.     var $passwd = '';
  51.  
  52.     /**
  53.      * Current user's database record id
  54.      *
  55.      * @var integer 
  56.      */
  57.     var $authUserId = 0;
  58.  
  59.     /**
  60.      * Is the current user allowed to login at all? If false,
  61.      * a call to login() will not set $logged_in to true, even
  62.      * if handle and password were submitted correctly. This is
  63.      * useful when you want your users to be activated by an
  64.      * administrator before they can actually use your application.
  65.      * Default: false
  66.      *
  67.      * @var boolean 
  68.      * @see $logged_in
  69.      */
  70.     var $isActive = false;
  71.  
  72.     /**
  73.      * Has the current user successfully logged in?
  74.      * Default: false
  75.      *
  76.      * @var boolean 
  77.      * @see $is_active
  78.      */
  79.     var $loggedIn = false;
  80.  
  81.     /**
  82.      * Timestamp of last login (previous to currentLogin)
  83.      *
  84.      * @var integer 
  85.      */
  86.     var $lastLogin = 0;
  87.  
  88.     /**
  89.      * Timestamp of current login (last to be written)
  90.      *
  91.      * @var integer 
  92.      */
  93.     var $currentLogin = 0;
  94.  
  95.     /**
  96.      * Number of hours that must pass between two logins
  97.      * to be counted as a new login. Comes in handy in
  98.      * some situations. Default: 12
  99.      *
  100.      * @var integer 
  101.      */
  102.     var $loginTimeout = 12;
  103.  
  104.     /**
  105.      * Auth lifetime in seconds
  106.      *
  107.      * If this variable is set to 0, auth never expires
  108.      *
  109.      * @var  integer 
  110.      */
  111.     var $expireTime = 0;
  112.  
  113.     /**
  114.      * Maximum time of idleness in seconds
  115.      *
  116.      * Idletime gets refreshed each time, init() is called. If this
  117.      * variable is set to 0, idle time is never checked.
  118.      *
  119.      * @var integer 
  120.      */
  121.     var $idleTime = 0;
  122.  
  123.     /**
  124.      * Allow multiple users in the database to have the same
  125.      * login handle. Default: false.
  126.      *
  127.      * @var boolean 
  128.      */
  129.     var $allowDuplicateHandles = false;
  130.  
  131.     /**
  132.      * Set posible encryption modes.
  133.      *
  134.      * $var array
  135.      */
  136.     var $encryptionModes = array('MD5'   => 'MD5',
  137.                                  'PLAIN' => 'PLAIN',
  138.                                  'RC4'   => 'RC4',
  139.                                  'SHA1'  => 'SHA1');
  140.  
  141.  
  142.     /**
  143.      * Defines the algorithm used for encrypting/decrypting
  144.      * passwords. Default: "MD5".
  145.      *
  146.      * @var string 
  147.      */
  148.     var $passwordEncryptionMode = 'MD5';
  149.  
  150.     /**
  151.      * Defines the array index number of the LoginManager?s "backends" property.
  152.      *
  153.      * @var integer 
  154.      */
  155.     var $backendArrayIndex = 0;
  156.  
  157.     /**
  158.      * Indicates if backend module initialized correctly. If yes,
  159.      * true, if not false. Backend module won't initialize if the
  160.      * init value (usually an object or resource handle that
  161.      * identifies the backend to be used) is not of the required
  162.      * type.
  163.      * @var boolean 
  164.      * @access public
  165.      */
  166.     var $init_ok = false;
  167.  
  168.     /**
  169.      * Class constructor. Feel free to override in backend subclasses.
  170.      */
  171.     function LiveUser_Auth_Common($connectOptions)
  172.     {
  173.         if (is_array($connectOptions)) {
  174.             foreach ($connectOptions as $key => $value{
  175.                 if (isset($this->$key)) {
  176.                     $this->$key $value;
  177.                 }
  178.             }
  179.         }
  180.     }
  181.  
  182.     /**
  183.      * store all properties in an array
  184.      *
  185.      * @access  public
  186.      */
  187.     function freeze()
  188.     {
  189.         $propertyValues = array(
  190.             'handle' => $this->handle,
  191.             'passwd' => $this->passwd,
  192.             'authUserId' => $this->authUserId,
  193.             'isActive' => $this->isActive,
  194.             'loggedIn' => $this->loggedIn,
  195.             'lastLogin' => $this->lastLogin,
  196.             'currentLogin' => $this->currentLogin,
  197.         );
  198.         return $propertyValues;
  199.     // end func freeze
  200.  
  201.     /**
  202.      * properly disconnect from resources
  203.      *
  204.      * @access  public
  205.      */
  206.     function disconnect()
  207.     {
  208.     }
  209.  
  210.     /**
  211.      * Reinitializes properties
  212.      *
  213.      * @access  public
  214.      * @param   array  $propertyValues 
  215.      */
  216.     function unfreeze($propertyValues)
  217.     {
  218.         foreach ($propertyValues as $key => $value{
  219.             $this->{$key$value;
  220.         }
  221.     // end func unfreeze
  222.  
  223.     /**
  224.      * Decrypts a password so that it can be compared with the user
  225.      * input. Uses the algorithm defined in the passwordEncryptionMode
  226.      * property.
  227.      *
  228.      * @param  string the encrypted password
  229.      * @return string The decrypted password
  230.      */
  231.     function decryptPW($encryptedPW)
  232.     {
  233.         $decryptedPW 'Encryption type not supported.';
  234.  
  235.         switch (strtoupper($this->passwordEncryptionMode)) {
  236.             case 'PLAIN':
  237.                 $decryptedPW $encryptedPW;
  238.                 break;
  239.             case 'MD5':
  240.                 // MD5 can't be decoded, so return the string unmodified
  241.                 $decryptedPW $encryptedPW;
  242.                 break;
  243.             case 'RC4':
  244.                 if (!is_object($this->rc4)) {
  245.                     @include_once 'Crypt/Rc4.php';
  246.                     if (!class_exists('Crypt_RC4')) {
  247.                         return LiveUser::raiseError(LIVEUSER_ERROR_NOT_SUPPORTEDnullnull,
  248.                             'Please install Crypt_RC4 to use this feature');
  249.                     }
  250.                     $this->rc4 =new Crypt_RC4('LiveUserMagicKey');
  251.                 }
  252.                 $decryptedPW $encryptedPW;
  253.                 $this->rc4->decrypt($decryptedPW);
  254.                 break;
  255.             case 'SHA1':
  256.                 // SHA1 can't be decoded, so return the string unmodified
  257.                 $decryptedPW $encryptedPW;
  258.                 break;
  259.         }
  260.  
  261.         return $decryptedPW;
  262.     }
  263.  
  264.     /**
  265.      * Encrypts a password for storage in a backend container.
  266.      * Uses the algorithm defined in the passwordEncryptionMode
  267.      * property.
  268.      *
  269.      * @param string  encryption type
  270.      * @return string The encrypted password
  271.      */
  272.     function encryptPW($plainPW)
  273.     {
  274.         $encryptedPW 'Encryption type not supported.';
  275.  
  276.         switch (strtoupper($this->passwordEncryptionMode)) {
  277.             case 'PLAIN':
  278.                 $encryptedPW $plainPW;
  279.                 break;
  280.             case 'MD5':
  281.                 $encryptedPW md5($plainPW);
  282.                 break;
  283.             case 'RC4':
  284.                 if (!is_object($this->rc4)) {
  285.                     @include_once 'Crypt/Rc4.php';
  286.                     if (!class_exists('Crypt_RC4')) {
  287.                         return LiveUser::raiseError(LIVEUSER_ERROR_NOT_SUPPORTEDnullnull,
  288.                             'Please install Crypt_RC4 to use this feature');
  289.                     }
  290.                     $this->rc4 =new Crypt_RC4('LiveUserMagicKey');
  291.                 }
  292.                 $encryptedPW $plainPW;
  293.                 $this->rc4->crypt($encryptedPW);
  294.                 break;
  295.             case 'SHA1':
  296.                 if (!function_exists('sha1')) {
  297.                     return LiveUser::raiseError(LIVEUSER_ERROR_NOT_SUPPORTEDnullnull,
  298.                         'SHA1 function doesn\'t exist. Upgrade your PHP version.');
  299.                 }
  300.                 $encryptedPW sha1($plainPW);
  301.                 break;
  302.         }
  303.  
  304.         return $encryptedPW;
  305.     }
  306.  
  307.     /**
  308.      * Checks if there's enough time between lastLogin
  309.      * and current login (now) to count as a new login.
  310.      *
  311.      * @return boolean 
  312.      */
  313.     function isNewLogin ()
  314.     {
  315.         $meantime $this->loginTimeout * 3600;
  316.         if (time(>= $this->lastLogin + $meantime{
  317.             return true;
  318.         else {
  319.             return false;
  320.         }
  321.     }
  322.  
  323.     /**
  324.      * Tries to make a login with the given handle and password.
  325.      * If $checkpw is set to false, the password won't be
  326.      * validated and the user will be logged in anyway. Set this
  327.      * option if you want to allow your users to be
  328.      * authenticated by a simple cookie... however, this is
  329.      * NOT RECOMMENDED !!!
  330.      * In any case, a user can't login if he's not active.
  331.      *
  332.      * @param string   user handle
  333.      * @param string   user password
  334.      * @param boolean  check password ? useful for some backends like LDAP
  335.      * @param boolean  update the last login data ?
  336.      */
  337.     function login($handle$passwd$checkpw = true$updateLastLogin = true)
  338.     {
  339.         // Init value: Has user data successfully been read?
  340.         $success        = false;
  341.         // Init value: Is user logged in?
  342.         $this->loggedIn = false;
  343.         // Read user data from database
  344.         if ($this->allowDuplicateHandles == true || $checkpw == true{
  345.             // If duplicate handles are allowed or the password _has_
  346.             // to be checked, only read in data if a matching user is found
  347.             $success $this->readUserData($handle$passwd);
  348.         else {
  349.             // If duplicate handles are not allowed or the password
  350.             // doesn't need to be checked, just read in the data based
  351.             // on the handle
  352.             $success $this->readUserData($handle);
  353.         }
  354.  
  355.         // If login is successful (user data has been read)
  356.         if ($success == true{
  357.             $pwCheck = false; // Init value
  358.  
  359.             // Just in case: Some databases will return whitespace when using
  360.             // CHAR fields to store passwords, so we?ll remove it.
  361.             $this->passwd = trim($this->passwd);
  362.  
  363.             // ...check again if we have to check the password...
  364.             if ($checkpw == true{
  365.                 // If yes, does the password from the database match the given one?
  366.                 if (strtoupper($this->passwordEncryptionMode== 'MD5'
  367.                         && $this->passwd == $this->encryptPW($passwd)){
  368.                     // If yes, set pwCheck Flag
  369.                     $pwCheck = true;
  370.                 else if ($this->passwd == $passwd{
  371.                     // If yes, set pwCheck Flag
  372.                     $pwCheck = true;
  373.                 }
  374.             else {
  375.                 // We don't have to check for the password, so set the pwCheck Flag
  376.                 // regardless of the user's input
  377.                 $pwCheck = true;
  378.             }
  379.  
  380.             // ...we still need to check if this user is declared active and
  381.             // if the pwCheck Flag is set to true...
  382.             if ($this->isActive != false && $pwCheck == true{
  383.                 // ...and if so, we have a successful login (hooray)!
  384.                 $this->loggedIn = true;
  385.                 $this->currentLogin = time();
  386.             }
  387.         }
  388.  
  389.         // In case Login was successful, check if this can be counted
  390.         // as a _new_ login by definition...
  391.         if ($updateLastLogin == true && $this->isNewLogin(== true && $this->loggedIn == true{
  392.             $this->updateUserData();
  393.         }
  394.     }
  395.  
  396.     /**
  397.      * Writes current values for user back to the database.
  398.      * This method does nothing in the base class and is supposed to
  399.      * be overridden in subclasses according to the supported backend.
  400.      *
  401.      * @access public
  402.      * @return object  PEAR_Error 
  403.      */
  404.     function updateUserData()
  405.     {
  406.         return LiveUser::raiseError(LIVEUSER_ERROR_NOT_SUPPORTEDnullnull,
  407.             'Method not supported by this container');
  408.     }
  409.  
  410.     /**
  411.      * Reads auth_user_id, passwd, is_active flag
  412.      * lastlogin timestamp from the database
  413.      * If only $handle is given, it will read the data
  414.      * from the first user with that handle and return
  415.      * true on success.
  416.      * If $handle and $passwd are given, it will try to
  417.      * find the first user with both handle and password
  418.      * matching and return true on success (this allows
  419.      * multiple users having the same handle but different
  420.      * passwords - yep, some people want this).
  421.      * If no match is found, false is being returned.
  422.      *
  423.      * Again, this does nothing in the base class. The
  424.      * described functionality must be implemented in a
  425.      * subclass overriding this method.
  426.      *
  427.      * @param  string  user handle
  428.      * @param  boolean user password
  429.      * @return boolean true on success, false on failure
  430.      */
  431.     function readUserData($handle$passwd = false)
  432.     {
  433.         return LiveUser::raiseError(LIVEUSER_ERROR_NOT_SUPPORTEDnullnull,
  434.             'Method not supported by this container');
  435.     }
  436.  
  437.     /**
  438.      * Helper function that checks if there is a user in
  439.      * the database who's matching the given parameters.
  440.      * If $checkHandle is given and $checkPW is set to
  441.      * false, it only checks if a user with that handle
  442.      * exists. If only $checkPW is given and $checkHandle
  443.      * is set to false, it will check if there exists a
  444.      * user with that password. If both values are set to
  445.      * anything but false, it will find the first user in
  446.      * the database with both values matching.
  447.      * Please note:
  448.      * - If no match was found, the return value is false
  449.      * - If a match was found, the auth_user_id from the database
  450.      *   is being returned
  451.      * Whatever is returned, please keep in mind that this
  452.      * function only searches for the _first_ occurence
  453.      * of the search values in the database. So when you
  454.      * have multiple users with the same handle, only the
  455.      * ID of the first one is returned. Same goes for
  456.      * passwords. Searching for both password and handle
  457.      * should be pretty safe, though - having more than
  458.      * one user with the same handle/password combination
  459.      * in the database would be pretty stupid anyway.
  460.      *
  461.      * Again, this does nothing in the base class. The
  462.      * described functionality must be implemented in a
  463.      * subclass overriding this method.
  464.      *
  465.      * @param boolean check handle ?
  466.      * @param boolean check password ?
  467.      * @return mixed  user id when there is a match, false otherwise
  468.      */
  469.     function userExists($checkHandle = false$checkPW = false)
  470.     {
  471.         return LiveUser::raiseError(LIVEUSER_ERROR_NOT_SUPPORTEDnullnull,
  472.             'Method not supported by this container');
  473.     }
  474.  
  475.     /**
  476.      * Function returns the inquired value if it exists in the class.
  477.      *
  478.      * @param  string   Name of the property to be returned.
  479.      * @return mixed    null, a value or an array.
  480.      */
  481.     function getProperty($what)
  482.     {
  483.         $that = null;
  484.         if (isset($this->$what)) {
  485.             $that $this->$what;
  486.         }
  487.         return $that;
  488.     }
  489. }
  490. ?>

Documentation generated on Mon, 11 Mar 2019 10:16:10 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.