* @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'); function getGroups($username) { $groupdata = file($GLOBALS['davconfig']['group.file']); $retval = array(); foreach ($groupdata as $line) { $colonpos = strpos($line, ":"); if ($colonpos > 0) { $groupname = trim(substr($line, 0, $colonpos - 1)); $users = explode(" ", substr($line, $colonpos + 1)); foreach ($users as $user) { if (trim($user) == $username) { array_push($retval, $groupname); } } } } return $retval; } /** * Gets XML encoded data for a user. * * @param int $uid user id * @return XML string */ function getUserData($uid) { if (!(is_numeric($uid) && array_key_exists($uid, $GLOBALS['namemap']))) { errorAsXml(sprintf(_("Invalid user id %s"), $uid)); } $row = $GLOBALS['namemap'][$uid]; $groups = getGroups($row['username']); $retval = sprintf('%d%s%s%s%s0', $uid, $row['username'], $row['firstname'], $row['lastname'], implode(", ", $groups)); 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('%d', $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; } function createDigest($username, $realm, $password) { return sprintf("%s:%s:%s", $username, $realm, md5(sprintf("%s:%s:%s", $username, $realm, $password))); } /** * 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"); $smarty->assign("users", $namemap); $smarty->display("users.html"); } ?>