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

Source for file DB.php

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

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