summaryrefslogtreecommitdiff
path: root/inc/auth/mysql.class.php
diff options
context:
space:
mode:
Diffstat (limited to 'inc/auth/mysql.class.php')
-rw-r--r--inc/auth/mysql.class.php266
1 files changed, 174 insertions, 92 deletions
diff --git a/inc/auth/mysql.class.php b/inc/auth/mysql.class.php
index 41d45e940..a5fda82e5 100644
--- a/inc/auth/mysql.class.php
+++ b/inc/auth/mysql.class.php
@@ -14,6 +14,9 @@ require_once(DOKU_AUTH.'/basic.class.php');
class auth_mysql extends auth_basic {
var $dbcon = 0;
+ var $dbver = 0; // database version
+ var $dbrev = 0; // database revision
+ var $dbsub = 0; // database subrevision
var $cnf = null;
var $defaultgroup = "";
@@ -27,13 +30,13 @@ class auth_mysql extends auth_basic {
*/
function auth_mysql() {
global $conf;
- global $lang;
if (method_exists($this, 'auth_basic'))
parent::auth_basic();
if(!function_exists('mysql_connect')) {
- msg($lang['noMySQL'],-1);
+ if ($this->cnf['debug'])
+ msg("MySQL err: PHP MySQL extension not found.",-1);
$this->success = false;
}
@@ -141,17 +144,24 @@ class auth_mysql extends auth_basic {
}
/**
- * [public function]
+ * Modify user data [public function]
*
- * Modify user data
+ * An existing user dataset will be modified. Changes are given in an array.
+ *
+ * The dataset update will be rejected if the user name should be changed
+ * to an already existing one.
*
- * @param $user nick of the user to be changed
- * @param $changes array of field/value pairs to be changed (password will be clear text)
- * @return bool
+ * The password must be provides unencrypted. Pasword cryption is done
+ * automatically if configured.
*
- * @todo Modifications are done through deleting and recreating the user.
- * This might be suboptimal and dangerous. Using UPDATE seems the
- * better way.
+ * If one or more groups could't be updated, no error would be set. In
+ * this case the dataset might already be changed and we can't rollback
+ * the changes. Transactions would be really usefull here.
+ *
+ * @param $user nick of the user to be changed
+ * @param $changes array of field/value pairs to be changed (password
+ * will be clear text)
+ * @return bool true on success, false on error
*
* @author Chris Smith <chris@jalakai.co.uk>
* @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
@@ -161,25 +171,26 @@ class auth_mysql extends auth_basic {
if (!is_array($changes) || !count($changes))
return true; // nothing to change
-
+
if($this->_openDB()) {
$this->_lockTables("WRITE");
- if (($info = $this->_getUserInfo($user)) !== false) {
- $newuser = $user;
- foreach ($changes as $field => $value) {
- if ($field == 'user')
- $newuser = $value;
- if ($field == 'pass' && !$this->cnf['encryptPass'])
- $value = auth_cryptPassword($value);
- $info[$field] = $value; // update user record
- }
- $rc = $this->_delUser($user); // remove user from database
- if ($rc)
- $rc = $this->_addUser($newuser,$info['pass'],$info['name'],$info['mail'],$info['grps']);
- if (!$rc)
- msg($lang['modUserFailed'], -1);
- }
+ if (($uid = $this->_getUserID($user))) {
+ $rc = $this->_updateUserInfo($changes, $uid);
+
+ if ($rc && isset($changes['grps'])) {
+ $groups = $this->_getGroups($user);
+ $grpadd = array_diff($changes['grps'], $groups);
+ $grpdel = array_diff($groups, $changes['grps']);
+
+ foreach($grpadd as $group)
+ $this->_addUserToGroup($uid, $group, 1);
+
+ foreach($grpdel as $group)
+ $this->_delUserFromGroup($uid, $group);
+ }
+ }
+
$this->_unlockTables();
$this->_closeDB();
}
@@ -238,9 +249,7 @@ class auth_mysql extends auth_basic {
}
/**
- * [public function]
- *
- * Bulk retrieval of user data.
+ * Bulk retrieval of user data. [public function]
*
* @param start index of first user to be returned
* @param limit max number of users to be returned
@@ -276,22 +285,21 @@ class auth_mysql extends auth_basic {
}
/**
- * [public function]
- *
- * Give user membership of a group
+ * Give user membership of a group [public function]
*
* @param $user
* @param $group
- * @return bool
+ * @return bool true on success, false on error
*
* @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
*/
function joinGroup($user, $group) {
$rc = false;
- if($this->_openDB()) {
+ if ($this->_openDB()) {
$this->_lockTables("WRITE");
- $rc = _addUserToGroup($user, $group);
+ $uid = $this->_getUserID($user);
+ $rc = $this->_addUserToGroup($uid, $group);
$this->_unlockTables();
$this->_closeDB();
}
@@ -299,9 +307,7 @@ class auth_mysql extends auth_basic {
}
/**
- * [public function]
- *
- * Remove user from a group
+ * Remove user from a group [public function]
*
* @param $user user that leaves a group
* @param $group group to leave
@@ -312,20 +318,10 @@ class auth_mysql extends auth_basic {
function leaveGroup($user, $group) {
$rc = false;
- if($this->_openDB()) {
+ if ($this->_openDB()) {
$this->_lockTables("WRITE");
-
$uid = $this->_getUserID($user);
- if ($uid) {
- $gid = $this->_getGroupID($group);
- if ($gid) {
- $sql = str_replace('%{uid}', addslashes($uid),$this->cnf['delUserGroup']);
- $sql = str_replace('%{user}', addslashes($user),$sql);
- $sql = str_replace('%{gid}', addslashes($gid),$sql);
- $sql = str_replace('%{group}',addslashes($group),$sql);
- $rc = $this->_modifyDB($sql) == 0 ? true : false;
- }
- }
+ $rc = $this->_delUserFromGroup($uid, $group);
$this->_unlockTables();
$this->_closeDB();
}
@@ -333,54 +329,77 @@ class auth_mysql extends auth_basic {
}
/**
- * Adds a user to a group. If $force is set to '1' the group will be
- * created if it not already existed.
+ * Adds a user to a group.
+ *
+ * If $force is set to '1' non existing groups would be created.
*
* The database connection must already be established. Otherwise
* this function does nothing and returns 'false'. It is strongly
* recommended to call this function only after all participating
* tables (group and usergroup) have been locked.
*
- * @param $user user to add to a group
+ * @param $uid user id to add to a group
* @param $group name of the group
* @param $force '1' create missing groups
* @return bool 'true' on success, 'false' on error
*
* @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
*/
- function _addUserToGroup($user, $group, $force=0) {
+ function _addUserToGroup($uid, $group, $force=0) {
$newgroup = 0;
- if($this->dbcon) {
- $uid = $this->_getUserID($user);
- if ($uid) {
- $gid = $this->_getGroupID($group);
- if (!$gid) {
- if ($force) { // create missing groups
- $sql = str_replace('%{group}',addslashes($group),$this->cnf['addGroup']);
- $gid = $this->_modifyDB($sql);
- $newgroup = 1; // group newly created
- }
- if (!$gid) return false; // group didn't exist and can't be created
+ if (($this->dbcon) && ($uid)) {
+ $gid = $this->_getGroupID($group);
+ if (!$gid) {
+ if ($force) { // create missing groups
+ $sql = str_replace('%{group}',addslashes($group),$this->cnf['addGroup']);
+ $gid = $this->_modifyDB($sql);
+ $newgroup = 1; // group newly created
}
+ if (!$gid) return false; // group didn't exist and can't be created
+ }
- $sql = str_replace('%{uid}', addslashes($uid),$this->cnf['addUserGroup']);
- $sql = str_replace('%{user}', addslashes($user),$sql);
- $sql = str_replace('%{gid}', addslashes($gid),$sql);
- $sql = str_replace('%{group}',addslashes($group),$sql);
- if ($this->_modifyDB($sql) !== false) return true;
+ $sql = str_replace('%{uid}', addslashes($uid),$this->cnf['addUserGroup']);
+ $sql = str_replace('%{user}', addslashes($user),$sql);
+ $sql = str_replace('%{gid}', addslashes($gid),$sql);
+ $sql = str_replace('%{group}',addslashes($group),$sql);
+ if ($this->_modifyDB($sql) !== false) return true;
- if ($newgroup) { // remove previously created group on error
- $sql = str_replace('%{gid}', addslashes($gid),$this->cnf['delGroup']);
- $sql = str_replace('%{group}',addslashes($group),$sql);
- $this->_modifyDB($sql);
- }
+ if ($newgroup) { // remove previously created group on error
+ $sql = str_replace('%{gid}', addslashes($gid),$this->cnf['delGroup']);
+ $sql = str_replace('%{group}',addslashes($group),$sql);
+ $this->_modifyDB($sql);
}
}
return false;
}
/**
+ * Remove user from a group
+ *
+ * @param $uid user id that leaves a group
+ * @param $group group to leave
+ * @return bool true on success, false on error
+ *
+ * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
+ */
+ function _delUserFromGroup($uid, $group) {
+ $rc = false;
+
+ if (($this->dbcon) && ($uid)) {
+ $gid = $this->_getGroupID($group);
+ if ($gid) {
+ $sql = str_replace('%{uid}', addslashes($uid),$this->cnf['delUserGroup']);
+ $sql = str_replace('%{user}', addslashes($user),$sql);
+ $sql = str_replace('%{gid}', addslashes($gid),$sql);
+ $sql = str_replace('%{group}',addslashes($group),$sql);
+ $rc = $this->_modifyDB($sql) == 0 ? true : false;
+ }
+ }
+ return $rc;
+ }
+
+ /**
* Retrieves a list of groups the user is a member off.
*
* The database connection must already be established
@@ -458,7 +477,8 @@ class auth_mysql extends auth_basic {
if ($uid) {
foreach($grps as $group) {
- $gid = $this->_addUserToGroup($user, $group, 1);
+ $uid = $this->_getUserID($user);
+ $gid = $this->_addUserToGroup($uid, $group, 1);
if ($gid === false) break;
}
@@ -470,9 +490,8 @@ class auth_mysql extends auth_basic {
* is not a big issue so we ignore this problem here.
*/
$this->_delUser($user);
- $text = str_replace('%{user}',addslashes($user),$this->cnf['joinGroupFailed']);
- $text = str_replace('%{group}',addslashes($group),$text);
- msg($text, -1);
+ if ($this->cnf['debug'])
+ msg ("MySQL err: Adding user '$user' to group '$group' failed.",-1);
}
}
}
@@ -531,6 +550,65 @@ class auth_mysql extends auth_basic {
}
/**
+ * Updates the user info in the database
+ *
+ * Update a user data structure in the database according changes
+ * given in an array. The user name can only be changes if it didn't
+ * exists already. If the new user name exists the update procedure
+ * will be aborted. The database keeps unchanged.
+ *
+ * The database connection has already to be established for this
+ * function to work. Otherwise it will return 'false'.
+ *
+ * The password will be crypted if necessary.
+ *
+ * @param $changes array of items to change as pairs of item and value
+ * @param $uid user id of dataset to change, must be unique in DB
+ * @return true on success or false on error
+ *
+ * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
+ */
+ function _updateUserInfo($changes, $uid) {
+ $sql = $this->cnf['updateUser']." ";
+ $cnt = 0;
+ $err = 0;
+
+ if($this->dbcon) {
+ foreach ($changes as $item => $value) {
+ if ($item == 'user') {
+ if (($this->_getUserID($changes['user']))) {
+ $err = 1; /* new username already exists */
+ break; /* abort update */
+ }
+ if ($cnt++ > 0) $sql .= ", ";
+ $sql .= str_replace('%{user}',$value,$this->cnf['UpdateLogin']);
+ } else if ($item == 'name') {
+ if ($cnt++ > 0) $sql .= ", ";
+ $sql .= str_replace('%{name}',$value,$this->cnf['UpdateName']);
+ } else if ($item == 'pass') {
+ if (!$this->cnf['encryptPass'])
+ $value = auth_cryptPassword($value);
+ if ($cnt++ > 0) $sql .= ", ";
+ $sql .= str_replace('%{pass}',$value,$this->cnf['UpdatePass']);
+ } else if ($item == 'mail') {
+ if ($cnt++ > 0) $sql .= ", ";
+ $sql .= str_replace('%{email}',$value,$this->cnf['UpdateEmail']);
+ }
+ }
+
+ if ($err == 0) {
+ if ($cnt > 0) {
+ $sql .= " ".str_replace('%{uid}', $uid, $this->cnf['UpdateTarget']);
+ $sql .= " LIMIT 1";
+ $this->_modifyDB($sql);
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Retrieves the group id of a given group name
*
* The database connection must already be established
@@ -561,24 +639,25 @@ class auth_mysql extends auth_basic {
* @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
*/
function _openDB() {
- global $lang;
-
if (!$this->dbcon) {
$con = @mysql_connect ($this->cnf['server'], $this->cnf['user'], $this->cnf['password']);
if ($con) {
if ((mysql_select_db($this->cnf['database'], $con))) {
+ if ((preg_match("/^(\d+)\.(\d+)\.(\d+).*/", mysql_get_server_info ($con), $result)) == 1) {
+ $this->dbver = $result[1];
+ $this->dbrev = $result[2];
+ $this->dbsub = $result[3];
+ }
$this->dbcon = $con;
- return true; // connection and database sucessfully opened
+ return true; // connection and database successfully opened
} else {
- $text = str_replace('%d',addslashes($this->cnf['database']),$lang['noDatabase']);
- msg($text, -1);
mysql_close ($con);
+ if ($this->cnf['debug'])
+ msg("MySQL err: No access to database {$this->cnf['database']}.", -1);
}
- } else {
- $text = str_replace('%u',addslashes($this->cnf['user']),$lang['noConnect']);
- $text = str_replace('%s',addslashes($this->cnf['server']),$text);
- msg($text, -1);
- }
+ } else if ($this->cnf['debug'])
+ msg ("MySQL err: Connection to {$this->cnf['user']}@{$this->cnf['server']} not possible.", -1);
+
return false; // connection failed
}
return true; // connection already open
@@ -617,7 +696,8 @@ class auth_mysql extends auth_basic {
mysql_free_result ($result);
return $resultarray;
}
- msg('MySQL: '.mysql_error($this->dbcon), -1);
+ if ($this->cnf['debug'])
+ msg('MySQL err: '.mysql_error($this->dbcon), -1);
}
return false;
}
@@ -640,7 +720,8 @@ class auth_mysql extends auth_basic {
$rc = mysql_insert_id($this->dbcon); //give back ID on insert
if ($rc !== false) return $rc;
}
- msg('MySQL: '.mysql_error($this->dbcon), -1);
+ if ($this->cnf['debug'])
+ msg('MySQL err: '.mysql_error($this->dbcon), -1);
}
return false;
}
@@ -741,7 +822,8 @@ class auth_mysql extends auth_basic {
return $sql;
}
-
+
+
}
//Setup VIM: ex: et ts=2 enc=utf-8 :