ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
MDB2.php
Go to the documentation of this file.
1<?php
2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
3
29require_once 'Auth/Container.php';
33require_once 'MDB2.php';
34
52{
53
54 // {{{ properties
55
60 var $options = array();
61
66 var $db = null;
67 var $dsn = '';
68
73 var $activeUser = '';
74
75 // }}}
76 // {{{ Auth_Container_MDB2() [constructor]
77
87 {
88 $this->_setDefaults();
89
90 if (is_array($dsn)) {
91 $this->_parseOptions($dsn);
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_MDB2::_connect() called.', AUTH_LOG_DEBUG);
113 if (is_string($dsn) || is_array($dsn)) {
114 $this->db =& MDB2::connect($dsn, $this->options['db_options']);
115 } elseif (is_subclass_of($dsn, 'MDB2_Driver_Common')) {
116 $this->db = $dsn;
117 } elseif (is_object($dsn) && MDB2::isError($dsn)) {
118 return PEAR::raiseError($dsn->getMessage(), $dsn->code);
119 } else {
120 return PEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__,
121 41,
123 null,
124 null
125 );
126
127 }
128
129 if (MDB2::isError($this->db) || PEAR::isError($this->db)) {
130 return PEAR::raiseError($this->db->getMessage(), $this->db->code);
131 }
132
133 if ($this->options['auto_quote']) {
134 if (strpos('.', $this->options['table']) === false) {
135 $this->options['final_table'] = $this->db->quoteIdentifier($this->options['table'], true);
136 } else {
137 $t = explode('.', $this->options['table']);
138 for ($i = 0, $count = count($t); $i < $count; $i++)
139 $t[$i] = $this->db->quoteIdentifier($t[$i], true);
140 $this->options['final_table'] = implode('.', $t);
141 }
142 $this->options['final_usernamecol'] = $this->db->quoteIdentifier($this->options['usernamecol'], true);
143 $this->options['final_passwordcol'] = $this->db->quoteIdentifier($this->options['passwordcol'], true);
144 } else {
145 $this->options['final_table'] = $this->options['table'];
146 $this->options['final_usernamecol'] = $this->options['usernamecol'];
147 $this->options['final_passwordcol'] = $this->options['passwordcol'];
148 }
149
150 return true;
151 }
152
153 // }}}
154 // {{{ _prepare()
155
165 function _prepare()
166 {
167 if (is_subclass_of($this->db, 'MDB2_Driver_Common')) {
168 return true;
169 }
170 return $this->_connect($this->options['dsn']);
171 }
172
173 // }}}
174 // {{{ query()
175
188 function query($query)
189 {
190 $this->log('Auth_Container_MDB2::query() called.', AUTH_LOG_DEBUG);
191 $err = $this->_prepare();
192 if ($err !== true) {
193 return $err;
194 }
195 return $this->db->exec($query);
196 }
197
198 // }}}
199 // {{{ _setDefaults()
200
207 function _setDefaults()
208 {
209 $this->options['table'] = 'auth';
210 $this->options['usernamecol'] = 'username';
211 $this->options['passwordcol'] = 'password';
212 $this->options['dsn'] = '';
213 $this->options['db_fields'] = '';
214 $this->options['cryptType'] = 'md5';
215 $this->options['db_options'] = array();
216 $this->options['db_where'] = '';
217 $this->options['auto_quote'] = true;
218 }
219
220 // }}}
221 // {{{ _parseOptions()
222
229 function _parseOptions($array)
230 {
231 foreach ($array as $key => $value) {
232 if (isset($this->options[$key])) {
233 $this->options[$key] = $value;
234 }
235 }
236 }
237
238 // }}}
239 // {{{ _quoteDBFields()
240
248 function _quoteDBFields()
249 {
250 if (isset($this->options['db_fields'])) {
251 if (is_array($this->options['db_fields'])) {
252 if ($this->options['auto_quote']) {
253 $fields = array();
254 foreach ($this->options['db_fields'] as $field) {
255 $fields[] = $this->db->quoteIdentifier($field, true);
256 }
257 return implode(', ', $fields);
258 } else {
259 return implode(', ', $this->options['db_fields']);
260 }
261 } else {
262 if (strlen($this->options['db_fields']) > 0) {
263 if ($this->options['auto_quote']) {
264 return $this->db->quoteIdentifier($this->options['db_fields'], true);
265 } else {
266 return $this->options['db_fields'];
267 }
268 }
269 }
270 }
271
272 return '';
273 }
274
275 // }}}
276 // {{{ fetchData()
277
294 function fetchData($username, $password, $isChallengeResponse=false)
295 {
296 $this->log('Auth_Container_MDB2::fetchData() called.', AUTH_LOG_DEBUG);
297 // Prepare for a database query
298 $err = $this->_prepare();
299 if ($err !== true) {
300 return PEAR::raiseError($err->getMessage(), $err->getCode());
301 }
302
303 //Check if db_fields contains a *, if so assume all columns are selected
304 if (is_string($this->options['db_fields'])
305 && strstr($this->options['db_fields'], '*')) {
306 $sql_from = '*';
307 } else {
308 $sql_from = $this->options['final_usernamecol'].
309 ", ".$this->options['final_passwordcol'];
310
311 if (strlen($fields = $this->_quoteDBFields()) > 0) {
312 $sql_from .= ', '.$fields;
313 }
314 }
315 $query = sprintf("SELECT %s FROM %s WHERE %s = %s",
316 $sql_from,
317 $this->options['final_table'],
318 $this->options['final_usernamecol'],
319 $this->db->quote($username, 'text')
320 );
321
322 // check if there is an optional parameter db_where
323 if ($this->options['db_where'] != '') {
324 // there is one, so add it to the query
325 $query .= " AND ".$this->options['db_where'];
326 }
327
328 $this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG);
329
330 $res = $this->db->queryRow($query, null, MDB2_FETCHMODE_ASSOC);
332 return PEAR::raiseError($res->getMessage(), $res->getCode());
333 }
334 if (!is_array($res)) {
335 $this->activeUser = '';
336 return false;
337 }
338
339 // Perform trimming here before the hashing
340 $password = trim($password, "\r\n");
341 $res[$this->options['passwordcol']] = trim($res[$this->options['passwordcol']], "\r\n");
342 // If using Challenge Response md5 the pass with the secret
343 if ($isChallengeResponse) {
344 $res[$this->options['passwordcol']] =
345 md5($res[$this->options['passwordcol']].$this->_auth_obj->session['loginchallenege']);
346 // UGLY cannot avoid without modifying verifyPassword
347 if ($this->options['cryptType'] == 'md5') {
348 $res[$this->options['passwordcol']] = md5($res[$this->options['passwordcol']]);
349 }
350 }
351 if ($this->verifyPassword($password,
352 $res[$this->options['passwordcol']],
353 $this->options['cryptType'])) {
354 // Store additional field values in the session
355 foreach ($res as $key => $value) {
356 if ($key == $this->options['passwordcol'] ||
357 $key == $this->options['usernamecol']) {
358 continue;
359 }
360
361 $this->log('Storing additional field: '.$key, AUTH_LOG_DEBUG);
362
363 // Use reference to the auth object if exists
364 // This is because the auth session variable can change so a static call to setAuthData does not make sense
365 $this->_auth_obj->setAuthData($key, $value);
366 }
367 return true;
368 }
369
370 $this->activeUser = $res[$this->options['usernamecol']];
371 return false;
372 }
373
374 // }}}
375 // {{{ listUsers()
376
383 function listUsers()
384 {
385 $this->log('Auth_Container_MDB2::listUsers() called.', AUTH_LOG_DEBUG);
386 $err = $this->_prepare();
387 if ($err !== true) {
388 return PEAR::raiseError($err->getMessage(), $err->getCode());
389 }
390
391 $retVal = array();
392
393 //Check if db_fields contains a *, if so assume all columns are selected
394 if ( is_string($this->options['db_fields'])
395 && strstr($this->options['db_fields'], '*')) {
396 $sql_from = '*';
397 } else {
398 $sql_from = $this->options['final_usernamecol'].
399 ", ".$this->options['final_passwordcol'];
400
401 if (strlen($fields = $this->_quoteDBFields()) > 0) {
402 $sql_from .= ', '.$fields;
403 }
404 }
405
406 $query = sprintf('SELECT %s FROM %s',
407 $sql_from,
408 $this->options['final_table']
409 );
410
411 // check if there is an optional parameter db_where
412 if ($this->options['db_where'] != '') {
413 // there is one, so add it to the query
414 $query .= " WHERE ".$this->options['db_where'];
415 }
416
417 $this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG);
418
419 $res = $this->db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
420 if (MDB2::isError($res)) {
421 return PEAR::raiseError($res->getMessage(), $res->getCode());
422 } else {
423 foreach ($res as $user) {
424 $user['username'] = $user[$this->options['usernamecol']];
425 $retVal[] = $user;
426 }
427 }
428 $this->log('Found '.count($retVal).' users.', AUTH_LOG_DEBUG);
429 return $retVal;
430 }
431
432 // }}}
433 // {{{ addUser()
434
445 function addUser($username, $password, $additional = "")
446 {
447 $this->log('Auth_Container_MDB2::addUser() called.', AUTH_LOG_DEBUG);
448
449 // Prepare for a database query
450 $err = $this->_prepare();
451 if ($err !== true) {
452 return PEAR::raiseError($err->getMessage(), $err->getCode());
453 }
454
455 if (isset($this->options['cryptType']) && $this->options['cryptType'] == 'none') {
456 $cryptFunction = 'strval';
457 } elseif (isset($this->options['cryptType']) && function_exists($this->options['cryptType'])) {
458 $cryptFunction = $this->options['cryptType'];
459 } else {
460 $cryptFunction = 'md5';
461 }
462
463 $password = $cryptFunction($password);
464
465 $additional_key = '';
466 $additional_value = '';
467
468 if (is_array($additional)) {
469 foreach ($additional as $key => $value) {
470 if ($this->options['auto_quote']) {
471 $additional_key .= ', ' . $this->db->quoteIdentifier($key, true);
472 } else {
473 $additional_key .= ', ' . $key;
474 }
475 $additional_value .= ', ' . $this->db->quote($value, 'text');
476 }
477 }
478
479 $query = sprintf("INSERT INTO %s (%s, %s%s) VALUES (%s, %s%s)",
480 $this->options['final_table'],
481 $this->options['final_usernamecol'],
482 $this->options['final_passwordcol'],
483 $additional_key,
484 $this->db->quote($username, 'text'),
485 $this->db->quote($password, 'text'),
486 $additional_value
487 );
488
489 $this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG);
490
491 $res = $this->query($query);
492
493 if (MDB2::isError($res)) {
494 return PEAR::raiseError($res->getMessage(), $res->code);
495 }
496 return true;
497 }
498
499 // }}}
500 // {{{ removeUser()
501
510 function removeUser($username)
511 {
512 $this->log('Auth_Container_MDB2::removeUser() called.', AUTH_LOG_DEBUG);
513 // Prepare for a database query
514 $err = $this->_prepare();
515 if ($err !== true) {
516 return PEAR::raiseError($err->getMessage(), $err->getCode());
517 }
518
519 $query = sprintf("DELETE FROM %s WHERE %s = %s",
520 $this->options['final_table'],
521 $this->options['final_usernamecol'],
522 $this->db->quote($username, 'text')
523 );
524
525 // check if there is an optional parameter db_where
526 if ($this->options['db_where'] != '') {
527 // there is one, so add it to the query
528 $query .= " AND ".$this->options['db_where'];
529 }
530
531 $this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG);
532
533 $res = $this->query($query);
534
535 if (MDB2::isError($res)) {
536 return PEAR::raiseError($res->getMessage(), $res->code);
537 }
538 return true;
539 }
540
541 // }}}
542 // {{{ changePassword()
543
550 function changePassword($username, $password)
551 {
552 $this->log('Auth_Container_MDB2::changePassword() called.', AUTH_LOG_DEBUG);
553 // Prepare for a database query
554 $err = $this->_prepare();
555 if ($err !== true) {
556 return PEAR::raiseError($err->getMessage(), $err->getCode());
557 }
558
559 if (isset($this->options['cryptType']) && $this->options['cryptType'] == 'none') {
560 $cryptFunction = 'strval';
561 } elseif (isset($this->options['cryptType']) && function_exists($this->options['cryptType'])) {
562 $cryptFunction = $this->options['cryptType'];
563 } else {
564 $cryptFunction = 'md5';
565 }
566
567 $password = $cryptFunction($password);
568
569 $query = sprintf("UPDATE %s SET %s = %s WHERE %s = %s",
570 $this->options['final_table'],
571 $this->options['final_passwordcol'],
572 $this->db->quote($password, 'text'),
573 $this->options['final_usernamecol'],
574 $this->db->quote($username, 'text')
575 );
576
577 // check if there is an optional parameter db_where
578 if ($this->options['db_where'] != '') {
579 // there is one, so add it to the query
580 $query .= " AND ".$this->options['db_where'];
581 }
582
583 $this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG);
584
585 $res = $this->query($query);
586
587 if (MDB2::isError($res)) {
588 return PEAR::raiseError($res->getMessage(), $res->code);
589 }
590 return true;
591 }
592
593 // }}}
594 // {{{ supportsChallengeResponse()
595
604 {
605 return in_array($this->options['cryptType'], array('md5', 'none', ''));
606 }
607
608 // }}}
609 // {{{ getCryptType()
610
616 function getCryptType()
617 {
618 return $this->options['cryptType'];
619 }
620
621 // }}}
622
623}
624?>
const AUTH_LOG_DEBUG
Auth Log level - DEBUG.
Definition: Auth.php:59
const MDB2_FETCHMODE_ASSOC
Column data indexed by column names.
Definition: MDB2.php:129
const PEAR_ERROR_RETURN
#+ ERROR constants
Definition: PEAR.php:31
query($query)
Prepare query to the database.
Definition: MDB2.php:188
Auth_Container_MDB2($dsn)
Constructor of the container class.
Definition: MDB2.php:86
listUsers()
Returns a list of users from the container.
Definition: MDB2.php:383
removeUser($username)
Remove user from the storage container.
Definition: MDB2.php:510
fetchData($username, $password, $isChallengeResponse=false)
Get user information from database.
Definition: MDB2.php:294
addUser($username, $password, $additional="")
Add user to the storage container.
Definition: MDB2.php:445
supportsChallengeResponse()
Determine if this container supports password authentication with challenge response.
Definition: MDB2.php:603
_setDefaults()
Set some default options.
Definition: MDB2.php:207
_parseOptions($array)
Parse options passed to the container class.
Definition: MDB2.php:229
changePassword($username, $password)
Change password for user in the storage container.
Definition: MDB2.php:550
getCryptType()
Returns the selected crypt type for this container.
Definition: MDB2.php:616
_prepare()
Prepare database connection.
Definition: MDB2.php:165
_connect($dsn)
Connect to database by using the given DSN string.
Definition: MDB2.php:110
_quoteDBFields()
Quote the db_fields option to avoid the possibility of SQL injection.
Definition: MDB2.php:248
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 MDB2 error.
Definition: MDB2.php:594
& connect($dsn, $options=false)
Create a new MDB2 connection object and connect to the specified database.
Definition: MDB2.php:431
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
$additional
Definition: goto.php:89