ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups Pages
MDB2.php
Go to the documentation of this file.
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
3 
29 require_once 'Auth/Container.php';
33 require_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 ?>