317 lines
10 KiB
PHP
317 lines
10 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* User administration code.
|
||
|
*
|
||
|
* @author Jan Dittberner <jan@dittberner.info>
|
||
|
* @version $Id$
|
||
|
* @license GPL
|
||
|
* @package WebDAVAdmin
|
||
|
*
|
||
|
* Copyright (c) 2007 Jan Dittberner
|
||
|
*
|
||
|
* This file is part of WebDAVAdmin.
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU General Public License as
|
||
|
* published by the Free Software Foundation; either version 2 of the
|
||
|
* License, or (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful, but
|
||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, write to the Free Software
|
||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||
|
* 02110-1301 USA.
|
||
|
*/
|
||
|
|
||
|
/** Include common code. */
|
||
|
include_once('common.inc.php');
|
||
|
|
||
|
/**
|
||
|
* Gets XML encoded data for a user.
|
||
|
*
|
||
|
* @param int $uid user id
|
||
|
* @return XML string
|
||
|
*/
|
||
|
function getUserData($uid) {
|
||
|
if (!is_numeric($uid)) {
|
||
|
errorAsXml(sprintf(_("Invalid user id %s"), $uid));
|
||
|
}
|
||
|
try {
|
||
|
$currentuser = $_SERVER['PHP_AUTH_USER'];
|
||
|
|
||
|
$dbh = new PDO($GLOBALS['dsn'], $GLOBALS['dbuser'], $GLOBALS['dbpass']);
|
||
|
$sth = $dbh->prepare("SELECT groupname FROM dav_group, dav_password WHERE dav_group.username=dav_password.username AND dav_password.uid=:uid");
|
||
|
if (!$sth->execute(array(':uid' => $uid))) {
|
||
|
statementErrorAsXml($sth);
|
||
|
}
|
||
|
$groups = array();
|
||
|
while ($grouprow = $sth->fetch(PDO::FETCH_ASSOC)) {
|
||
|
array_push($groups, $grouprow['groupname']);
|
||
|
}
|
||
|
$sth = $dbh->prepare("SELECT username, firstname, lastname FROM dav_password WHERE uid=:uid");
|
||
|
if (!$sth->execute(array(':uid' => $uid))) {
|
||
|
statementErrorAsXml($sth);
|
||
|
}
|
||
|
$row = $sth->fetch(PDO::FETCH_ASSOC);
|
||
|
$retval = sprintf('<?xml version="1.0" encoding="utf8"?><userdata><uid>%d</uid><username>%s</username><firstname>%s</firstname><lastname>%s</lastname><groups>%s</groups><loggedin>%d</loggedin></userdata>',
|
||
|
$uid, $row['username'], $row['firstname'],
|
||
|
$row['lastname'], implode(", ", $groups),
|
||
|
($currentuser == $row['username']) ? 1 : 0);
|
||
|
$dbh = null;
|
||
|
} catch (PDOException $e) {
|
||
|
errorAsXml($e->getMessage());
|
||
|
}
|
||
|
header("Content-Type: text/xml; charset=UTF-8");
|
||
|
return $retval;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets XML encoded data for a deleted user.
|
||
|
*
|
||
|
* @param int $uid user id
|
||
|
* @return XML string
|
||
|
*/
|
||
|
function getDeletedUserData($uid) {
|
||
|
if (!is_numeric($uid)) {
|
||
|
errorAsXml(sprintf(_("Invalid user id %s"), $uid));
|
||
|
}
|
||
|
return sprintf('<?xml version="1.0" encoding="utf8"?><userdata><uid>%d</uid></userdata>', $uid);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Validates the given user data array for correctness.
|
||
|
*
|
||
|
* @param array &$userdata reference to an user data array
|
||
|
* @param boolean $forinsert if this is true the check skips field
|
||
|
* that will be created during insert
|
||
|
* @return an array with validation error messages or an empty array
|
||
|
*/
|
||
|
function validateUserData(&$userdata, $forinsert) {
|
||
|
$errormsgs = array();
|
||
|
// normalize the user data array
|
||
|
foreach ($userdata as $key => $value) {
|
||
|
$userdata[$key] = trim($value);
|
||
|
}
|
||
|
if (!$forinsert) {
|
||
|
if (!is_numeric($userdata['uid'])) {
|
||
|
array_push($errormsgs, _("Uid must be numeric."));
|
||
|
}
|
||
|
if (!empty($userdata['password']) && strlen($userdata['password']) < 8) {
|
||
|
array_push($errormsgs, _("Password must be at least 8 characters long."));
|
||
|
}
|
||
|
} else {
|
||
|
if (!preg_match('/^[a-zA-Z0-9]{2,}$/', $userdata['username'])) {
|
||
|
array_push($errormsgs, _("Username must be at least 2 characters long and must contain letters and digits only."));
|
||
|
}
|
||
|
if (empty($userdata['password']) || strlen($userdata['password']) < 8) {
|
||
|
array_push($errormsgs, _("Password must be at least 8 characters long."));
|
||
|
}
|
||
|
}
|
||
|
if (empty($userdata['firstname'])) {
|
||
|
$userdata['firstname'] = null;
|
||
|
}
|
||
|
if (empty($userdata['lastname'])) {
|
||
|
$userdata['lastname'] = null;
|
||
|
}
|
||
|
if (!preg_match('/^([0-9a-zA-z]+[,\s]*)+$/', $userdata['groups'])) {
|
||
|
array_push($errormsgs, _('Groups must be a list of group names separated by commas. Group names must consist of letters and digits.'));
|
||
|
}
|
||
|
return $errormsgs;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Updates the data of a user in the database.
|
||
|
*
|
||
|
* @param array &$userdata reference to a user data array
|
||
|
*/
|
||
|
function updateUser(&$userdata) {
|
||
|
$validation = validateUserData($userdata, false);
|
||
|
if (!empty($validation)) {
|
||
|
errorAsXml(implode("\n", $validation));
|
||
|
}
|
||
|
try {
|
||
|
$dbh = new PDO($GLOBALS['dsn'], $GLOBALS['dbuser'], $GLOBALS['dbpass']);
|
||
|
$dbh->beginTransaction();
|
||
|
if ($userdata['password']) {
|
||
|
$sth = $dbh->prepare("UPDATE dav_password SET firstname=:firstname, lastname=:lastname, password=md5(:password) WHERE uid=:uid");
|
||
|
if (!$sth->execute(array(':firstname' => $userdata['firstname'],
|
||
|
':lastname' => $userdata['lastname'],
|
||
|
':password' => $userdata['password'],
|
||
|
':uid' => $userdata['uid']))) {
|
||
|
$dbh->rollback();
|
||
|
statementErrorAsXml($sth);
|
||
|
}
|
||
|
} else {
|
||
|
$sth = $dbh->prepare("UPDATE dav_password SET firstname=:firstname, lastname=:lastname WHERE uid=:uid");
|
||
|
if (!$sth->execute(array(':firstname' => $userdata['firstname'],
|
||
|
':lastname' => $userdata['lastname'],
|
||
|
':uid' => $userdata['uid']))) {
|
||
|
$dbh->rollback();
|
||
|
statementErrorAsXml($sth);
|
||
|
}
|
||
|
}
|
||
|
if ($userdata['groups']) {
|
||
|
$groups = array();
|
||
|
$sth = $dbh->prepare("DELETE FROM dav_group WHERE username=:username");
|
||
|
if (!$sth->execute(array(':username' => $userdata['username']))) {
|
||
|
$dbh->rollback();
|
||
|
statementErrorAsXml($sth);
|
||
|
}
|
||
|
$sth = $dbh->prepare("INSERT INTO dav_group (username, groupname) VALUES (:username, :groupname)");
|
||
|
foreach (explode(",", $userdata['groups']) as $group) {
|
||
|
$group = trim($group);
|
||
|
if (!in_array($group, $groups)) {
|
||
|
array_push($groups, $group);
|
||
|
if (!$sth->execute(array(':username' => $userdata['username'],
|
||
|
':groupname' => $group))) {
|
||
|
$dbh->rollback();
|
||
|
statementErrorAsXml($sth);
|
||
|
}
|
||
|
$sth->closeCursor();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
$dbh->commit();
|
||
|
$dbh = null;
|
||
|
} catch (PDOException $e) {
|
||
|
errorAsXml($e->getMessage());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Inserts a new user and its group assignments into the database.
|
||
|
*
|
||
|
* @param array &$userdata reference to an user data array
|
||
|
*/
|
||
|
function insertUser(&$userdata) {
|
||
|
$validation = validateUserData($userdata, true);
|
||
|
if (!empty($validation)) {
|
||
|
errorAsXml(implode("\n", $validation));
|
||
|
}
|
||
|
try {
|
||
|
$dbh = new PDO($GLOBALS['dsn'], $GLOBALS['dbuser'], $GLOBALS['dbpass']);
|
||
|
$dbh->beginTransaction();
|
||
|
$sth = $dbh->prepare("INSERT INTO dav_password (username, firstname, lastname, password) VALUES (:username, :firstname, :lastname, md5(:password))");
|
||
|
if (!$sth->execute(array(':username' => $userdata['username'],
|
||
|
':firstname' => $userdata['firstname'],
|
||
|
':lastname' => $userdata['lastname'],
|
||
|
':password' => $userdata['password']))) {
|
||
|
$dbh->rollback();
|
||
|
statementErrorAsXml($sth);
|
||
|
}
|
||
|
$uid = $dbh->lastInsertId('dav_password_uid_seq');
|
||
|
$groups = array();
|
||
|
$sth = $dbh->prepare("INSERT INTO dav_group (username, groupname) VALUES (:username, :groupname)");
|
||
|
foreach (split(",", $userdata['groups']) as $group) {
|
||
|
$group = trim($group);
|
||
|
if (!in_array($group, $groups)) {
|
||
|
array_push($groups, $group);
|
||
|
if (!$sth->execute(array(':username' => $userdata['username'],
|
||
|
':groupname' => $group))) {
|
||
|
$dbh->rollback();
|
||
|
statementErrorAsXml($sth);
|
||
|
}
|
||
|
$sth->closeCursor();
|
||
|
}
|
||
|
}
|
||
|
$dbh->commit();
|
||
|
$dbh = null;
|
||
|
} catch (PDOException $e) {
|
||
|
errorAsXml($e->getMessage);
|
||
|
}
|
||
|
return $uid;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Delete the user with the given user id and its group assignments
|
||
|
* from the database.
|
||
|
*
|
||
|
* @param int $uid user id
|
||
|
*/
|
||
|
function deleteUser($uid) {
|
||
|
if (!is_numeric($uid)) {
|
||
|
errorAsXml(sprintf(_("Invalid user id %s"), $uid));
|
||
|
}
|
||
|
try {
|
||
|
$dbh = new PDO($GLOBALS['dsn'], $GLOBALS['dbuser'], $GLOBALS['dbpass']);
|
||
|
$dbh->beginTransaction();
|
||
|
$query = $dbh->prepare("DELETE FROM dav_group WHERE username IN (SELECT username FROM dav_password WHERE uid=:uid)");
|
||
|
if (!$query->execute(array(':uid' => $uid))) {
|
||
|
$dbh->rollback();
|
||
|
statementErrorAsXml($query);
|
||
|
}
|
||
|
$query = $dbh->prepare("DELETE FROM dav_password WHERE uid=:uid");
|
||
|
if (!$query->execute(array(':uid' => $uid))) {
|
||
|
$dbh->rollback();
|
||
|
statementErrorAsXml($query);
|
||
|
}
|
||
|
$dbh->commit();
|
||
|
$dbh = null;
|
||
|
} catch (PDOException $e) {
|
||
|
errorAsXml($e->getMessage());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($_GET) {
|
||
|
if ($_GET['method']) {
|
||
|
switch ($_GET['method']) {
|
||
|
case 'getuserdata':
|
||
|
if ($_GET['uid']) {
|
||
|
print getUserData($_GET['uid']);
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
errorAsXml(sprintf(_("Unexpected values %s!"), serialize($_GET)));
|
||
|
}
|
||
|
} else {
|
||
|
invalidCall();
|
||
|
}
|
||
|
} elseif ($_POST) {
|
||
|
if ($_POST['method']) {
|
||
|
switch ($_POST['method']) {
|
||
|
case 'submituser':
|
||
|
if ($_POST['uid']) {
|
||
|
updateUser($_POST);
|
||
|
print getUserData($_POST['uid']);
|
||
|
} else {
|
||
|
print getUserData(insertUser($_POST));
|
||
|
}
|
||
|
break;
|
||
|
case 'deleteuser':
|
||
|
if ($_POST['uid']) {
|
||
|
deleteUser($_POST['uid']);
|
||
|
print getDeletedUserData($_POST['uid']);
|
||
|
} else {
|
||
|
errorAsXml(sprintf(_("Unexpected values %s!"), serialize($_POST)));
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
errorAsXml(sprintf(_("Unexpected values %s!"), serialize($_POST)));
|
||
|
}
|
||
|
} else {
|
||
|
invalidCall();
|
||
|
}
|
||
|
} else {
|
||
|
$currentuser = $_SERVER['PHP_AUTH_USER'];
|
||
|
|
||
|
header("Content-Type: text/html; charset=UTF-8");
|
||
|
try {
|
||
|
$dbh = new PDO($dsn, $dbuser, $dbpass);
|
||
|
$query = $dbh->prepare("SELECT uid, username, firstname, lastname FROM dav_password ORDER BY username");
|
||
|
$query->execute();
|
||
|
$rows = $query->fetchall(PDO::FETCH_ASSOC);
|
||
|
foreach ($rows as $key => $value) {
|
||
|
$value['loggedin'] = ($value['username'] == $currentuser);
|
||
|
$rows[$key] = $value;
|
||
|
}
|
||
|
$smarty->assign("users", $rows);
|
||
|
$smarty->display("users.html");
|
||
|
} catch (PDOException $e) {
|
||
|
errorAsHtml($e->getMessage());
|
||
|
}
|
||
|
}
|
||
|
?>
|