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

Source for file MDB2.php

Documentation is available at MDB2.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: MDB2.php,v 1.8 2006/02/28 02:19:22 aashley Exp $
  20. //
  21.  
  22. require_once 'Auth/Container.php';
  23. require_once 'MDB2.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 MDB2 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.8 $
  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_MDB2() [constructor]
  62.  
  63.     /**
  64.      * Constructor of the container class
  65.      *
  66.      * Initate connection to the database via PEAR::MDB2
  67.      *
  68.      * @param  string Connection data or MDB2 object
  69.      * @return object Returns an error object if something went wrong
  70.      */
  71.     function Auth_Container_MDB2($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 =MDB2::connect($dsn$this->options['db_options']);
  99.         elseif (is_subclass_of($dsn'MDB2_Driver_Common')) {
  100.             $this->db = $dsn;
  101.         elseif (is_object($dsn&& MDB2::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 (MDB2::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'MDB2_Driver_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->exec($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.         $query sprintf("SELECT %s FROM %s WHERE %s = %s",
  243.                          $sql_from,
  244.                          $this->options['table'],
  245.                          $this->options['usernamecol'],
  246.                          $this->db->quote($username'text')
  247.                          );
  248.  
  249.         $res $this->db->queryRow($querynullMDB2_FETCHMODE_ASSOC);
  250.         if (MDB2::isError($res|| PEAR::isError($res)) {
  251.             return PEAR::raiseError($res->getMessage()$res->getCode());
  252.         }
  253.         if (!is_array($res)) {
  254.             $this->activeUser = '';
  255.             return false;
  256.         }
  257.  
  258.         // Perform trimming here before the hashing
  259.         $password trim($password"\r\n");
  260.         $res[$this->options['passwordcol']] trim($res[$this->options['passwordcol']]"\r\n");
  261.         // If using Challenge Response md5 the pass with the secret
  262.         if ($isChallengeResponse{
  263.             $res[$this->options['passwordcol']] =
  264.                 md5($res[$this->options['passwordcol']].$this->_auth_obj->session['loginchallenege']);
  265.             // UGLY cannot avoid without modifying verifyPassword
  266.             if ($this->options['cryptType'== 'md5'{
  267.                 $res[$this->options['passwordcol']] md5($res[$this->options['passwordcol']]);
  268.             }
  269.         }
  270.         if ($this->verifyPassword($password,
  271.                                   $res[$this->options['passwordcol']],
  272.                                   $this->options['cryptType'])) {
  273.             // Store additional field values in the session
  274.             foreach ($res as $key => $value{
  275.                 if ($key == $this->options['passwordcol'||
  276.                     $key == $this->options['usernamecol']{
  277.                     continue;
  278.                 }
  279.                 // Use reference to the auth object if exists
  280.                 // This is because the auth session variable can change so a static call to setAuthData does not make sense
  281.                 $this->_auth_obj->setAuthData($key$value);
  282.             }
  283.             return true;
  284.         }
  285.  
  286.         $this->activeUser = $res[$this->options['usernamecol']];
  287.         return false;
  288.     }
  289.  
  290.     // }}}
  291.     // {{{ listUsers()
  292.  
  293.     /**
  294.      * Returns a list of users from the container
  295.      *
  296.      * @return mixed array|PEAR_Error
  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.         //Check if db_fields contains a *, if so assume all columns are selected
  309.         if (strstr($this->options['db_fields']'*')) {
  310.             $sql_from '*';
  311.         else {
  312.             $sql_from $this->options['db_fields'];
  313.         }
  314.  
  315.         $query sprintf('SELECT %s FROM %s',
  316.                          $sql_from,
  317.                          $this->options['table']
  318.                          );
  319.  
  320.         $res $this->db->queryAll($querynullMDB2_FETCHMODE_ASSOC);
  321.         if (MDB2::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.     // {{{ addUser()
  334.  
  335.     /**
  336.      * Add user to the storage container
  337.      *
  338.      * @access public
  339.      * @param  string Username
  340.      * @param  string Password
  341.      * @param  mixed  Additional information that are stored in the DB
  342.      *
  343.      * @return mixed True on success, otherwise error object
  344.      */
  345.     function addUser($username$password$additional "")
  346.     {
  347.  
  348.         // Prepare for a database query
  349.         $err $this->_prepare();
  350.         if ($err !== true{
  351.             return PEAR::raiseError($err->getMessage()$err->getCode());
  352.         }
  353.  
  354.         if (isset($this->options['cryptType']&& $this->options['cryptType'== 'none'{
  355.             $cryptFunction 'strval';
  356.         elseif (isset($this->options['cryptType']&& function_exists($this->options['cryptType'])) {
  357.             $cryptFunction $this->options['cryptType'];
  358.         else {
  359.             $cryptFunction 'md5';
  360.         }
  361.  
  362.         $password $cryptFunction($password);
  363.  
  364.         $additional_key   '';
  365.         $additional_value '';
  366.  
  367.         if (is_array($additional)) {
  368.             foreach ($additional as $key => $value{
  369.                 $additional_key   .= ', ' $key;
  370.                 $additional_value .= ', ' $this->db->quote($value'text');
  371.             }
  372.         }
  373.  
  374.         $query sprintf("INSERT INTO %s (%s, %s%s) VALUES (%s, %s%s)",
  375.                          $this->options['table'],
  376.                          $this->options['usernamecol'],
  377.                          $this->options['passwordcol'],
  378.                          $additional_key,
  379.                          $this->db->quote($username'text'),
  380.                          $this->db->quote($password'text'),
  381.                          $additional_value
  382.                          );
  383.  
  384.         $res $this->query($query);
  385.  
  386.         if (MDB2::isError($res)) {
  387.             return PEAR::raiseError($res->getMessage()$res->code);
  388.         }
  389.         return true;
  390.     }
  391.  
  392.     // }}}
  393.     // {{{ removeUser()
  394.  
  395.     /**
  396.      * Remove user from the storage container
  397.      *
  398.      * @access public
  399.      * @param  string Username
  400.      *
  401.      * @return mixed True on success, otherwise error object
  402.      */
  403.     function removeUser($username)
  404.     {
  405.         // Prepare for a database query
  406.         $err $this->_prepare();
  407.         if ($err !== true{
  408.             return PEAR::raiseError($err->getMessage()$err->getCode());
  409.         }
  410.  
  411.         $query sprintf("DELETE FROM %s WHERE %s = %s",
  412.                          $this->options['table'],
  413.                          $this->options['usernamecol'],
  414.                          $this->db->quote($username'text')
  415.                          );
  416.  
  417.         $res $this->query($query);
  418.  
  419.         if (MDB2::isError($res)) {
  420.             return PEAR::raiseError($res->getMessage()$res->code);
  421.         }
  422.         return true;
  423.     }
  424.  
  425.     // }}}
  426.     // {{{ changePassword()
  427.  
  428.     /**
  429.      * Change password for user in the storage container
  430.      *
  431.      * @param string Username
  432.      * @param string The new password (plain text)
  433.      */
  434.     function changePassword($username$password)
  435.     {
  436.         // Prepare for a database query
  437.         $err $this->_prepare();
  438.         if ($err !== true{
  439.             return PEAR::raiseError($err->getMessage()$err->getCode());
  440.         }
  441.  
  442.         if (isset($this->options['cryptType']&& $this->options['cryptType'== 'none'{
  443.             $cryptFunction 'strval';
  444.         elseif (isset($this->options['cryptType']&& function_exists($this->options['cryptType'])) {
  445.             $cryptFunction $this->options['cryptType'];
  446.         else {
  447.             $cryptFunction 'md5';
  448.         }
  449.  
  450.         $password $cryptFunction($password);
  451.  
  452.         $query sprintf("UPDATE %s SET %s = %s WHERE %s = %s",
  453.                          $this->options['table'],
  454.                          $this->options['passwordcol'],
  455.                          $this->db->quote($password'text'),
  456.                          $this->options['usernamecol'],
  457.                          $this->db->quote($username'text')
  458.                          );
  459.  
  460.         $res $this->query($query);
  461.  
  462.         if (MDB2::isError($res)) {
  463.             return PEAR::raiseError($res->getMessage()$res->code);
  464.         }
  465.         return true;
  466.     }
  467.  
  468.     // }}}
  469.     // {{{ supportsChallengeResponse()
  470.  
  471.     /**
  472.      * Determine if this container supports
  473.      * password authentication with challenge response
  474.      *
  475.      * @return bool 
  476.      * @access public
  477.      */
  478.     function supportsChallengeResponse()
  479.     {
  480.         return in_array($this->options['cryptType']array('md5''none'''));
  481.     }
  482.  
  483.     // }}}
  484.     // {{{ getCryptType()
  485.  
  486.     /**
  487.      * Returns the selected crypt type for this container
  488.      *
  489.      * @return string Function used to crypt the password
  490.      */
  491.     function getCryptType()
  492.     {
  493.         return $this->options['cryptType'];
  494.     }
  495.  
  496.     // }}}
  497.  
  498. }
  499. ?>

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