MDL-37125 import latest YUI 3.8.0
[moodle.git] / auth / db / auth.php
1 <?php
2 /**
3  * Authentication Plugin: External Database Authentication
4  *
5  * Checks against an external database.
6  *
7  * @package    auth
8  * @subpackage db
9  * @author     Martin Dougiamas
10  * @license    http://www.gnu.org/copyleft/gpl.html GNU Public License
11  */
13 defined('MOODLE_INTERNAL') || die();
15 require_once($CFG->libdir.'/authlib.php');
16 require_once($CFG->libdir.'/adodb/adodb.inc.php');
18 /**
19  * External database authentication plugin.
20  */
21 class auth_plugin_db extends auth_plugin_base {
23     /**
24      * Constructor.
25      */
26     function auth_plugin_db() {
27         $this->authtype = 'db';
28         $this->config = get_config('auth/db');
29         if (empty($this->config->extencoding)) {
30             $this->config->extencoding = 'utf-8';
31         }
32     }
34     /**
35      * Returns true if the username and password work and false if they are
36      * wrong or don't exist.
37      *
38      * @param string $username The username
39      * @param string $password The password
40      *
41      * @return bool Authentication success or failure.
42      */
43     function user_login($username, $password) {
44         global $CFG, $DB;
46         $extusername = textlib::convert($username, 'utf-8', $this->config->extencoding);
47         $extpassword = textlib::convert($password, 'utf-8', $this->config->extencoding);
49         if ($this->is_internal()) {
50             // lookup username externally, but resolve
51             // password locally -- to support backend that
52             // don't track passwords
54             if (isset($this->config->removeuser) and $this->config->removeuser == AUTH_REMOVEUSER_KEEP) {
55                 // No need to connect to external database in this case because users are never removed and we verify password locally.
56                 if ($user = $DB->get_record('user', array('username'=>$username, 'mnethostid'=>$CFG->mnet_localhost_id, 'auth'=>$this->authtype))) {
57                     return validate_internal_user_password($user, $password);
58                 } else {
59                     return false;
60                 }
61             }
63             $authdb = $this->db_init();
65             $rs = $authdb->Execute("SELECT * FROM {$this->config->table}
66                                      WHERE {$this->config->fielduser} = '".$this->ext_addslashes($extusername)."' ");
67             if (!$rs) {
68                 $authdb->Close();
69                 debugging(get_string('auth_dbcantconnect','auth_db'));
70                 return false;
71             }
73             if (!$rs->EOF) {
74                 $rs->Close();
75                 $authdb->Close();
76                 // user exists externally
77                 // check username/password internally
78                 if ($user = $DB->get_record('user', array('username'=>$username, 'mnethostid'=>$CFG->mnet_localhost_id, 'auth'=>$this->authtype))) {
79                     return validate_internal_user_password($user, $password);
80                 }
81             } else {
82                 $rs->Close();
83                 $authdb->Close();
84                 // user does not exist externally
85                 return false;
86             }
88         } else {
89             // normal case: use external db for both usernames and passwords
91             $authdb = $this->db_init();
93             if ($this->config->passtype === 'md5') {   // Re-format password accordingly
94                 $extpassword = md5($extpassword);
95             } else if ($this->config->passtype === 'sha1') {
96                 $extpassword = sha1($extpassword);
97             }
99             $rs = $authdb->Execute("SELECT * FROM {$this->config->table}
100                                 WHERE {$this->config->fielduser} = '".$this->ext_addslashes($extusername)."'
101                                   AND {$this->config->fieldpass} = '".$this->ext_addslashes($extpassword)."' ");
102             if (!$rs) {
103                 $authdb->Close();
104                 debugging(get_string('auth_dbcantconnect','auth_db'));
105                 return false;
106             }
108             if (!$rs->EOF) {
109                 $rs->Close();
110                 $authdb->Close();
111                 return true;
112             } else {
113                 $rs->Close();
114                 $authdb->Close();
115                 return false;
116             }
118         }
119     }
121     function db_init() {
122         // Connect to the external database (forcing new connection)
123         $authdb = ADONewConnection($this->config->type);
124         if (!empty($this->config->debugauthdb)) {
125             $authdb->debug = true;
126             ob_start();//start output buffer to allow later use of the page headers
127         }
128         $authdb->Connect($this->config->host, $this->config->user, $this->config->pass, $this->config->name, true);
129         $authdb->SetFetchMode(ADODB_FETCH_ASSOC);
130         if (!empty($this->config->setupsql)) {
131             $authdb->Execute($this->config->setupsql);
132         }
134         return $authdb;
135     }
137     /**
138      * Returns user attribute mappings between moodle and ldap
139      *
140      * @return array
141      */
142     function db_attributes() {
143         $moodleattributes = array();
144         foreach ($this->userfields as $field) {
145             if (!empty($this->config->{"field_map_$field"})) {
146                 $moodleattributes[$field] = $this->config->{"field_map_$field"};
147             }
148         }
149         $moodleattributes['username'] = $this->config->fielduser;
150         return $moodleattributes;
151     }
153     /**
154      * Reads any other information for a user from external database,
155      * then returns it in an array
156      *
157      * @param string $username
158      *
159      * @return array without magic quotes
160      */
161     function get_userinfo($username) {
162         global $CFG;
164         $extusername = textlib::convert($username, 'utf-8', $this->config->extencoding);
166         $authdb = $this->db_init();
168         //Array to map local fieldnames we want, to external fieldnames
169         $selectfields = $this->db_attributes();
171         $result = array();
172         //If at least one field is mapped from external db, get that mapped data:
173         if ($selectfields) {
174             $select = '';
175             foreach ($selectfields as $localname=>$externalname) {
176                 $select .= ", $externalname AS $localname";
177             }
178             $select = 'SELECT ' . substr($select,1);
179             $sql = $select .
180                 " FROM {$this->config->table}" .
181                 " WHERE {$this->config->fielduser} = '".$this->ext_addslashes($extusername)."'";
182             if ($rs = $authdb->Execute($sql)) {
183                 if ( !$rs->EOF ) {
184                     $fields_obj = $rs->FetchObj();
185                     $fields_obj = (object)array_change_key_case((array)$fields_obj , CASE_LOWER);
186                     foreach ($selectfields as $localname=>$externalname) {
187                         $result[$localname] = textlib::convert($fields_obj->{$localname}, $this->config->extencoding, 'utf-8');
188                      }
189                  }
190                  $rs->Close();
191             }
192         }
193         $authdb->Close();
194         return $result;
195     }
197     /**
198      * Change a user's password
199      *
200      * @param  object  $user        User table object
201      * @param  string  $newpassword Plaintext password
202      *
203      * @return bool                  True on success
204      */
205     function user_update_password($user, $newpassword) {
206         global $DB;
208         if ($this->is_internal()) {
209             $puser = $DB->get_record('user', array('id'=>$user->id), '*', MUST_EXIST);
210             if (update_internal_user_password($puser, $newpassword)) {
211                 $user->password = $puser->password;
212                 return true;
213             } else {
214                 return false;
215             }
216         } else {
217             // we should have never been called!
218             return false;
219         }
220     }
222     /**
223      * synchronizes user from external db to moodle user table
224      *
225      * Sync should be done by using idnumber attribute, not username.
226      * You need to pass firstsync parameter to function to fill in
227      * idnumbers if they don't exists in moodle user table.
228      *
229      * Syncing users removes (disables) users that don't exists anymore in external db.
230      * Creates new users and updates coursecreator status of users.
231      *
232      * This implementation is simpler but less scalable than the one found in the LDAP module.
233      *
234      * @param bool $do_updates  Optional: set to true to force an update of existing accounts
235      * @param bool $verbose
236      * @return int 0 means success, 1 means failure
237      */
238     function sync_users($do_updates=false, $verbose=false) {
239         global $CFG, $DB;
241         // list external users
242         $userlist = $this->get_userlist();
244         // delete obsolete internal users
245         if (!empty($this->config->removeuser)) {
247             $suspendselect = "";
248             if ($this->config->removeuser == AUTH_REMOVEUSER_SUSPEND) {
249                 $suspendselect = "AND u.suspended = 0";
250             }
252             // find obsolete users
253             if (count($userlist)) {
254                 list($notin_sql, $params) = $DB->get_in_or_equal($userlist, SQL_PARAMS_NAMED, 'u', false);
255                 $params['authtype'] = $this->authtype;
256                 $sql = "SELECT u.*
257                           FROM {user} u
258                          WHERE u.auth=:authtype AND u.deleted=0 AND u.mnethostid=:mnethostid $suspendselect AND u.username $notin_sql";
259             } else {
260                 $sql = "SELECT u.*
261                           FROM {user} u
262                          WHERE u.auth=:authtype AND u.deleted=0 AND u.mnethostid=:mnethostid $suspendselect";
263                 $params = array();
264                 $params['authtype'] = $this->authtype;
265             }
266             $params['mnethostid'] = $CFG->mnet_localhost_id;
267             $remove_users = $DB->get_records_sql($sql, $params);
269             if (!empty($remove_users)) {
270                 if ($verbose) {
271                     mtrace(get_string('auth_dbuserstoremove','auth_db', count($remove_users)));
272                 }
274                 foreach ($remove_users as $user) {
275                     if ($this->config->removeuser == AUTH_REMOVEUSER_FULLDELETE) {
276                         delete_user($user);
277                         if ($verbose) {
278                             mtrace("\t".get_string('auth_dbdeleteuser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)));
279                         }
280                     } else if ($this->config->removeuser == AUTH_REMOVEUSER_SUSPEND) {
281                         $updateuser = new stdClass();
282                         $updateuser->id   = $user->id;
283                         $updateuser->suspended = 1;
284                         $updateuser->timemodified = time();
285                         $DB->update_record('user', $updateuser);
286                         if ($verbose) {
287                             mtrace("\t".get_string('auth_dbsuspenduser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)));
288                         }
289                     }
290                 }
291             }
292             unset($remove_users); // free mem!
293         }
295         if (!count($userlist)) {
296             // exit right here
297             // nothing else to do
298             return 0;
299         }
301         ///
302         /// update existing accounts
303         ///
304         if ($do_updates) {
305             // narrow down what fields we need to update
306             $all_keys = array_keys(get_object_vars($this->config));
307             $updatekeys = array();
308             foreach ($all_keys as $key) {
309                 if (preg_match('/^field_updatelocal_(.+)$/',$key, $match)) {
310                     if ($this->config->{$key} === 'onlogin') {
311                         array_push($updatekeys, $match[1]); // the actual key name
312                     }
313                 }
314             }
315             // print_r($all_keys); print_r($updatekeys);
316             unset($all_keys); unset($key);
318             // only go ahead if we actually
319             // have fields to update locally
320             if (!empty($updatekeys)) {
321                 list($in_sql, $params) = $DB->get_in_or_equal($userlist, SQL_PARAMS_NAMED, 'u', true);
322                 $params['authtype'] = $this->authtype;
323                 $sql = "SELECT u.id, u.username
324                           FROM {user} u
325                          WHERE u.auth=:authtype AND u.deleted=0 AND u.username {$in_sql}";
326                 if ($update_users = $DB->get_records_sql($sql, $params)) {
327                     if ($verbose) {
328                         mtrace("User entries to update: ".count($update_users));
329                     }
331                     foreach ($update_users as $user) {
332                         if ($this->update_user_record($user->username, $updatekeys)) {
333                             if ($verbose) {
334                                 mtrace("\t".get_string('auth_dbupdatinguser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)));
335                             }
336                         } else {
337                             if ($verbose) {
338                                 mtrace("\t".get_string('auth_dbupdatinguser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id))." - ".get_string('skipped'));
339                             }
340                         }
341                     }
342                     unset($update_users); // free memory
343                 }
344             }
345         }
348         ///
349         /// create missing accounts
350         ///
351         // NOTE: this is very memory intensive
352         // and generally inefficient
353         $suspendselect = "";
354         if ($this->config->removeuser == AUTH_REMOVEUSER_SUSPEND) {
355             $suspendselect = "AND u.suspended = 0";
356         }
357         $sql = "SELECT u.id, u.username
358                   FROM {user} u
359                  WHERE u.auth=:authtype AND u.deleted='0' AND mnethostid=:mnethostid $suspendselect";
361         $users = $DB->get_records_sql($sql, array('authtype'=>$this->authtype, 'mnethostid'=>$CFG->mnet_localhost_id));
363         // simplify down to usernames
364         $usernames = array();
365         if (!empty($users)) {
366             foreach ($users as $user) {
367                 array_push($usernames, $user->username);
368             }
369             unset($users);
370         }
372         $add_users = array_diff($userlist, $usernames);
373         unset($usernames);
375         if (!empty($add_users)) {
376             if ($verbose) {
377                 mtrace(get_string('auth_dbuserstoadd','auth_db',count($add_users)));
378             }
379             // Do not use transactions around this foreach, we want to skip problematic users, not revert everything.
380             foreach($add_users as $user) {
381                 $username = $user;
382                 if ($this->config->removeuser == AUTH_REMOVEUSER_SUSPEND) {
383                     if ($old_user = $DB->get_record('user', array('username'=>$username, 'deleted'=>0, 'suspended'=>1, 'mnethostid'=>$CFG->mnet_localhost_id, 'auth'=>$this->authtype))) {
384                         $DB->set_field('user', 'suspended', 0, array('id'=>$old_user->id));
385                         if ($verbose) {
386                             mtrace("\t".get_string('auth_dbreviveduser', 'auth_db', array('name'=>$username, 'id'=>$old_user->id)));
387                         }
388                         continue;
389                     }
390                 }
392                 // Do not try to undelete users here, instead select suspending if you ever expect users will reappear.
394                 // prep a few params
395                 $user = $this->get_userinfo_asobj($user);
396                 $user->username   = $username;
397                 $user->confirmed  = 1;
398                 $user->auth       = $this->authtype;
399                 $user->mnethostid = $CFG->mnet_localhost_id;
400                 if (empty($user->lang)) {
401                     $user->lang = $CFG->lang;
402                 }
403                 $user->timecreated = time();
404                 $user->timemodified = $user->timecreated;
405                 if ($collision = $DB->get_record_select('user', "username = :username AND mnethostid = :mnethostid AND auth <> :auth", array('username'=>$user->username, 'mnethostid'=>$CFG->mnet_localhost_id, 'auth'=>$this->authtype), 'id,username,auth')) {
406                     if ($verbose) {
407                         mtrace("\t".get_string('auth_dbinsertuserduplicate', 'auth_db', array('username'=>$user->username, 'auth'=>$collision->auth)));
408                     }
409                     continue;
410                 }
411                 try {
412                     $id = $DB->insert_record ('user', $user); // it is truly a new user
413                     if ($verbose) {
414                         mtrace("\t".get_string('auth_dbinsertuser', 'auth_db', array('name'=>$user->username, 'id'=>$id)));
415                     }
416                 } catch (moodle_exception $e) {
417                     if ($verbose) {
418                         mtrace("\t".get_string('auth_dbinsertusererror', 'auth_db', $user->username));
419                     }
420                     continue;
421                 }
422                 // if relevant, tag for password generation
423                 if ($this->is_internal()) {
424                     set_user_preference('auth_forcepasswordchange', 1, $id);
425                     set_user_preference('create_password',          1, $id);
426                 }
427                 // Make sure user context is present.
428                 context_user::instance($id);
429             }
430             unset($add_users); // free mem
431         }
432         return 0;
433     }
435     function user_exists($username) {
437     /// Init result value
438         $result = false;
440         $extusername = textlib::convert($username, 'utf-8', $this->config->extencoding);
442         $authdb = $this->db_init();
444         $rs = $authdb->Execute("SELECT * FROM {$this->config->table}
445                                      WHERE {$this->config->fielduser} = '".$this->ext_addslashes($extusername)."' ");
447         if (!$rs) {
448             print_error('auth_dbcantconnect','auth_db');
449         } else if (!$rs->EOF) {
450             // user exists externally
451             $result = true;
452         }
454         $authdb->Close();
455         return $result;
456     }
459     function get_userlist() {
461     /// Init result value
462         $result = array();
464         $authdb = $this->db_init();
466         // fetch userlist
467         $rs = $authdb->Execute("SELECT {$this->config->fielduser} AS username
468                                 FROM   {$this->config->table} ");
470         if (!$rs) {
471             print_error('auth_dbcantconnect','auth_db');
472         } else if (!$rs->EOF) {
473             while ($rec = $rs->FetchRow()) {
474                 $rec = (object)array_change_key_case((array)$rec , CASE_LOWER);
475                 array_push($result, $rec->username);
476             }
477         }
479         $authdb->Close();
480         return $result;
481     }
483     /**
484      * reads user information from DB and return it in an object
485      *
486      * @param string $username username (with system magic quotes)
487      * @return array
488      */
489     function get_userinfo_asobj($username) {
490         $user_array = truncate_userinfo($this->get_userinfo($username));
491         $user = new stdClass();
492         foreach($user_array as $key=>$value) {
493             $user->{$key} = $value;
494         }
495         return $user;
496     }
498     /**
499      * will update a local user record from an external source.
500      * is a lighter version of the one in moodlelib -- won't do
501      * expensive ops such as enrolment
502      *
503      * If you don't pass $updatekeys, there is a performance hit and
504      * values removed from DB won't be removed from moodle.
505      *
506      * @param string $username username
507      * @param bool $updatekeys
508      * @return stdClass
509      */
510     function update_user_record($username, $updatekeys=false) {
511         global $CFG, $DB;
513         //just in case check text case
514         $username = trim(textlib::strtolower($username));
516         // get the current user record
517         $user = $DB->get_record('user', array('username'=>$username, 'mnethostid'=>$CFG->mnet_localhost_id));
518         if (empty($user)) { // trouble
519             error_log("Cannot update non-existent user: $username");
520             print_error('auth_dbusernotexist','auth_db',$username);
521             die;
522         }
524         // Ensure userid is not overwritten
525         $userid = $user->id;
526         $updated = false;
528         if ($newinfo = $this->get_userinfo($username)) {
529             $newinfo = truncate_userinfo($newinfo);
531             if (empty($updatekeys)) { // all keys? this does not support removing values
532                 $updatekeys = array_keys($newinfo);
533             }
535             foreach ($updatekeys as $key) {
536                 if (isset($newinfo[$key])) {
537                     $value = $newinfo[$key];
538                 } else {
539                     $value = '';
540                 }
542                 if (!empty($this->config->{'field_updatelocal_' . $key})) {
543                     if (isset($user->{$key}) and $user->{$key} != $value) { // only update if it's changed
544                         $DB->set_field('user', $key, $value, array('id'=>$userid));
545                         $updated = true;
546                     }
547                 }
548             }
549         }
550         if ($updated) {
551             $DB->set_field('user', 'timemodified', time(), array('id'=>$userid));
552         }
553         return $DB->get_record('user', array('id'=>$userid, 'deleted'=>0));
554     }
556     /**
557      * Called when the user record is updated.
558      * Modifies user in external database. It takes olduser (before changes) and newuser (after changes)
559      * compares information saved modified information to external db.
560      *
561      * @param mixed $olduser     Userobject before modifications
562      * @param mixed $newuser     Userobject new modified userobject
563      * @return boolean result
564      *
565      */
566     function user_update($olduser, $newuser) {
567         if (isset($olduser->username) and isset($newuser->username) and $olduser->username != $newuser->username) {
568             error_log("ERROR:User renaming not allowed in ext db");
569             return false;
570         }
572         if (isset($olduser->auth) and $olduser->auth != $this->authtype) {
573             return true; // just change auth and skip update
574         }
576         $curruser = $this->get_userinfo($olduser->username);
577         if (empty($curruser)) {
578             error_log("ERROR:User $olduser->username found in ext db");
579             return false;
580         }
582         $extusername = textlib::convert($olduser->username, 'utf-8', $this->config->extencoding);
584         $authdb = $this->db_init();
586         $update = array();
587         foreach($curruser as $key=>$value) {
588             if ($key == 'username') {
589                 continue; // skip this
590             }
591             if (empty($this->config->{"field_updateremote_$key"})) {
592                 continue; // remote update not requested
593             }
594             if (!isset($newuser->$key)) {
595                 continue;
596             }
597             $nuvalue = $newuser->$key;
598             if ($nuvalue != $value) {
599                 $update[] = $this->config->{"field_map_$key"}."='".$this->ext_addslashes(textlib::convert($nuvalue, 'utf-8', $this->config->extencoding))."'";
600             }
601         }
602         if (!empty($update)) {
603             $authdb->Execute("UPDATE {$this->config->table}
604                                  SET ".implode(',', $update)."
605                                WHERE {$this->config->fielduser}='".$this->ext_addslashes($extusername)."'");
606         }
607         $authdb->Close();
608         return true;
609     }
611     /**
612      * A chance to validate form data, and last chance to
613      * do stuff before it is inserted in config_plugin
614      *
615      * @param stfdClass config form
616      * @param array $error errors
617      * @return void
618      */
619      function validate_form($form, &$err) {
620         if ($form->passtype === 'internal') {
621             $this->config->changepasswordurl = '';
622             set_config('changepasswordurl', '', 'auth/db');
623         }
624     }
626     function prevent_local_passwords() {
627         return !$this->is_internal();
628     }
630     /**
631      * Returns true if this authentication plugin is "internal".
632      *
633      * Internal plugins use password hashes from Moodle user table for authentication.
634      *
635      * @return bool
636      */
637     function is_internal() {
638         if (!isset($this->config->passtype)) {
639             return true;
640         }
641         return ($this->config->passtype === 'internal');
642     }
644     /**
645      * Indicates if moodle should automatically update internal user
646      * records with data from external sources using the information
647      * from auth_plugin_base::get_userinfo().
648      *
649      * @return bool true means automatically copy data from ext to user table
650      */
651     function is_synchronised_with_external() {
652         return true;
653     }
655     /**
656      * Returns true if this authentication plugin can change the user's
657      * password.
658      *
659      * @return bool
660      */
661     function can_change_password() {
662         return ($this->is_internal() or !empty($this->config->changepasswordurl));
663     }
665     /**
666      * Returns the URL for changing the user's pw, or empty if the default can
667      * be used.
668      *
669      * @return moodle_url
670      */
671     function change_password_url() {
672         if ($this->is_internal()) {
673             // standard form
674             return null;
675         } else {
676             // use admin defined custom url
677             return new moodle_url($this->config->changepasswordurl);
678         }
679     }
681     /**
682      * Returns true if plugin allows resetting of internal password.
683      *
684      * @return bool
685      */
686     function can_reset_password() {
687         return $this->is_internal();
688     }
690     /**
691      * Prints a form for configuring this authentication plugin.
692      *
693      * This function is called from admin/auth.php, and outputs a full page with
694      * a form for configuring this plugin.
695      *
696      * @param stdClass $config
697      * @param array $err errors
698      * @param array $user_fields
699      * @return void
700      */
701     function config_form($config, $err, $user_fields) {
702         include 'config.html';
703     }
705     /**
706      * Processes and stores configuration data for this authentication plugin.
707      * @param srdClass $config
708      * @return bool always true or exception
709      */
710     function process_config($config) {
711         // set to defaults if undefined
712         if (!isset($config->host)) {
713             $config->host = 'localhost';
714         }
715         if (!isset($config->type)) {
716             $config->type = 'mysql';
717         }
718         if (!isset($config->sybasequoting)) {
719             $config->sybasequoting = 0;
720         }
721         if (!isset($config->name)) {
722             $config->name = '';
723         }
724         if (!isset($config->user)) {
725             $config->user = '';
726         }
727         if (!isset($config->pass)) {
728             $config->pass = '';
729         }
730         if (!isset($config->table)) {
731             $config->table = '';
732         }
733         if (!isset($config->fielduser)) {
734             $config->fielduser = '';
735         }
736         if (!isset($config->fieldpass)) {
737             $config->fieldpass = '';
738         }
739         if (!isset($config->passtype)) {
740             $config->passtype = 'plaintext';
741         }
742         if (!isset($config->extencoding)) {
743             $config->extencoding = 'utf-8';
744         }
745         if (!isset($config->setupsql)) {
746             $config->setupsql = '';
747         }
748         if (!isset($config->debugauthdb)) {
749             $config->debugauthdb = 0;
750         }
751         if (!isset($config->removeuser)) {
752             $config->removeuser = AUTH_REMOVEUSER_KEEP;
753         }
754         if (!isset($config->changepasswordurl)) {
755             $config->changepasswordurl = '';
756         }
758         // save settings
759         set_config('host',          $config->host,          'auth/db');
760         set_config('type',          $config->type,          'auth/db');
761         set_config('sybasequoting', $config->sybasequoting, 'auth/db');
762         set_config('name',          $config->name,          'auth/db');
763         set_config('user',          $config->user,          'auth/db');
764         set_config('pass',          $config->pass,          'auth/db');
765         set_config('table',         $config->table,         'auth/db');
766         set_config('fielduser',     $config->fielduser,     'auth/db');
767         set_config('fieldpass',     $config->fieldpass,     'auth/db');
768         set_config('passtype',      $config->passtype,      'auth/db');
769         set_config('extencoding',   trim($config->extencoding), 'auth/db');
770         set_config('setupsql',      trim($config->setupsql),'auth/db');
771         set_config('debugauthdb',   $config->debugauthdb,   'auth/db');
772         set_config('removeuser',    $config->removeuser,    'auth/db');
773         set_config('changepasswordurl', trim($config->changepasswordurl), 'auth/db');
775         return true;
776     }
778     function ext_addslashes($text) {
779         // using custom made function for now
780         if (empty($this->config->sybasequoting)) {
781             $text = str_replace('\\', '\\\\', $text);
782             $text = str_replace(array('\'', '"', "\0"), array('\\\'', '\\"', '\\0'), $text);
783         } else {
784             $text = str_replace("'", "''", $text);
785         }
786         return $text;
787     }