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

Source for file MDB.php

Documentation is available at MDB.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // |                                                                      |
  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. // | Author: Lorenzo Alberton <l.alberton@quipo.it>                       |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: MDB.php,v 1.22 2006/02/28 02:19:22 aashley Exp $
  20. //
  21.  
  22. require_once 'Auth/Container.php';
  23. require_once 'MDB.php';
  24.  
  25. /**
  26.  * Storage driver for fetching login data from a database
  27.  *
  28.  * This storage driver can use all databases which are supported
  29.  * by the PEAR MDB abstraction layer to fetch login data.
  30.  *
  31.  * @author   Lorenzo Alberton <l.alberton@quipo.it>
  32.  * @author   Adam Ashley <aashley@php.net>
  33.  * @package  Auth
  34.  * @version  $Revision: 1.22 $
  35.  */
  36. {
  37.  
  38.     // {{{ properties
  39.  
  40.     /**
  41.      * Additional options for the storage container
  42.      * @var array 
  43.      */
  44.     var $options = array();
  45.  
  46.     /**
  47.      * MDB object
  48.      * @var object 
  49.      */
  50.     var $db = null;
  51.     var $dsn = '';
  52.  
  53.     /**
  54.      * User that is currently selected from the DB.
  55.      * @var string 
  56.      */
  57.     var $activeUser = '';
  58.  
  59.     // }}}
  60.  
  61.     // {{{ Auth_Container_MDB() [constructor]
  62.  
  63.     /**
  64.      * Constructor of the container class
  65.      *
  66.      * Initate connection to the database via PEAR::MDB
  67.      *
  68.      * @param  string Connection data or MDB object
  69.      * @return object Returns an error object if something went wrong
  70.      */
  71.     function Auth_Container_MDB($dsn)
  72.     {
  73.         $this->_setDefaults();
  74.  
  75.         if (is_array($dsn)) {
  76.             $this->_parseOptions($dsn);
  77.             if (empty($this->options['dsn'])) {
  78.                 PEAR::raiseError('No connection parameters specified!');
  79.             }
  80.         else {
  81.             $this->options['dsn'$dsn;
  82.         }
  83.     }
  84.  
  85.     // }}}
  86.     // {{{ _connect()
  87.  
  88.     /**
  89.      * Connect to database by using the given DSN string
  90.      *
  91.      * @access private
  92.      * @param  mixed DSN string | array | mdb object
  93.      * @return mixed  Object on error, otherwise bool
  94.      */
  95.     function _connect($dsn)
  96.     {
  97.         if (is_string($dsn|| is_array($dsn)) {
  98.             $this->db =MDB::connect($dsn$this->options['db_options']);
  99.         elseif (is_subclass_of($dsn'mdb_common')) {
  100.             $this->db = $dsn;
  101.         elseif (is_object($dsn&& MDB::isError($dsn)) {
  102.             return PEAR::raiseError($dsn->getMessage()$dsn->code);
  103.         else {
  104.             return PEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__,
  105.                                     41,
  106.                                     PEAR_ERROR_RETURN,
  107.                                     null,
  108.                                     null
  109.                                     );
  110.  
  111.         }
  112.  
  113.         if (MDB::isError($this->db|| PEAR::isError($this->db)) {
  114.             return PEAR::raiseError($this->db->getMessage()$this->db->code);
  115.         }
  116.         return true;
  117.     }
  118.  
  119.     // }}}
  120.     // {{{ _prepare()
  121.  
  122.     /**
  123.      * Prepare database connection
  124.      *
  125.      * This function checks if we have already opened a connection to
  126.      * the database. If that's not the case, a new connection is opened.
  127.      *
  128.      * @access private
  129.      * @return mixed True or a MDB error object.
  130.      */
  131.     function _prepare()
  132.     {
  133.         if (is_subclass_of($this->db'mdb_common')) {
  134.             return true;
  135.         }
  136.         return $this->_connect($this->options['dsn']);
  137.     }
  138.  
  139.     // }}}
  140.     // {{{ query()
  141.  
  142.     /**
  143.      * Prepare query to the database
  144.      *
  145.      * This function checks if we have already opened a connection to
  146.      * the database. If that's not the case, a new connection is opened.
  147.      * After that the query is passed to the database.
  148.      *
  149.      * @access public
  150.      * @param  string Query string
  151.      * @return mixed  a MDB_result object or MDB_OK on success, a MDB
  152.      *                 or PEAR error on failure
  153.      */
  154.     function query($query)
  155.     {
  156.         $err $this->_prepare();
  157.         if ($err !== true{
  158.             return $err;
  159.         }
  160.         return $this->db->query($query);
  161.     }
  162.  
  163.     // }}}
  164.     // {{{ _setDefaults()
  165.  
  166.     /**
  167.      * Set some default options
  168.      *
  169.      * @access private
  170.      * @return void 
  171.      */
  172.     function _setDefaults()
  173.     {
  174.         $this->options['table']       'auth';
  175.         $this->options['usernamecol''username';
  176.         $this->options['passwordcol''password';
  177.         $this->options['dsn']         '';
  178.         $this->options['db_fields']   '';
  179.         $this->options['cryptType']   'md5';
  180.         $this->options['db_options']  = array();
  181.     }
  182.  
  183.     // }}}
  184.     // {{{ _parseOptions()
  185.  
  186.     /**
  187.      * Parse options passed to the container class
  188.      *
  189.      * @access private
  190.      * @param  array 
  191.      */
  192.     function _parseOptions($array)
  193.     {
  194.         foreach ($array as $key => $value{
  195.             if (isset($this->options[$key])) {
  196.                 $this->options[$key$value;
  197.             }
  198.         }
  199.  
  200.         // Include additional fields if they exist
  201.         if (!empty($this->options['db_fields'])) {
  202.             if (is_array($this->options['db_fields'])) {
  203.                 $this->options['db_fields'join($this->options['db_fields']', ');
  204.             }
  205.             $this->options['db_fields'', ' $this->options['db_fields'];
  206.         }
  207.     }
  208.  
  209.     // }}}
  210.     // {{{ fetchData()
  211.  
  212.     /**
  213.      * Get user information from database
  214.      *
  215.      * This function uses the given username to fetch
  216.      * the corresponding login data from the database
  217.      * table. If an account that matches the passed username
  218.      * and password is found, the function returns true.
  219.      * Otherwise it returns false.
  220.      *
  221.      * @param   string Username
  222.      * @param   string Password
  223.      * @param   boolean If true password is secured using a md5 hash
  224.      *                   the frontend and auth are responsible for making sure the container supports
  225.      *                   challenge response password authentication
  226.      * @return  mixed  Error object or boolean
  227.      */
  228.     function fetchData($username$password$isChallengeResponse=false)
  229.     {
  230.         // Prepare for a database query
  231.         $err $this->_prepare();
  232.         if ($err !== true{
  233.             return PEAR::raiseError($err->getMessage()$err->getCode());
  234.         }
  235.  
  236.         //Check if db_fields contains a *, if so assume all columns are selected
  237.         if (strstr($this->options['db_fields']'*')) {
  238.             $sql_from '*';
  239.         else {
  240.             $sql_from $this->options['usernamecol'', '$this->options['passwordcol'$this->options['db_fields'];
  241.         }
  242.  
  243.         $query sprintf("SELECT %s FROM %s WHERE %s = %s",
  244.                          $sql_from,
  245.                          $this->options['table'],
  246.                          $this->options['usernamecol'],
  247.                          $this->db->getTextValue($username)
  248.                          );
  249.  
  250.         $res $this->db->getRow($querynullnullnullMDB_FETCHMODE_ASSOC);
  251.  
  252.         if (MDB::isError($res|| PEAR::isError($res)) {
  253.             return PEAR::raiseError($res->getMessage()$res->getCode());
  254.         }
  255.         if (!is_array($res)) {
  256.             $this->activeUser = '';
  257.             return false;
  258.         }
  259.  
  260.         // Perform trimming here before the hashing
  261.         $password trim($password"\r\n");
  262.         $res[$this->options['passwordcol']] trim($res[$this->options['passwordcol']]"\r\n");
  263.         
  264.         // If using Challenge Response md5 the pass with the secret
  265.         if ($isChallengeResponse{
  266.             $res[$this->options['passwordcol']] =
  267.                 md5($res[$this->options['passwordcol']].$this->_auth_obj->session['loginchallenege']);
  268.             // UGLY cannot avoid without modifying verifyPassword
  269.             if ($this->options['cryptType'== 'md5'{
  270.                 $res[$this->options['passwordcol']] md5($res[$this->options['passwordcol']]);
  271.             }
  272.         }
  273.         
  274.         if ($this->verifyPassword($password,
  275.                                   $res[$this->options['passwordcol']],
  276.                                   $this->options['cryptType'])) {
  277.             // Store additional field values in the session
  278.             foreach ($res as $key => $value{
  279.                 if ($key == $this->options['passwordcol'||
  280.                     $key == $this->options['usernamecol']{
  281.                     continue;
  282.                 }
  283.                 // Use reference to the auth object if exists
  284.                 // This is because the auth session variable can change so a static
  285.                 // call to setAuthData does not make sense
  286.                 $this->_auth_obj->setAuthData($key$value);
  287.             }
  288.             return true;
  289.         }
  290.  
  291.         $this->activeUser = $res[$this->options['usernamecol']];
  292.         return false;
  293.     }
  294.  
  295.     // }}}
  296.     // {{{ listUsers()
  297.  
  298.     /**
  299.      * Returns a list of users from the container
  300.      *
  301.      * @return mixed array|PEAR_Error
  302.      * @access public
  303.      */
  304.     function listUsers()
  305.     {
  306.         $err $this->_prepare();
  307.         if ($err !== true{
  308.             return PEAR::raiseError($err->getMessage()$err->getCode());
  309.         }
  310.  
  311.         $retVal = array();
  312.  
  313.         //Check if db_fields contains a *, if so assume all columns are selected
  314.         if (strstr($this->options['db_fields']'*')) {
  315.             $sql_from '*';
  316.         else {
  317.             $sql_from $this->options['db_fields'];
  318.         }
  319.  
  320.         $query sprintf('SELECT %s FROM %s',
  321.                          $sql_from,
  322.                          $this->options['table']
  323.                          );
  324.  
  325.         $res $this->db->getAll($querynullnullnullMDB_FETCHMODE_ASSOC);
  326.  
  327.         if (MDB::isError($res)) {
  328.             return PEAR::raiseError($res->getMessage()$res->getCode());
  329.         else {
  330.             foreach ($res as $user{
  331.                 $user['username'$user[$this->options['usernamecol']];
  332.                 $retVal[$user;
  333.             }
  334.         }
  335.         return $retVal;
  336.     }
  337.  
  338.     // }}}
  339.     // {{{ addUser()
  340.  
  341.     /**
  342.      * Add user to the storage container
  343.      *
  344.      * @access public
  345.      * @param  string Username
  346.      * @param  string Password
  347.      * @param  mixed  Additional information that are stored in the DB
  348.      *
  349.      * @return mixed True on success, otherwise error object
  350.      */
  351.     function addUser($username$password$additional "")
  352.     {
  353.         $err $this->_prepare();
  354.         if ($err !== true{
  355.             return PEAR::raiseError($err->getMessage()$err->getCode());
  356.         }
  357.  
  358.         if (isset($this->options['cryptType']&& $this->options['cryptType'== 'none'{
  359.             $cryptFunction 'strval';
  360.         elseif (isset($this->options['cryptType']&& function_exists($this->options['cryptType'])) {
  361.             $cryptFunction $this->options['cryptType'];
  362.         else {
  363.             $cryptFunction 'md5';
  364.         }
  365.  
  366.         $password $cryptFunction($password);
  367.  
  368.         $additional_key   '';
  369.         $additional_value '';
  370.  
  371.         if (is_array($additional)) {
  372.             foreach ($additional as $key => $value{
  373.                 $additional_key   .= ', ' $key;
  374.                 $additional_value .= ', ' $this->db->getTextValue($value);
  375.             }
  376.         }
  377.  
  378.         $query sprintf("INSERT INTO %s (%s, %s%s) VALUES (%s, %s%s)",
  379.                          $this->options['table'],
  380.                          $this->options['usernamecol'],
  381.                          $this->options['passwordcol'],
  382.                          $additional_key,
  383.                          $this->db->getTextValue($username),
  384.                          $this->db->getTextValue($password),
  385.                          $additional_value
  386.                          );
  387.  
  388.         $res $this->query($query);
  389.  
  390.         if (MDB::isError($res)) {
  391.             return PEAR::raiseError($res->getMessage()$res->code);
  392.         }
  393.         return true;
  394.     }
  395.  
  396.     // }}}
  397.     // {{{ removeUser()
  398.  
  399.     /**
  400.      * Remove user from the storage container
  401.      *
  402.      * @access public
  403.      * @param  string Username
  404.      *
  405.      * @return mixed True on success, otherwise error object
  406.      */
  407.     function removeUser($username)
  408.     {
  409.         $err $this->_prepare();
  410.         if ($err !== true{
  411.             return PEAR::raiseError($err->getMessage()$err->getCode());
  412.         }
  413.  
  414.         $query sprintf("DELETE FROM %s WHERE %s = %s",
  415.                          $this->options['table'],
  416.                          $this->options['usernamecol'],
  417.                          $this->db->getTextValue($username)
  418.                          );
  419.  
  420.         $res $this->query($query);
  421.  
  422.         if (MDB::isError($res)) {
  423.             return PEAR::raiseError($res->getMessage()$res->code);
  424.         }
  425.         return true;
  426.     }
  427.  
  428.     // }}}
  429.     // {{{ changePassword()
  430.  
  431.     /**
  432.      * Change password for user in the storage container
  433.      *
  434.      * @param string Username
  435.      * @param string The new password (plain text)
  436.      */
  437.     function changePassword($username$password)
  438.     {
  439.         $err $this->_prepare();
  440.         if ($err !== true{
  441.             return PEAR::raiseError($err->getMessage()$err->getCode());
  442.         }
  443.  
  444.         if (isset($this->options['cryptType']&& $this->options['cryptType'== 'none'{
  445.             $cryptFunction 'strval';
  446.         elseif (isset($this->options['cryptType']&& function_exists($this->options['cryptType'])) {
  447.             $cryptFunction $this->options['cryptType'];
  448.         else {
  449.             $cryptFunction 'md5';
  450.         }
  451.  
  452.         $password $cryptFunction($password);
  453.  
  454.         $query sprintf("UPDATE %s SET %s = %s WHERE %s = %s",
  455.                          $this->options['table'],
  456.                          $this->options['passwordcol'],
  457.                          $this->db->getTextValue($password),
  458.                          $this->options['usernamecol'],
  459.                          $this->db->getTextValue($username)
  460.                          );
  461.  
  462.         $res $this->query($query);
  463.  
  464.         if (MDB::isError($res)) {
  465.             return PEAR::raiseError($res->getMessage()$res->code);
  466.         }
  467.         return true;
  468.     }
  469.  
  470.     // }}}
  471.     // {{{ supportsChallengeResponse()
  472.  
  473.     /**
  474.      * Determine if this container supports
  475.      * password authentication with challenge response
  476.      *
  477.      * @return bool 
  478.      * @access public
  479.      */
  480.     function supportsChallengeResponse()
  481.     {
  482.         return in_array($this->options['cryptType']array('md5''none'''));
  483.     }
  484.  
  485.     // }}}
  486.     // {{{ getCryptType()
  487.  
  488.     /**
  489.      * Returns the selected crypt type for this container
  490.      *
  491.      * @return string Function used to crypt the password
  492.      */
  493.     function getCryptType()
  494.     {
  495.         return $this->options['cryptType'];
  496.     }
  497.  
  498.     // }}}
  499.  
  500. }
  501. ?>

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