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

Source for file DB.php

Documentation is available at DB.php

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

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