3 V5.18 3 Sep 2012 (c) 2000-2012 John Lim (jlim#natsoft.com). All rights reserved.
4 Released under both BSD license and Lesser GPL library license.
5 Whenever there is any discrepancy between the two licenses,
6 the BSD license will take precedence. See License.txt.
7 Set tabs to 4 for best viewing.
9 Latest version is available at http://adodb.sourceforge.net
11 Original Authors: Martin Jansen <mj#php.net>
12 Richard Tango-Lowy <richtl#arscognita.com>
15 require_once 'Auth/Container.php';
16 require_once 'adodb.inc.php';
17 require_once 'adodb-pear.inc.php';
18 require_once 'adodb-errorpear.inc.php';
21 * Storage driver for fetching login data from a database using ADOdb-PHP.
23 * This storage driver can use all databases which are supported
24 * by the ADBdb DB abstraction layer to fetch login data.
25 * See http://php.weblogs.com/adodb for information on ADOdb.
26 * NOTE: The ADOdb directory MUST be in your PHP include_path!
28 * @author Richard Tango-Lowy <richtl@arscognita.com>
30 * @version $Revision: 1.3 $
32 class Auth_Container_ADOdb extends Auth_Container
36 * Additional options for the storage container
39 var $options = array();
49 * User that is currently selected from the DB.
57 * Constructor of the container class
59 * Initate connection to the database via PEAR::ADOdb
61 * @param string Connection data or DB object
62 * @return object Returns an error object if something went wrong
64 function Auth_Container_ADOdb($dsn)
66 $this->_setDefaults();
69 $this->_parseOptions($dsn);
71 if (empty($this->options['dsn'])) {
72 PEAR::raiseError('No connection parameters specified!');
75 // Extract db_type from dsn string.
76 $this->options['dsn'] = $dsn;
84 * Connect to database by using the given DSN string
87 * @param string DSN string
88 * @return mixed Object on error, otherwise bool
90 function _connect($dsn)
92 if (is_string($dsn) || is_array($dsn)) {
94 $this->db = ADONewConnection($dsn);
95 if( $err = ADODB_Pear_error() ) {
96 return PEAR::raiseError($err);
101 return PEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__,
110 return PEAR::raiseError(ADODB_Pear_error());
120 * Prepare database connection
122 * This function checks if we have already opened a connection to
123 * the database. If that's not the case, a new connection is opened.
126 * @return mixed True or a DB error object.
131 $res = $this->_connect($this->options['dsn']);
140 * Prepare query to the database
142 * This function checks if we have already opened a connection to
143 * the database. If that's not the case, a new connection is opened.
144 * After that the query is passed to the database.
147 * @param string Query string
148 * @return mixed a DB_result object or DB_OK on success, a DB
149 * or PEAR error on failure
151 function query($query)
153 $err = $this->_prepare();
157 return $this->db->query($query);
161 // {{{ _setDefaults()
164 * Set some default options
169 function _setDefaults()
171 $this->options['db_type'] = 'mysql';
172 $this->options['table'] = 'auth';
173 $this->options['usernamecol'] = 'username';
174 $this->options['passwordcol'] = 'password';
175 $this->options['dsn'] = '';
176 $this->options['db_fields'] = '';
177 $this->options['cryptType'] = 'md5';
181 // {{{ _parseOptions()
184 * Parse options passed to the container class
189 function _parseOptions($array)
191 foreach ($array as $key => $value) {
192 if (isset($this->options[$key])) {
193 $this->options[$key] = $value;
197 /* Include additional fields if they exist */
198 if(!empty($this->options['db_fields'])){
199 if(is_array($this->options['db_fields'])){
200 $this->options['db_fields'] = join($this->options['db_fields'], ', ');
202 $this->options['db_fields'] = ', '.$this->options['db_fields'];
210 * Get user information from database
212 * This function uses the given username to fetch
213 * the corresponding login data from the database
214 * table. If an account that matches the passed username
215 * and password is found, the function returns true.
216 * Otherwise it returns false.
218 * @param string Username
219 * @param string Password
220 * @return mixed Error object or boolean
222 function fetchData($username, $password)
224 // Prepare for a database query
225 $err = $this->_prepare();
227 return PEAR::raiseError($err->getMessage(), $err->getCode());
230 // Find if db_fields contains a *, i so assume all col are selected
231 if(strstr($this->options['db_fields'], '*')){
235 $sql_from = $this->options['usernamecol'] . ", ".$this->options['passwordcol'].$this->options['db_fields'];
238 $query = "SELECT ".$sql_from.
239 " FROM ".$this->options['table'].
240 " WHERE ".$this->options['usernamecol']." = " . $this->db->Quote($username);
242 $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
243 $rset = $this->db->Execute( $query );
244 $res = $rset->fetchRow();
246 if (DB::isError($res)) {
247 return PEAR::raiseError($res->getMessage(), $res->getCode());
249 if (!is_array($res)) {
250 $this->activeUser = '';
253 if ($this->verifyPassword(trim($password, "\r\n"),
254 trim($res[$this->options['passwordcol']], "\r\n"),
255 $this->options['cryptType'])) {
256 // Store additional field values in the session
257 foreach ($res as $key => $value) {
258 if ($key == $this->options['passwordcol'] ||
259 $key == $this->options['usernamecol']) {
262 // Use reference to the auth object if exists
263 // This is because the auth session variable can change so a static call to setAuthData does not make sence
264 if(is_object($this->_auth_obj)){
265 $this->_auth_obj->setAuthData($key, $value);
267 Auth::setAuthData($key, $value);
274 $this->activeUser = $res[$this->options['usernamecol']];
283 $err = $this->_prepare();
285 return PEAR::raiseError($err->getMessage(), $err->getCode());
290 // Find if db_fileds contains a *, i so assume all col are selected
291 if(strstr($this->options['db_fields'], '*')){
295 $sql_from = $this->options['usernamecol'] . ", ".$this->options['passwordcol'].$this->options['db_fields'];
298 $query = sprintf("SELECT %s FROM %s",
300 $this->options['table']
302 $res = $this->db->getAll($query, null, DB_FETCHMODE_ASSOC);
304 if (DB::isError($res)) {
305 return PEAR::raiseError($res->getMessage(), $res->getCode());
307 foreach ($res as $user) {
308 $user['username'] = $user[$this->options['usernamecol']];
319 * Add user to the storage container
322 * @param string Username
323 * @param string Password
324 * @param mixed Additional information that are stored in the DB
326 * @return mixed True on success, otherwise error object
328 function addUser($username, $password, $additional = "")
330 if (function_exists($this->options['cryptType'])) {
331 $cryptFunction = $this->options['cryptType'];
333 $cryptFunction = 'md5';
336 $additional_key = '';
337 $additional_value = '';
339 if (is_array($additional)) {
340 foreach ($additional as $key => $value) {
341 $additional_key .= ', ' . $key;
342 $additional_value .= ", '" . $value . "'";
346 $query = sprintf("INSERT INTO %s (%s, %s%s) VALUES ('%s', '%s'%s)",
347 $this->options['table'],
348 $this->options['usernamecol'],
349 $this->options['passwordcol'],
352 $cryptFunction($password),
356 $res = $this->query($query);
358 if (DB::isError($res)) {
359 return PEAR::raiseError($res->getMessage(), $res->getCode());
369 * Remove user from the storage container
372 * @param string Username
374 * @return mixed True on success, otherwise error object
376 function removeUser($username)
378 $query = sprintf("DELETE FROM %s WHERE %s = '%s'",
379 $this->options['table'],
380 $this->options['usernamecol'],
384 $res = $this->query($query);
386 if (DB::isError($res)) {
387 return PEAR::raiseError($res->getMessage(), $res->getCode());
396 function showDbg( $string ) {
400 function dump( $var, $str, $vardump = false ) {
401 print "<H4>$str</H4><pre>";
402 ( !$vardump ) ? ( print_r( $var )) : ( var_dump( $var ));