first commit. dokuwiki.
[h2N7SspZmY.git] / inc / auth / mysql.class.php
blobb1c6a3a52c0df3cb34722f6e36d62b35bad0e13f
1 <?php
2 /**
3 * MySQLP authentication backend
5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author Andreas Gohr <andi@splitbrain.org>
7 * @author Chris Smith <chris@jalakai.co.uk>
8 * @author Matthias Grimm <matthias.grimmm@sourceforge.net>
9 */
11 define('DOKU_AUTH', dirname(__FILE__));
12 require_once(DOKU_AUTH.'/basic.class.php');
14 class auth_mysql extends auth_basic {
16 var $dbcon = 0;
17 var $dbver = 0; // database version
18 var $dbrev = 0; // database revision
19 var $dbsub = 0; // database subrevision
20 var $cnf = null;
21 var $defaultgroup = "";
23 /**
24 * Constructor
26 * checks if the mysql interface is available, otherwise it will
27 * set the variable $success of the basis class to false
29 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
31 function auth_mysql() {
32 global $conf;
33 $this->cnf = $conf['auth']['mysql'];
35 if (method_exists($this, 'auth_basic'))
36 parent::auth_basic();
38 if(!function_exists('mysql_connect')) {
39 if ($this->cnf['debug'])
40 msg("MySQL err: PHP MySQL extension not found.",-1,__LINE__,__FILE__);
41 $this->success = false;
42 return;
45 // default to UTF-8, you rarely want something else
46 if(!isset($this->cnf['charset'])) $this->cnf['charset'] = 'utf8';
48 $this->defaultgroup = $conf['defaultgroup'];
50 // set capabilities based upon config strings set
51 if (empty($this->cnf['server']) || empty($this->cnf['user']) ||
52 empty($this->cnf['password']) || empty($this->cnf['database'])){
53 if ($this->cnf['debug'])
54 msg("MySQL err: insufficient configuration.",-1,__LINE__,__FILE__);
55 $this->success = false;
56 return;
59 $this->cando['addUser'] = $this->_chkcnf(array('getUserInfo',
60 'getGroups',
61 'addUser',
62 'getUserID',
63 'getGroupID',
64 'addGroup',
65 'addUserGroup'),true);
66 $this->cando['delUser'] = $this->_chkcnf(array('getUserID',
67 'delUser',
68 'delUserRefs'),true);
69 $this->cando['modLogin'] = $this->_chkcnf(array('getUserID',
70 'updateUser',
71 'UpdateTarget'),true);
72 $this->cando['modPass'] = $this->cando['modLogin'];
73 $this->cando['modName'] = $this->cando['modLogin'];
74 $this->cando['modMail'] = $this->cando['modLogin'];
75 $this->cando['modGroups'] = $this->_chkcnf(array('getUserID',
76 'getGroups',
77 'getGroupID',
78 'addGroup',
79 'addUserGroup',
80 'delGroup',
81 'getGroupID',
82 'delUserGroup'),true);
83 /* getGroups is not yet supported
84 $this->cando['getGroups'] = $this->_chkcnf(array('getGroups',
85 'getGroupID'),false); */
86 $this->cando['getUsers'] = $this->_chkcnf(array('getUsers',
87 'getUserInfo',
88 'getGroups'),false);
89 $this->cando['getUserCount'] = $this->_chkcnf(array('getUsers'),false);
92 /**
93 * Check if the given config strings are set
95 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
96 * @return bool
98 function _chkcnf($keys, $wop=false){
99 foreach ($keys as $key){
100 if (empty($this->cnf[$key])) return false;
103 /* write operation and lock array filled with tables names? */
104 if ($wop && (!is_array($this->cnf['TablesToLock']) ||
105 !count($this->cnf['TablesToLock']))){
106 return false;
109 return true;
113 * Checks if the given user exists and the given plaintext password
114 * is correct. Furtheron it might be checked wether the user is
115 * member of the right group
117 * Depending on which SQL string is defined in the config, password
118 * checking is done here (getpass) or by the database (passcheck)
120 * @param $user user who would like access
121 * @param $pass user's clear text password to check
122 * @return bool
124 * @author Andreas Gohr <andi@splitbrain.org>
125 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
127 function checkPass($user,$pass){
128 $rc = false;
130 if($this->_openDB()) {
131 $sql = str_replace('%{user}',$this->_escape($user),$this->cnf['checkPass']);
132 $sql = str_replace('%{pass}',$this->_escape($pass),$sql);
133 $sql = str_replace('%{dgroup}',$this->_escape($this->defaultgroup),$sql);
134 $result = $this->_queryDB($sql);
136 if($result !== false && count($result) == 1) {
137 if($this->cnf['forwardClearPass'] == 1)
138 $rc = true;
139 else
140 $rc = auth_verifyPassword($pass,$result[0]['pass']);
142 $this->_closeDB();
144 return $rc;
148 * [public function]
150 * Returns info about the given user needs to contain
151 * at least these fields:
152 * name string full name of the user
153 * mail string email addres of the user
154 * grps array list of groups the user is in
156 * @param $user user's nick to get data for
158 * @author Andreas Gohr <andi@splitbrain.org>
159 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
161 function getUserData($user){
162 if($this->_openDB()) {
163 $this->_lockTables("READ");
164 $info = $this->_getUserInfo($user);
165 $this->_unlockTables();
166 $this->_closeDB();
167 } else
168 $info = false;
169 return $info;
173 * [public function]
175 * Create a new User. Returns false if the user already exists,
176 * null when an error occurred and true if everything went well.
178 * The new user will be added to the default group by this
179 * function if grps are not specified (default behaviour).
181 * @param $user nick of the user
182 * @param $pwd clear text password
183 * @param $name full name of the user
184 * @param $mail email address
185 * @param $grps array of groups the user should become member of
187 * @author Andreas Gohr <andi@splitbrain.org>
188 * @author Chris Smith <chris@jalakai.co.uk>
189 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
191 function createUser($user,$pwd,$name,$mail,$grps=null){
192 if($this->_openDB()) {
193 if (($info = $this->_getUserInfo($user)) !== false)
194 return false; // user already exists
196 // set defaultgroup if no groups were given
197 if ($grps == null)
198 $grps = array($this->defaultgroup);
200 $this->_lockTables("WRITE");
201 $pwd = $this->cnf['forwardClearPass'] ? $pwd : auth_cryptPassword($pwd);
202 $rc = $this->_addUser($user,$pwd,$name,$mail,$grps);
203 $this->_unlockTables();
204 $this->_closeDB();
205 if ($rc) return true;
207 return null; // return error
211 * Modify user data [public function]
213 * An existing user dataset will be modified. Changes are given in an array.
215 * The dataset update will be rejected if the user name should be changed
216 * to an already existing one.
218 * The password must be provides unencrypted. Pasword cryption is done
219 * automatically if configured.
221 * If one or more groups could't be updated, an error would be set. In
222 * this case the dataset might already be changed and we can't rollback
223 * the changes. Transactions would be really usefull here.
225 * modifyUser() may be called without SQL statements defined that are
226 * needed to change group membership (for example if only the user profile
227 * should be modified). In this case we asure that we don't touch groups
228 * even $changes['grps'] is set by mistake.
230 * @param $user nick of the user to be changed
231 * @param $changes array of field/value pairs to be changed (password
232 * will be clear text)
233 * @return bool true on success, false on error
235 * @author Chris Smith <chris@jalakai.co.uk>
236 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
238 function modifyUser($user, $changes) {
239 $rc = false;
241 if (!is_array($changes) || !count($changes))
242 return true; // nothing to change
244 if($this->_openDB()) {
245 $this->_lockTables("WRITE");
247 if (($uid = $this->_getUserID($user))) {
248 $rc = $this->_updateUserInfo($changes, $uid);
250 if ($rc && isset($changes['grps']) && $this->cando['modGroups']) {
251 $groups = $this->_getGroups($user);
252 $grpadd = array_diff($changes['grps'], $groups);
253 $grpdel = array_diff($groups, $changes['grps']);
255 foreach($grpadd as $group)
256 if (($this->_addUserToGroup($user, $group, 1)) == false)
257 $rc = false;
259 foreach($grpdel as $group)
260 if (($this->_delUserFromGroup($user, $group)) == false)
261 $rc = false;
265 $this->_unlockTables();
266 $this->_closeDB();
268 return $rc;
272 * [public function]
274 * Remove one or more users from the list of registered users
276 * @param array $users array of users to be deleted
277 * @return int the number of users deleted
279 * @author Christopher Smith <chris@jalakai.co.uk>
280 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
282 function deleteUsers($users) {
283 $count = 0;
285 if($this->_openDB()) {
286 if (is_array($users) && count($users)) {
287 $this->_lockTables("WRITE");
288 foreach ($users as $user) {
289 if ($this->_delUser($user))
290 $count++;
292 $this->_unlockTables();
294 $this->_closeDB();
296 return $count;
300 * [public function]
302 * Counts users which meet certain $filter criteria.
304 * @param array $filter filter criteria in item/pattern pairs
305 * @return count of found users.
307 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
309 function getUserCount($filter=array()) {
310 $rc = 0;
312 if($this->_openDB()) {
313 $sql = $this->_createSQLFilter($this->cnf['getUsers'], $filter);
315 if ($this->dbver >= 4) {
316 $sql = substr($sql, 6); /* remove 'SELECT' or 'select' */
317 $sql = "SELECT SQL_CALC_FOUND_ROWS".$sql." LIMIT 1";
318 $this->_queryDB($sql);
319 $result = $this->_queryDB("SELECT FOUND_ROWS()");
320 $rc = $result[0]['FOUND_ROWS()'];
321 } else if (($result = $this->_queryDB($sql)))
322 $rc = count($result);
324 $this->_closeDB();
326 return $rc;
330 * Bulk retrieval of user data. [public function]
332 * @param first index of first user to be returned
333 * @param limit max number of users to be returned
334 * @param filter array of field/pattern pairs
335 * @return array of userinfo (refer getUserData for internal userinfo details)
337 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
339 function retrieveUsers($first=0,$limit=10,$filter=array()) {
340 $out = array();
342 if($this->_openDB()) {
343 $this->_lockTables("READ");
344 $sql = $this->_createSQLFilter($this->cnf['getUsers'], $filter);
345 $sql .= " ".$this->cnf['SortOrder']." LIMIT $first, $limit";
346 $result = $this->_queryDB($sql);
348 if (!empty($result)) {
349 foreach ($result as $user)
350 if (($info = $this->_getUserInfo($user['user'])))
351 $out[$user['user']] = $info;
354 $this->_unlockTables();
355 $this->_closeDB();
357 return $out;
361 * Give user membership of a group [public function]
363 * @param $user
364 * @param $group
365 * @return bool true on success, false on error
367 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
369 function joinGroup($user, $group) {
370 $rc = false;
372 if ($this->_openDB()) {
373 $this->_lockTables("WRITE");
374 $rc = $this->_addUserToGroup($user, $group);
375 $this->_unlockTables();
376 $this->_closeDB();
378 return $rc;
382 * Remove user from a group [public function]
384 * @param $user user that leaves a group
385 * @param $group group to leave
386 * @return bool
388 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
390 function leaveGroup($user, $group) {
391 $rc = false;
393 if ($this->_openDB()) {
394 $this->_lockTables("WRITE");
395 $uid = $this->_getUserID($user);
396 $rc = $this->_delUserFromGroup($user, $group);
397 $this->_unlockTables();
398 $this->_closeDB();
400 return $rc;
404 * MySQL is case-insensitive
406 function isCaseSensitive(){
407 return false;
411 * Adds a user to a group.
413 * If $force is set to '1' non existing groups would be created.
415 * The database connection must already be established. Otherwise
416 * this function does nothing and returns 'false'. It is strongly
417 * recommended to call this function only after all participating
418 * tables (group and usergroup) have been locked.
420 * @param $user user to add to a group
421 * @param $group name of the group
422 * @param $force '1' create missing groups
423 * @return bool 'true' on success, 'false' on error
425 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
427 function _addUserToGroup($user, $group, $force=0) {
428 $newgroup = 0;
430 if (($this->dbcon) && ($user)) {
431 $gid = $this->_getGroupID($group);
432 if (!$gid) {
433 if ($force) { // create missing groups
434 $sql = str_replace('%{group}',$this->_escape($group),$this->cnf['addGroup']);
435 $gid = $this->_modifyDB($sql);
436 $newgroup = 1; // group newly created
438 if (!$gid) return false; // group didn't exist and can't be created
441 $sql = $this->cnf['addUserGroup'];
442 if(strpos($sql,'%{uid}') !== false){
443 $uid = $this->_getUserID($user);
444 $sql = str_replace('%{uid}', $this->_escape($uid),$sql);
446 $sql = str_replace('%{user}', $this->_escape($user),$sql);
447 $sql = str_replace('%{gid}', $this->_escape($gid),$sql);
448 $sql = str_replace('%{group}',$this->_escape($group),$sql);
449 if ($this->_modifyDB($sql) !== false) return true;
451 if ($newgroup) { // remove previously created group on error
452 $sql = str_replace('%{gid}', $this->_escape($gid),$this->cnf['delGroup']);
453 $sql = str_replace('%{group}',$this->_escape($group),$sql);
454 $this->_modifyDB($sql);
457 return false;
461 * Remove user from a group
463 * @param $user user that leaves a group
464 * @param $group group to leave
465 * @return bool true on success, false on error
467 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
469 function _delUserFromGroup($user, $group) {
470 $rc = false;
473 if (($this->dbcon) && ($user)) {
474 $sql = $this->cnf['delUserGroup'];
475 if(strpos($sql,'%{uid}') !== false){
476 $uid = $this->_getUserID($user);
477 $sql = str_replace('%{uid}', $this->_escape($uid),$sql);
479 $gid = $this->_getGroupID($group);
480 if ($gid) {
481 $sql = str_replace('%{user}', $this->_escape($user),$sql);
482 $sql = str_replace('%{gid}', $this->_escape($gid),$sql);
483 $sql = str_replace('%{group}',$this->_escape($group),$sql);
484 $rc = $this->_modifyDB($sql) == 0 ? true : false;
487 return $rc;
491 * Retrieves a list of groups the user is a member off.
493 * The database connection must already be established
494 * for this function to work. Otherwise it will return
495 * 'false'.
497 * @param $user user whose groups should be listed
498 * @return bool false on error
499 * @return array array containing all groups on success
501 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
503 function _getGroups($user) {
504 $groups = array();
506 if($this->dbcon) {
507 $sql = str_replace('%{user}',$this->_escape($user),$this->cnf['getGroups']);
508 $result = $this->_queryDB($sql);
510 if($result !== false && count($result)) {
511 foreach($result as $row)
512 $groups[] = $row['group'];
514 return $groups;
516 return false;
520 * Retrieves the user id of a given user name
522 * The database connection must already be established
523 * for this function to work. Otherwise it will return
524 * 'false'.
526 * @param $user user whose id is desired
527 * @return user id
529 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
531 function _getUserID($user) {
532 if($this->dbcon) {
533 $sql = str_replace('%{user}',$this->_escape($user),$this->cnf['getUserID']);
534 $result = $this->_queryDB($sql);
535 return $result === false ? false : $result[0]['id'];
537 return false;
541 * Adds a new User to the database.
543 * The database connection must already be established
544 * for this function to work. Otherwise it will return
545 * 'false'.
547 * @param $user login of the user
548 * @param $pwd encrypted password
549 * @param $name full name of the user
550 * @param $mail email address
551 * @param $grps array of groups the user should become member of
552 * @return bool
554 * @author Andreas Gohr <andi@splitbrain.org>
555 * @author Chris Smith <chris@jalakai.co.uk>
556 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
558 function _addUser($user,$pwd,$name,$mail,$grps){
559 if($this->dbcon && is_array($grps)) {
560 $sql = str_replace('%{user}', $this->_escape($user),$this->cnf['addUser']);
561 $sql = str_replace('%{pass}', $this->_escape($pwd),$sql);
562 $sql = str_replace('%{name}', $this->_escape($name),$sql);
563 $sql = str_replace('%{email}',$this->_escape($mail),$sql);
564 $uid = $this->_modifyDB($sql);
566 if ($uid) {
567 foreach($grps as $group) {
568 $gid = $this->_addUserToGroup($user, $group, 1);
569 if ($gid === false) break;
572 if ($gid) return true;
573 else {
574 /* remove the new user and all group relations if a group can't
575 * be assigned. Newly created groups will remain in the database
576 * and won't be removed. This might create orphaned groups but
577 * is not a big issue so we ignore this problem here.
579 $this->_delUser($user);
580 if ($this->cnf['debug'])
581 msg ("MySQL err: Adding user '$user' to group '$group' failed.",-1,__LINE__,__FILE__);
585 return false;
589 * Deletes a given user and all his group references.
591 * The database connection must already be established
592 * for this function to work. Otherwise it will return
593 * 'false'.
595 * @param $user user whose id is desired
596 * @return bool
598 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
600 function _delUser($user) {
601 if($this->dbcon) {
602 $uid = $this->_getUserID($user);
603 if ($uid) {
604 $sql = str_replace('%{uid}',$this->_escape($uid),$this->cnf['delUserRefs']);
605 $this->_modifyDB($sql);
606 $sql = str_replace('%{uid}',$this->_escape($uid),$this->cnf['delUser']);
607 $sql = str_replace('%{user}', $this->_escape($user),$sql);
608 $this->_modifyDB($sql);
609 return true;
612 return false;
616 * getUserInfo
618 * Gets the data for a specific user The database connection
619 * must already be established for this function to work.
620 * Otherwise it will return 'false'.
622 * @param $user user's nick to get data for
623 * @return bool false on error
624 * @return array user info on success
626 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
628 function _getUserInfo($user){
629 $sql = str_replace('%{user}',$this->_escape($user),$this->cnf['getUserInfo']);
630 $result = $this->_queryDB($sql);
631 if($result !== false && count($result)) {
632 $info = $result[0];
633 $info['grps'] = $this->_getGroups($user);
634 return $info;
636 return false;
640 * Updates the user info in the database
642 * Update a user data structure in the database according changes
643 * given in an array. The user name can only be changes if it didn't
644 * exists already. If the new user name exists the update procedure
645 * will be aborted. The database keeps unchanged.
647 * The database connection has already to be established for this
648 * function to work. Otherwise it will return 'false'.
650 * The password will be crypted if necessary.
652 * @param $changes array of items to change as pairs of item and value
653 * @param $uid user id of dataset to change, must be unique in DB
654 * @return true on success or false on error
656 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
658 function _updateUserInfo($changes, $uid) {
659 $sql = $this->cnf['updateUser']." ";
660 $cnt = 0;
661 $err = 0;
663 if($this->dbcon) {
664 foreach ($changes as $item => $value) {
665 if ($item == 'user') {
666 if (($this->_getUserID($changes['user']))) {
667 $err = 1; /* new username already exists */
668 break; /* abort update */
670 if ($cnt++ > 0) $sql .= ", ";
671 $sql .= str_replace('%{user}',$value,$this->cnf['UpdateLogin']);
672 } else if ($item == 'name') {
673 if ($cnt++ > 0) $sql .= ", ";
674 $sql .= str_replace('%{name}',$value,$this->cnf['UpdateName']);
675 } else if ($item == 'pass') {
676 if (!$this->cnf['forwardClearPass'])
677 $value = auth_cryptPassword($value);
678 if ($cnt++ > 0) $sql .= ", ";
679 $sql .= str_replace('%{pass}',$value,$this->cnf['UpdatePass']);
680 } else if ($item == 'mail') {
681 if ($cnt++ > 0) $sql .= ", ";
682 $sql .= str_replace('%{email}',$value,$this->cnf['UpdateEmail']);
686 if ($err == 0) {
687 if ($cnt > 0) {
688 $sql .= " ".str_replace('%{uid}', $uid, $this->cnf['UpdateTarget']);
689 if(get_class($this) == 'auth_mysql') $sql .= " LIMIT 1"; //some PgSQL inheritance comp.
690 $this->_modifyDB($sql);
692 return true;
695 return false;
699 * Retrieves the group id of a given group name
701 * The database connection must already be established
702 * for this function to work. Otherwise it will return
703 * 'false'.
705 * @param $group group name which id is desired
706 * @return group id
708 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
710 function _getGroupID($group) {
711 if($this->dbcon) {
712 $sql = str_replace('%{group}',$this->_escape($group),$this->cnf['getGroupID']);
713 $result = $this->_queryDB($sql);
714 return $result === false ? false : $result[0]['id'];
716 return false;
720 * Opens a connection to a database and saves the handle for further
721 * usage in the object. The successful call to this functions is
722 * essential for most functions in this object.
724 * @return bool
726 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
728 function _openDB() {
729 if (!$this->dbcon) {
730 $con = @mysql_connect ($this->cnf['server'], $this->cnf['user'], $this->cnf['password']);
731 if ($con) {
732 if ((mysql_select_db($this->cnf['database'], $con))) {
733 if ((preg_match("/^(\d+)\.(\d+)\.(\d+).*/", mysql_get_server_info ($con), $result)) == 1) {
734 $this->dbver = $result[1];
735 $this->dbrev = $result[2];
736 $this->dbsub = $result[3];
738 $this->dbcon = $con;
739 if(!empty($this->cnf['charset'])){
740 mysql_query('SET CHARACTER SET "' . $this->cnf['charset'] . '"', $con);
742 return true; // connection and database successfully opened
743 } else {
744 mysql_close ($con);
745 if ($this->cnf['debug'])
746 msg("MySQL err: No access to database {$this->cnf['database']}.",-1,__LINE__,__FILE__);
748 } else if ($this->cnf['debug'])
749 msg ("MySQL err: Connection to {$this->cnf['user']}@{$this->cnf['server']} not possible.",
750 -1,__LINE__,__FILE__);
752 return false; // connection failed
754 return true; // connection already open
758 * Closes a database connection.
760 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
762 function _closeDB() {
763 if ($this->dbcon) {
764 mysql_close ($this->dbcon);
765 $this->dbcon = 0;
770 * Sends a SQL query to the database and transforms the result into
771 * an associative array.
773 * This function is only able to handle queries that returns a
774 * table such as SELECT.
776 * @param $query SQL string that contains the query
777 * @return array with the result table
779 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
781 function _queryDB($query) {
782 if($this->cnf['debug'] >= 2){
783 msg('MySQL query: '.hsc($query),0,__LINE__,__FILE__);
786 $resultarray = array();
787 if ($this->dbcon) {
788 $result = @mysql_query($query,$this->dbcon);
789 if ($result) {
790 while (($t = mysql_fetch_assoc($result)) !== false)
791 $resultarray[]=$t;
792 mysql_free_result ($result);
793 return $resultarray;
795 if ($this->cnf['debug'])
796 msg('MySQL err: '.mysql_error($this->dbcon),-1,__LINE__,__FILE__);
798 return false;
802 * Sends a SQL query to the database
804 * This function is only able to handle queries that returns
805 * either nothing or an id value such as INPUT, DELETE, UPDATE, etc.
807 * @param $query SQL string that contains the query
808 * @return insert id or 0, false on error
810 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
812 function _modifyDB($query) {
813 if ($this->dbcon) {
814 $result = @mysql_query($query,$this->dbcon);
815 if ($result) {
816 $rc = mysql_insert_id($this->dbcon); //give back ID on insert
817 if ($rc !== false) return $rc;
819 if ($this->cnf['debug'])
820 msg('MySQL err: '.mysql_error($this->dbcon),-1,__LINE__,__FILE__);
822 return false;
826 * Locked a list of tables for exclusive access so that modifications
827 * to the database can't be disturbed by other threads. The list
828 * could be set with $conf['auth']['mysql']['TablesToLock'] = array()
830 * If aliases for tables are used in SQL statements, also this aliases
831 * must be locked. For eg. you use a table 'user' and the alias 'u' in
832 * some sql queries, the array must looks like this (order is important):
833 * array("user", "user AS u");
835 * MySQL V3 is not able to handle transactions with COMMIT/ROLLBACK
836 * so that this functionality is simulated by this function. Nevertheless
837 * it is not as powerful as transactions, it is a good compromise in safty.
839 * @param $mode could be 'READ' or 'WRITE'
841 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
843 function _lockTables($mode) {
844 if ($this->dbcon) {
845 if (is_array($this->cnf['TablesToLock']) && !empty($this->cnf['TablesToLock'])) {
846 if ($mode == "READ" || $mode == "WRITE") {
847 $sql = "LOCK TABLES ";
848 $cnt = 0;
849 foreach ($this->cnf['TablesToLock'] as $table) {
850 if ($cnt++ != 0) $sql .= ", ";
851 $sql .= "$table $mode";
853 $this->_modifyDB($sql);
854 return true;
858 return false;
862 * Unlock locked tables. All existing locks of this thread will be
863 * abrogated.
865 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
867 function _unlockTables() {
868 if ($this->dbcon) {
869 $this->_modifyDB("UNLOCK TABLES");
870 return true;
872 return false;
876 * Transforms the filter settings in an filter string for a SQL database
877 * The database connection must already be established, otherwise the
878 * original SQL string without filter criteria will be returned.
880 * @param $sql SQL string to which the $filter criteria should be added
881 * @param $filter array of filter criteria as pairs of item and pattern
882 * @return SQL string with attached $filter criteria on success
883 * @return the original SQL string on error.
885 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
887 function _createSQLFilter($sql, $filter) {
888 $SQLfilter = "";
889 $cnt = 0;
891 if ($this->dbcon) {
892 foreach ($filter as $item => $pattern) {
893 $tmp = '%'.$this->_escape($pattern).'%';
894 if ($item == 'user') {
895 if ($cnt++ > 0) $SQLfilter .= " AND ";
896 $SQLfilter .= str_replace('%{user}',$tmp,$this->cnf['FilterLogin']);
897 } else if ($item == 'name') {
898 if ($cnt++ > 0) $SQLfilter .= " AND ";
899 $SQLfilter .= str_replace('%{name}',$tmp,$this->cnf['FilterName']);
900 } else if ($item == 'mail') {
901 if ($cnt++ > 0) $SQLfilter .= " AND ";
902 $SQLfilter .= str_replace('%{email}',$tmp,$this->cnf['FilterEmail']);
903 } else if ($item == 'grps') {
904 if ($cnt++ > 0) $SQLfilter .= " AND ";
905 $SQLfilter .= str_replace('%{group}',$tmp,$this->cnf['FilterGroup']);
909 // we have to check SQLfilter here and must not use $cnt because if
910 // any of cnf['Filter????'] is not defined, a malformed SQL string
911 // would be generated.
913 if (strlen($SQLfilter)) {
914 $glue = strpos(strtolower($sql),"where") ? " AND " : " WHERE ";
915 $sql = $sql.$glue.$SQLfilter;
919 return $sql;
923 * Escape a string for insertion into the database
925 * @author Andreas Gohr <andi@splitbrain.org>
926 * @param string $string The string to escape
927 * @param boolean $like Escape wildcard chars as well?
929 function _escape($string,$like=false){
930 if($this->dbcon){
931 $string = mysql_real_escape_string($string, $this->dbcon);
932 }else{
933 $string = addslashes($string);
935 if($like){
936 $string = addcslashes($string,'%_');
938 return $string;
942 //Setup VIM: ex: et ts=2 enc=utf-8 :