ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
DB.php
Go to the documentation of this file.
1<?php
2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
3
28require_once 'Auth/Container.php';
32require_once 'DB.php';
33
50{
51
52 // {{{ properties
53
58 var $options = array();
59
64 var $db = null;
65 var $dsn = '';
66
71 var $activeUser = '';
72
73 // }}}
74 // {{{ Auth_Container_DB [constructor]
75
86 {
87 $this->_setDefaults();
88
89 if (is_array($dsn)) {
90 $this->_parseOptions($dsn);
91
92 if (empty($this->options['dsn'])) {
93 PEAR::raiseError('No connection parameters specified!');
94 }
95 } else {
96 $this->options['dsn'] = $dsn;
97 }
98 }
99
100 // }}}
101 // {{{ _connect()
102
110 function _connect($dsn)
111 {
112 $this->log('Auth_Container_DB::_connect() called.', AUTH_LOG_DEBUG);
113
114 if (is_string($dsn) || is_array($dsn)) {
115 $this->db = DB::Connect($dsn, $this->options['db_options']);
116 } elseif (is_subclass_of($dsn, 'db_common')) {
117 $this->db = $dsn;
118 } elseif (DB::isError($dsn)) {
119 return PEAR::raiseError($dsn->getMessage(), $dsn->getCode());
120 } else {
121 return PEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__,
122 41,
124 null,
125 null
126 );
127 }
128
129 if (DB::isError($this->db) || PEAR::isError($this->db)) {
130 return PEAR::raiseError($this->db->getMessage(), $this->db->getCode());
131 } else {
132 return true;
133 }
134 }
135
136 // }}}
137 // {{{ _prepare()
138
148 function _prepare()
149 {
150 if (!DB::isConnection($this->db)) {
151 $res = $this->_connect($this->options['dsn']);
152 if (DB::isError($res) || PEAR::isError($res)) {
153 return $res;
154 }
155 }
156 if ($this->options['auto_quote'] && $this->db->dsn['phptype'] != 'sqlite') {
157 if (strpos('.', $this->options['table']) === false) {
158 $this->options['final_table'] = $this->db->quoteIdentifier($this->options['table']);
159 } else {
160 $t = explode('.', $this->options['table']);
161 for ($i = 0, $count = count($t); $i < $count; $i++)
162 $t[$i] = $this->db->quoteIdentifier($t[$i]);
163 $this->options['final_table'] = implode('.', $t);
164 }
165 $this->options['final_usernamecol'] = $this->db->quoteIdentifier($this->options['usernamecol']);
166 $this->options['final_passwordcol'] = $this->db->quoteIdentifier($this->options['passwordcol']);
167 } else {
168 $this->options['final_table'] = $this->options['table'];
169 $this->options['final_usernamecol'] = $this->options['usernamecol'];
170 $this->options['final_passwordcol'] = $this->options['passwordcol'];
171 }
172 return true;
173 }
174
175 // }}}
176 // {{{ query()
177
190 function query($query)
191 {
192 $err = $this->_prepare();
193 if ($err !== true) {
194 return $err;
195 }
196 return $this->db->query($query);
197 }
198
199 // }}}
200 // {{{ _setDefaults()
201
208 function _setDefaults()
209 {
210 $this->options['table'] = 'auth';
211 $this->options['usernamecol'] = 'username';
212 $this->options['passwordcol'] = 'password';
213 $this->options['dsn'] = '';
214 $this->options['db_fields'] = '';
215 $this->options['cryptType'] = 'md5';
216 $this->options['db_options'] = array();
217 $this->options['db_where'] = '';
218 $this->options['auto_quote'] = true;
219 }
220
221 // }}}
222 // {{{ _parseOptions()
223
230 function _parseOptions($array)
231 {
232 foreach ($array as $key => $value) {
233 if (isset($this->options[$key])) {
234 $this->options[$key] = $value;
235 }
236 }
237 }
238
239 // }}}
240 // {{{ _quoteDBFields()
241
249 function _quoteDBFields()
250 {
251 if (isset($this->options['db_fields'])) {
252 if (is_array($this->options['db_fields'])) {
253 if ($this->options['auto_quote']) {
254 $fields = array();
255 foreach ($this->options['db_fields'] as $field) {
256 $fields[] = $this->db->quoteIdentifier($field);
257 }
258 return implode(', ', $fields);
259 } else {
260 return implode(', ', $this->options['db_fields']);
261 }
262 } else {
263 if (strlen($this->options['db_fields']) > 0) {
264 if ($this->options['auto_quote']) {
265 return $this->db->quoteIdentifier($this->options['db_fields']);
266 } else {
267 return $this->options['db_fields'];
268 }
269 }
270 }
271 }
272
273 return '';
274 }
275
276 // }}}
277 // {{{ fetchData()
278
295 function fetchData($username, $password, $isChallengeResponse=false)
296 {
297 $this->log('Auth_Container_DB::fetchData() called.', AUTH_LOG_DEBUG);
298 // Prepare for a database query
299 $err = $this->_prepare();
300 if ($err !== true) {
301 return PEAR::raiseError($err->getMessage(), $err->getCode());
302 }
303
304 // Find if db_fields contains a *, if so assume all columns are selected
305 if (is_string($this->options['db_fields'])
306 && strstr($this->options['db_fields'], '*')) {
307 $sql_from = "*";
308 } else {
309 $sql_from = $this->options['final_usernamecol'].
310 ", ".$this->options['final_passwordcol'];
311
312 if (strlen($fields = $this->_quoteDBFields()) > 0) {
313 $sql_from .= ', '.$fields;
314 }
315 }
316
317 $query = "SELECT ".$sql_from.
318 " FROM ".$this->options['final_table'].
319 " WHERE ".$this->options['final_usernamecol']." = ".$this->db->quoteSmart($username);
320
321 // check if there is an optional parameter db_where
322 if ($this->options['db_where'] != '') {
323 // there is one, so add it to the query
324 $query .= " AND ".$this->options['db_where'];
325 }
326
327 $this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
328
329 $res = $this->db->getRow($query, null, DB_FETCHMODE_ASSOC);
330
331 if (DB::isError($res)) {
332 return PEAR::raiseError($res->getMessage(), $res->getCode());
333 }
334
335 if (!is_array($res)) {
336 $this->activeUser = '';
337 return false;
338 }
339
340 // Perform trimming here before the hashihg
341 $password = trim($password, "\r\n");
342 $res[$this->options['passwordcol']] = trim($res[$this->options['passwordcol']], "\r\n");
343
344 // If using Challenge Response md5 the pass with the secret
345 if ($isChallengeResponse) {
346 $res[$this->options['passwordcol']] = md5($res[$this->options['passwordcol']]
347 .$this->_auth_obj->session['loginchallenege']);
348
349 // UGLY cannot avoid without modifying verifyPassword
350 if ($this->options['cryptType'] == 'md5') {
351 $res[$this->options['passwordcol']] = md5($res[$this->options['passwordcol']]);
352 }
353
354 //print " Hashed Password [{$res[$this->options['passwordcol']]}]<br/>\n";
355 }
356
357 if ($this->verifyPassword($password,
358 $res[$this->options['passwordcol']],
359 $this->options['cryptType'])) {
360 // Store additional field values in the session
361 foreach ($res as $key => $value) {
362 if ($key == $this->options['passwordcol'] ||
363 $key == $this->options['usernamecol']) {
364 continue;
365 }
366
367 $this->log('Storing additional field: '.$key, AUTH_LOG_DEBUG);
368
369 // Use reference to the auth object if exists
370 // This is because the auth session variable can change so a
371 // static call to setAuthData does not make sence
372 $this->_auth_obj->setAuthData($key, $value);
373 }
374 return true;
375 }
376 $this->activeUser = $res[$this->options['usernamecol']];
377 return false;
378 }
379
380 // }}}
381 // {{{ listUsers()
382
389 function listUsers()
390 {
391 $this->log('Auth_Container_DB::listUsers() called.', AUTH_LOG_DEBUG);
392 $err = $this->_prepare();
393 if ($err !== true) {
394 return PEAR::raiseError($err->getMessage(), $err->getCode());
395 }
396
397 $retVal = array();
398
399 // Find if db_fields contains a *, if so assume all col are selected
400 if ( is_string($this->options['db_fields'])
401 && strstr($this->options['db_fields'], '*')) {
402 $sql_from = "*";
403 } else {
404 $sql_from = $this->options['final_usernamecol'].
405 ", ".$this->options['final_passwordcol'];
406
407 if (strlen($fields = $this->_quoteDBFields()) > 0) {
408 $sql_from .= ', '.$fields;
409 }
410 }
411
412 $query = sprintf("SELECT %s FROM %s",
413 $sql_from,
414 $this->options['final_table']
415 );
416
417 // check if there is an optional parameter db_where
418 if ($this->options['db_where'] != '') {
419 // there is one, so add it to the query
420 $query .= " WHERE ".$this->options['db_where'];
421 }
422
423 $this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
424
425 $res = $this->db->getAll($query, null, DB_FETCHMODE_ASSOC);
426
427 if (DB::isError($res)) {
428 return PEAR::raiseError($res->getMessage(), $res->getCode());
429 } else {
430 foreach ($res as $user) {
431 $user['username'] = $user[$this->options['usernamecol']];
432 $retVal[] = $user;
433 }
434 }
435 $this->log('Found '.count($retVal).' users.', AUTH_LOG_DEBUG);
436 return $retVal;
437 }
438
439 // }}}
440 // {{{ addUser()
441
452 function addUser($username, $password, $additional = "")
453 {
454 $this->log('Auth_Container_DB::addUser() called.', AUTH_LOG_DEBUG);
455 $err = $this->_prepare();
456 if ($err !== true) {
457 return PEAR::raiseError($err->getMessage(), $err->getCode());
458 }
459
460 if ( isset($this->options['cryptType'])
461 && $this->options['cryptType'] == 'none') {
462 $cryptFunction = 'strval';
463 } elseif ( isset($this->options['cryptType'])
464 && function_exists($this->options['cryptType'])) {
465 $cryptFunction = $this->options['cryptType'];
466 } else {
467 $cryptFunction = 'md5';
468 }
469
470 $password = $cryptFunction($password);
471
472 $additional_key = '';
473 $additional_value = '';
474
475 if (is_array($additional)) {
476 foreach ($additional as $key => $value) {
477 if ($this->options['auto_quote']) {
478 $additional_key .= ', ' . $this->db->quoteIdentifier($key);
479 } else {
480 $additional_key .= ', ' . $key;
481 }
482 $additional_value .= ", " . $this->db->quoteSmart($value);
483 }
484 }
485
486 $query = sprintf("INSERT INTO %s (%s, %s%s) VALUES (%s, %s%s)",
487 $this->options['final_table'],
488 $this->options['final_usernamecol'],
489 $this->options['final_passwordcol'],
490 $additional_key,
491 $this->db->quoteSmart($username),
492 $this->db->quoteSmart($password),
493 $additional_value
494 );
495
496 $this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
497
498 $res = $this->query($query);
499
500 if (DB::isError($res)) {
501 return PEAR::raiseError($res->getMessage(), $res->getCode());
502 } else {
503 return true;
504 }
505 }
506
507 // }}}
508 // {{{ removeUser()
509
518 function removeUser($username)
519 {
520 $this->log('Auth_Container_DB::removeUser() called.', AUTH_LOG_DEBUG);
521
522 $err = $this->_prepare();
523 if ($err !== true) {
524 return PEAR::raiseError($err->getMessage(), $err->getCode());
525 }
526
527 // check if there is an optional parameter db_where
528 if ($this->options['db_where'] != '') {
529 // there is one, so add it to the query
530 $where = " AND ".$this->options['db_where'];
531 } else {
532 $where = '';
533 }
534
535 $query = sprintf("DELETE FROM %s WHERE %s = %s %s",
536 $this->options['final_table'],
537 $this->options['final_usernamecol'],
538 $this->db->quoteSmart($username),
539 $where
540 );
541
542 $this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
543
544 $res = $this->query($query);
545
546 if (DB::isError($res)) {
547 return PEAR::raiseError($res->getMessage(), $res->getCode());
548 } else {
549 return true;
550 }
551 }
552
553 // }}}
554 // {{{ changePassword()
555
562 function changePassword($username, $password)
563 {
564 $this->log('Auth_Container_DB::changePassword() called.', AUTH_LOG_DEBUG);
565 $err = $this->_prepare();
566 if ($err !== true) {
567 return PEAR::raiseError($err->getMessage(), $err->getCode());
568 }
569
570 if ( isset($this->options['cryptType'])
571 && $this->options['cryptType'] == 'none') {
572 $cryptFunction = 'strval';
573 } elseif ( isset($this->options['cryptType'])
574 && function_exists($this->options['cryptType'])) {
575 $cryptFunction = $this->options['cryptType'];
576 } else {
577 $cryptFunction = 'md5';
578 }
579
580 $password = $cryptFunction($password);
581
582 // check if there is an optional parameter db_where
583 if ($this->options['db_where'] != '') {
584 // there is one, so add it to the query
585 $where = " AND ".$this->options['db_where'];
586 } else {
587 $where = '';
588 }
589
590 $query = sprintf("UPDATE %s SET %s = %s WHERE %s = %s %s",
591 $this->options['final_table'],
592 $this->options['final_passwordcol'],
593 $this->db->quoteSmart($password),
594 $this->options['final_usernamecol'],
595 $this->db->quoteSmart($username),
596 $where
597 );
598
599 $this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
600
601 $res = $this->query($query);
602
603 if (DB::isError($res)) {
604 return PEAR::raiseError($res->getMessage(), $res->getCode());
605 } else {
606 return true;
607 }
608 }
609
610 // }}}
611 // {{{ supportsChallengeResponse()
612
621 {
622 return in_array($this->options['cryptType'], array('md5', 'none', ''));
623 }
624
625 // }}}
626 // {{{ getCryptType()
627
631 function getCryptType()
632 {
633 return($this->options['cryptType']);
634 }
635
636 // }}}
637
638}
639?>
const AUTH_LOG_DEBUG
Auth Log level - DEBUG.
Definition: Auth.php:59
const PEAR_ERROR_RETURN
#+ ERROR constants
Definition: PEAR.php:31
_prepare()
Prepare database connection.
Definition: DB.php:148
_quoteDBFields()
Quote the db_fields option to avoid the possibility of SQL injection.
Definition: DB.php:249
_connect($dsn)
Connect to database by using the given DSN string.
Definition: DB.php:110
addUser($username, $password, $additional="")
Add user to the storage container.
Definition: DB.php:452
changePassword($username, $password)
Change password for user in the storage container.
Definition: DB.php:562
listUsers()
Returns a list of users from the container.
Definition: DB.php:389
fetchData($username, $password, $isChallengeResponse=false)
Get user information from database.
Definition: DB.php:295
supportsChallengeResponse()
Determine if this container supports password authentication with challenge response.
Definition: DB.php:620
getCryptType()
Returns the selected crypt type for this container.
Definition: DB.php:631
Auth_Container_DB($dsn)
Constructor of the container class.
Definition: DB.php:85
query($query)
Prepare query to the database.
Definition: DB.php:190
_parseOptions($array)
Parse options passed to the container class.
Definition: DB.php:230
_setDefaults()
Set some default options.
Definition: DB.php:208
removeUser($username)
Remove user from the storage container.
Definition: DB.php:518
verifyPassword($password1, $password2, $cryptType="md5")
Crypt and verfiy the entered password.
Definition: Container.php:101
log($message, $level=AUTH_LOG_DEBUG)
Log a message to the Auth log.
Definition: Container.php:246
isError($data, $code=null)
Tell whether a value is a PEAR error.
Definition: PEAR.php:279
& raiseError($message=null, $code=null, $mode=null, $options=null, $userinfo=null, $error_class=null, $skipmsg=false)
This method is a wrapper that returns an instance of the configured error class with this object's de...
Definition: PEAR.php:524
const DB_FETCHMODE_ASSOC
Definition: class.ilDB.php:10
$additional
Definition: goto.php:89