Location: PHPKode > projects > Aukyla Platform > plugins/Frontends/AdminFrontend.php
<?php
/*
     AdminFrontend.php, an Admin Frontend for performing administrative tasks.
     Copyright (C) 2005 Arend van Beelen, Auton Rijnsburg

     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.,
     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

     For any questions, comments or whatever, you may mail me at: hide@address.com
*/

require_once('Config.php');
require_once('Decoration.php');
require_once('Forms.php');
require_once('Frontend.php');
require_once('GUI.php');
require_once('JavaScript.php');
require_once('Locale.php');
require_once('Login.php');
require_once('Menus.php');
require_once('Messages.php');
require_once('Navigation.php');
require_once('Output.php');
require_once('String.php');

/**
 * @brief The Admin Frontend
 */
class AdminFrontend implements Frontend
{
	public function buildGUI()
	{
		$this->modifyBaseUrl();

		Locale::init('plugins/Frontends', Locale::language());

		$this->mainWindow = $mainWindow = new MainWindow(i18n('Aukyla Administration Area'));
		new Box($mainWindow, 'logo');

		$menu = new Menu($mainWindow, 'mainmenu');
		$autonEntry = new MenuEntry($menu, i18n('Auton'));
		$autonEntry->setLink('http://www.auton.nl/');
		$autonEntry->setCssClass('home');

		$menu = new Menu($mainWindow, 'submenu');
		new MenuHead($menu, i18n('Main Menu'));
		$homeEntry = new MenuEntry($menu, i18n('Back'));
		$homeEntry->setLink($this->originalBaseURL);
		if(String::startsWith(Login::username(), 'anonymous'))
		{
			$loginEntry = new MenuEntry($menu, i18n('Login'));
			$loginEntry->setLink(Config::globals('baseURL').'?view=Login');
		}
		else
		{
			$logoutEntry = new MenuEntry($menu, i18n('Logout'));
			$logoutEntry->setLink(Config::globals('baseURL').'?action=Logout');
		}

		$main = new Box($mainWindow, 'main');

		new MessagesWidget($main);

		// reset the view if the user clicked a cancel button
		if(Config::request('button') == i18n('Cancel'))
		{
			Config::unsetRequest('view');
			Config::unsetRequest('action');
			Config::unsetRequest('button');
		}

		$this->handleActions($main);

		$this->showView($main);
	}

	private function modifyBaseUrl()
	{
		$this->originalBaseURL = Config::globals('baseURL');
		if(String::startsWith(Config::globals('secureBaseURL'), 'https://'))
		{
			Config::setGlobal('baseURL',       "https://{$_SERVER['HTTP_HOST']}/admin.php");
			Config::setGlobal('secureBaseURL', "https://{$_SERVER['HTTP_HOST']}/admin.php");
		}
		else
		{
			Config::setGlobal('baseURL',       "http://{$_SERVER['HTTP_HOST']}/admin.php");
			Config::setGlobal('secureBaseURL', "http://{$_SERVER['HTTP_HOST']}/admin.php");
		}
	}

	private function handleActions(Container $parent)
	{
		$action = Config::request('action');
		if($action != '' && $action != 'Login')
		{
			if(Login::isMemberOf('admin') == false)
			{
				new Paragraph($parent, i18n('You do not have access to the Aukyla Administration Area.'));
				return;
			}

			if($action == 'DeleteUser' || $action == 'DeleteGroup')
			{
				if(Config::request('userDeleteButton')  != i18n('Delete User(s)') &&
				   Config::request('groupDeleteButton') != i18n('Delete Group(s)'))
				{
					$action = '';
					Config::unsetRequest('action');
				}
				else
				{
					Config::unsetRequest('view');
				}
			}

			$config = new Config();
			$configChanged = false;
			switch($action)
			{
				case 'SaveDefaults':
					$config->setVariable('language',       Config::request('language', 'en'));
					$config->setVariable('theme',          Config::request('theme', 'default'));
					$config->setVariable('useDecorations', Config::request('useDecorations') == 'true' ? 'true' : 'false');
					$configChanged = true;
					break;

				case 'SaveServer';
					$config->setVariable('loginMethod',    Config::request('loginMethod', 'passwd'));
					$config->setVariable('output',         Config::request('output', 'XHTML'));
					$config->setVariable('serverSideXSLT', Config::request('serverSideXSLT') == 'true' ? 'true' : 'false');
					$configChanged = true;
					break;

				case 'AddUser':
					$this->addUser();
					break;

				case 'EditUser':
				case 'DeleteUser':
					$this->updateUser();
					break;

				case 'AddGroup':
					$this->addGroup();
					break;

				case 'EditGroup':
				case 'DeleteGroup':
					$this->updateGroup();
					break;
			}
			if($configChanged == true)
			{
				$config->saveConfiguration();
				Messages::confirm(i18n('Configuration saved.'));

				global $Config;
				$Config->readConfiguration();
				$this->modifyBaseUrl();
			}
		}
	}

	private function addUser()
	{
		if(Config::request('newPassword') == Config::request('newPasswordConfirm'))
		{
			$password = Config::request('newPassword');
		}
		else
		{
			Messages::error(i18n('Passwords don\'t match.'));
			return;
		}
		$username = Config::request('newUsername');
		$fullName = Config::request('newFullName');
		$userMail = Config::request('newUserMail');
		$ipRange = Config::request('newIpRange');
		$cryptedPassword = crypt($password);

		$output = "$username:$fullName:$userMail:$cryptedPassword";
		if($ipRange != '')
		{
			$output .= ":$ipRange";
		}
		$output .= "\n";

		$this->writePasswdFile($output, true);

		$this->updateUserGroups();

		Messages::confirm('User added.');
	}

	private function updateUser()
	{
		if(($lines = file(AUKYLA_DIR.'/config/passwd')) === false)
		{
			die('Could not open passwd file!');
		}

		switch(Config::request('action'))
		{
			case 'EditUser':
				if(Config::request('newPassword') == Config::request('newPasswordConfirm'))
				{
					$newPassword = Config::request('newPassword');
				}
				else
				{
					Messages::error(i18n('Passwords didn\'t match.'));
					return;
				}
				$oldUsername = Config::request('oldUsername');
				$newUsername = Config::request('newUsername');
				$newFullName = Config::request('newFullName');
				$newUserMail = Config::request('newUserMail');
				$newIpRange = Config::request('newIpRange');
				$newCryptedPassword = crypt($newPassword);
				$deleteUsersArray = array();
				break;

			case 'DeleteUser':
				$newPassword = '';
				$oldUsername = '';
				$newUsername = '';
				$newFullName = '';
				$newUserMail = '';
				$newIpRange = '';
				$newCryptedPassword = '';
				$deleteUsersArray = explode(',', Config::request('deleteItems'));
				break;
		}

		$output = '';
		foreach($lines as $line)
		{
			list($username, $fullName, $userMail, $cryptedPassword) = explode(':', trim($line), 4);
			$ipRange = '';
			if(strchr($cryptedPassword, ':'))
			{
				list($cryptedPassword, $ipRange) = explode(':', $cryptedPassword, 2);
			}

			if(in_array($username, $deleteUsersArray))
			{
				continue;
			}

			if($username == $oldUsername)
			{
				$username = $newUsername;
				$fullName = $newFullName;
				$userMail = $newUserMail;
				$ipRange = $newIpRange;
				if($newPassword != '')
				{
					$cryptedPassword = $newCryptedPassword;
				}
			}

			$output .= "$username:$fullName:$userMail:$cryptedPassword";
			if($ipRange != '')
			{
				$output .= ":$ipRange";
			}
			$output .= "\n";
		}

		$this->writePasswdFile($output);

		$this->updateUserGroups();

		Messages::confirm('User configuration updated.');
	}

	private function updateUserGroups()
	{
		if(($lines = file(AUKYLA_DIR.'/config/group')) === false)
		{
			die('Could not open group file!');
		}

		if(Config::request('action') == 'DeleteUser')
		{
			$oldUsername = explode(',', Config::request('deleteItems'));
		}
		else
		{
			$oldUsername = array(Config::request('oldUsername'));
		}
		$newUsername = Config::request('newUsername');
		$groups = explode(',', Config::request('selectedGroups'));

		$output = '';
		foreach($lines as $line)
		{
			list($group, $users) = explode(':', trim($line), 2);

			$usersArray = explode(',', $users);
			$newUsersArray = array();
			foreach($usersArray as $user)
			{
				if(in_array($user, $oldUsername) == false)
				{
					$newUsersArray[] = $user;
				}
			}
			if(in_array($group, $groups))
			{
				$newUsersArray[] = $newUsername;
			}
			$newUsers = implode(',', $newUsersArray);

			$output .= "$group:$newUsers\n";
		}

		$this->writeGroupFile($output);
	}

	private function addGroup()
	{
		$groupName = Config::request('editItem');
		$output = "$groupName:\n";

		$this->writeGroupFile($output, true);

		Messages::confirm('Group added.');
	}

	private function updateGroup()
	{
		if(($lines = file(AUKYLA_DIR.'/config/group')) === false)
		{
			die('Could not open group file!');
		}

		switch(Config::request('action'))
		{
			case 'EditGroup':
				$groupName = Config::request('groupName');
				$deleteGroupsArray = array();
				break;

			case 'DeleteGroup':
				$groupName = '';
				$deleteGroupsArray = explode(',', Config::request('deleteItems'));
				break;
		}

		$output = '';
		foreach($lines as $line)
		{
			list($group, $users) = explode(':', trim($line), 2);

			if(in_array($group, $deleteGroupsArray))
			{
				continue;
			}

			if($group == $groupName)
			{
				$users = Config::request('selectedUsers');
			}

			$output .= "$group:$users\n";
		}

		$this->writeGroupFile($output);

		Messages::confirm('Group configuration updated.');
	}

	private function writePasswdFile($output, $append = false)
	{
		if(($fp = fopen(AUKYLA_DIR.'/config/passwd', $append ? 'a' : 'w')) === false)
		{
			die('Could not write passwd file!');
		}
		fwrite($fp, $output, strlen($output));
		fclose($fp);
	}

	private function writeGroupFile($output, $append = false)
	{
		if(($fp = fopen(AUKYLA_DIR.'/config/group', $append ? 'a' : 'w')) === false)
		{
			die('Could not write group file!');
		}
		fwrite($fp, $output, strlen($output));
		fclose($fp);
	}

	private function showView(Container $parent)
	{
		$view = Config::request('view');
		switch($view)
		{
			case 'Login':
				new LoginForm($parent);
				break;

			default:
				if(Login::isMemberOf('admin') == false)
				{
					new Paragraph($parent, i18n('You do not have access to the Aukyla Administration Area.'));
					return;
				}

				$tabWidget = new TabWidget($parent, 'adminArea');
				$this->createDefaultsTab($tabWidget);
				$this->createServerTab($tabWidget);
				$this->createUsersAndGroupsTab($tabWidget);
		}
	}

	private function createDefaultsTab(TabWidget $tabWidget)
	{
		if($tabWidget->currentTab() == 'defaults')
		{
			new PageIcon($this->mainWindow, 'base/icons/settings');
		}

		$tab = $tabWidget->addTab('defaults', i18n('Defaults'));
		new Paragraph($tab, i18n('On this page you can configure the default settings for users. Users can override these settings.'));
		$form = new Form($tab, Config::globals('baseURL').'?action=SaveDefaults');
		$form->useGridLayout(true);
		$languageInput = new SelectInput($form, 'language');
		$languageInput->setText(i18n('Language:'));
		$languageInput->setOptions(Locale::availableLanguages());
		$languageInput->setValue(Config::globals('language'));
		$themeInput = new SelectInput($form, 'theme');
		$themeInput->setText(i18n('Theme:'));
		$themeInput->setOptions(Decoration::availableThemes());
		$themeInput->setValue(Config::globals('theme', 'default'));
		$decorationsInput = new CheckboxInput($form, 'useDecorations');
		$decorationsInput->setText(i18n('Show decoration icons.'));
		$decorationsInput->setChecked(Config::globals('useDecorations', 'true') == 'true');
		$button = new Button($form, 'button');
		$button->setValue(i18n('Apply'));
		$button->setConfirm(true);
	}

	private function createServerTab(TabWidget $tabWidget)
	{
		if($tabWidget->currentTab() == 'server')
		{
			new PageIcon($this->mainWindow, 'base/icons/ksysguard');
		}

		$outputMethods = array();
		foreach(glob(AUKYLA_DIR.'/htdocs/resources/base/Output/*.xsl') as $file)
		{
			$method = String::substringBefore(String::substringAfter($file, AUKYLA_DIR.'/htdocs/resources/base/Output/'), '.xsl');
			$outputMethods[$method] = $method;
		}

		$authenticationResources = array();
		foreach(glob(AUKYLA_DIR.'/plugins/LoginHandlers/*_LoginHandler.php') as $file)
		{
			$resource = String::substringBefore(String::substringAfter($file, AUKYLA_DIR.'/plugins/LoginHandlers/'), '_LoginHandler.php');
			$authenticationResources[$resource] = $resource;
		}

		$tab = $tabWidget->addTab('server', i18n('Server'));
		new Paragraph($tab, i18n('On this page you can configure the Aukyla server. Only change these settings if you know what you\'re doing.'));
		$form = new Form($tab, Config::globals('baseURL').'?action=SaveServer');
		$form->useGridLayout(true);
		$authenticationResourceInput = new SelectInput($form, 'loginMethod');
		$authenticationResourceInput->setText(i18n('Authentication resource:'));
		$authenticationResourceInput->setOptions($authenticationResources);
		$authenticationResourceInput->setValue(Config::globals('loginMethod', 'passwd'));
		$outputMethodInput = new SelectInput($form, 'output');
		$outputMethodInput->setText(i18n('Output format:'));
		$outputMethodInput->setOptions($outputMethods);
		$outputMethodInput->setValue(Config::globals('output', 'XHTML'));
		$serverSideXsltInput = new CheckboxInput($form, 'serverSideXSLT');
		$serverSideXsltInput->setText(i18n('Use Server-Side XSLT transformations.'));
		$serverSideXsltInput->setChecked(Config::globals('serverSideXSLT', 'true') == 'true');
		$button = new Button($form, 'button');
		$button->setValue(i18n('Apply'));
		$button->setConfirm(true);
		$paragraph = new Paragraph($form);
		$label = new Label($paragraph, i18n('Warning: '));
		$label->addCssStyle('font-weight: bold');
		new Label($paragraph, i18n('If you insist on using Internet Explorer, you have to select the HTML output format and enable Server-Side XSLT transformations. However, this will put extra load on your server.'));
	}

	private function createUsersAndGroupsTab(TabWidget $tabWidget)
	{
		if(Config::globals('loginMethod', 'passwd') == 'passwd')
		{
			$tab = $tabWidget->addTab('users', i18n('Users and Groups'));

			$view = Config::request('view');
			switch($view)
			{
				case 'EditUser':
					if($tabWidget->currentTab() == 'users')
					{
						new PageIcon($this->mainWindow, 'base/icons/personal');
					}
					$this->createUserDetailsForm($tab);
					break;

				case 'EditGroup':
					if($tabWidget->currentTab() == 'users')
					{
						new PageIcon($this->mainWindow, 'base/icons/groups');
					}
					if(Config::request('groupAddButton') == i18n('Add Group'))
					{
						$this->createNewGroupForm($tab);
					}
					else
					{
						$this->createGroupDetailsForm($tab);
					}
					break;

				default:
					if($tabWidget->currentTab() == 'users')
					{
						new PageIcon($this->mainWindow, 'base/icons/groups');
					}
					$this->createUserGroupOverview($tab);
					break;
			}
		}
	}

	private function createUserDetailsForm($parent)
	{
		if(Config::request('userAddButton') == i18n('Add User'))
		{
			$action = 'AddUser';
			$username = '';
			$fullName = '';
			$userMail = '';
			$ipRange = '';
			$memberGroups = array();
			$new = true;

			new Header($parent, i18n('New User'));
		}
		else
		{
			$action = 'EditUser';
			$username = Config::request('editItem');
			$fullName = Login::fullName($username);
			$userMail = Login::userMail($username);
			$ipRange = Login::ipRange($username);
			$memberGroups = Login::memberGroups($username);
			$new = false;

			new Header($parent, $username);
		}

		$groups = Login::groups();

		new ExternalJavaScript($parent, 'resources/plugins/Frontends/Admin/adminScripts.js');
		new Paragraph($parent, i18n('Please enter some user details.'));
		$form = new Form($parent, Config::globals('baseURL')."?action=$action");
		$form->setErrorMessage(i18n('Please fill in all required fields.'));
		$form->useGridLayout(true);
		$form->addJavaScript('onsubmit', 'updateSelectedGroups();');
		$oldUsernameInput = new HiddenInput($form, 'oldUsername');
		$oldUsernameInput->setValue($username);
		$usernameInput = new TextInput($form, 'newUsername');
		$usernameInput->setText(i18n('Username:'));
		$usernameInput->setValue($username);
		$usernameInput->setRequired(true);
		$fullNameInput = new TextInput($form, 'newFullName');
		$fullNameInput->setText(i18n('Full Name:'));
		$fullNameInput->setValue($fullName);
		$fullNameInput->setRequired(true);
		$passwordInput = new PasswordInput($form, 'newPassword');
		$passwordInput->setText(i18n('Password:'));
		$passwordConfirmInput = new PasswordInput($form, 'newPasswordConfirm');
		$passwordConfirmInput->setText(i18n('Confirm Password:'));
		if($new == true)
		{
			$passwordInput->setRequired(true);
			$passwordConfirmInput->setRequired(true);
		}
		$userMailInput = new TextInput($form, 'newUserMail');
		$userMailInput->setText(i18n('E-mail address:'));
		$userMailInput->setValue($userMail);
		$ipRangeInput = new TextInput($form, 'newIpRange');
		$ipRangeInput->setText(i18n('Allowed IP range:'));
		$ipRangeInput->setValue($ipRange);
		$groupsInput = new SelectInput($form, 'groupsSelect');
		$groupsInput->setMultiple(true, 10);
		$groupsInput->setText(i18n('Groups:'));
		$groupsInput->addCssStyle('width: 15em');
		foreach($groups as $group)
		{
			$groupsInput->addOption($group, $group, in_array($group, $memberGroups));
		}
		$box = new Box($form);
		$box->setOrientation('horizontal');
		$button = new Button($box, 'button');
		$button->setValue(i18n('OK'));
		$button->setConfirm(true);
		$button = new Button($box, 'button');
		$button->setValue(i18n('Cancel'));

		return $form;
	}

	private function createNewGroupForm($parent)
	{
		new Header($parent, i18n('New Group'));

		new Paragraph($parent, i18n('Please enter the name for the group.'));
		$form = new Form($parent, Config::globals('baseURL').'?action=AddGroup&amp;view=EditGroup');
		$form->useGridLayout(true);
		$nameInput = new TextInput($form, 'editItem');
		$nameInput->setText(i18n('Name:'));
		$nameInput->setRequired(true);
		$box = new Box($form);
		$box->setOrientation('horizontal');
		$button = new Button($box, 'button');
		$button->setValue(i18n('OK'));
		$button->setConfirm(true);
		$button = new Button($box, 'button');
		$button->setValue(i18n('Cancel'));

		return $form;
	}

	private function createGroupDetailsForm($parent)
	{
		$group = Config::request('editItem');

		new Header($parent, $group);

		$users = Login::users();
		$memberUsers = Login::usersOfGroup($group);

		new ExternalJavaScript($parent, 'resources/plugins/Frontends/Admin/adminScripts.js');
		new Paragraph($parent, i18n('Select the users which should be a member of this group.'));
		$form = new Form($parent, Config::globals('baseURL').'?action=EditGroup');
		$form->useGridLayout(true);
		$form->addJavaScript('onsubmit', 'updateSelectedUsers();');
		$groupNameInput = new HiddenInput($form, 'groupName');
		$groupNameInput->setValue($group);
		$usersInput = new SelectInput($form, 'usersSelect');
		$usersInput->setMultiple(true, 10);
		$usersInput->setText(i18n('Users:'));
		$usersInput->addCssStyle('width: 15em');
		foreach($users as $user)
		{
			$usersInput->addOption($user, $user, in_array($user, $memberUsers));
		}
		$box = new Box($form);
		$box->setOrientation('horizontal');
		$button = new Button($box, 'button');
		$button->setValue(i18n('OK'));
		$button->setConfirm(true);
		$button = new Button($box, 'button');
		$button->setValue(i18n('Cancel'));

		return $form;
	}

	private function createUserGroupOverview($parent)
	{
		$action = Config::request('action');
		if($action == 'AddUser' || $action == 'EditUser' || $action == 'DeleteUser' ||
		   $action == 'AddGroup' || $action == 'EditGroup' || $action == 'DeleteGroup')
		{
			new JavaScript($parent, 'document.location = \''.Config::globals('baseURL').'\';');
			return;
		}

		$users = array();
		foreach(Login::users() as $user)
		{
			$users[$user] = htmlspecialchars(Login::fullName($user));
		}
		$groups = array_combine(array_values(Login::groups()), array_values(Login::groups()));
		asort($users);
		asort($groups);

		new ExternalJavaScript($parent, 'resources/plugins/Frontends/Admin/adminScripts.js');

		$gridLayout = new GridLayout($parent, 2);
		$gridLayout->addCssStyle('width: 75%');

		$form = new Form($gridLayout, Config::globals('baseURL').'?view=EditUser&amp;action=DeleteUser');
		$form->addCssStyle('width: 50%');
		$paragraph = new Paragraph($form, i18n('Users:'));
		$paragraph->addCssStyle('font-weight: bold');
		$columnLayout = new GridLayout($form, 2);
		$usersInput = new SelectInput($columnLayout, 'usersSelect');
		$usersInput->setMultiple(true, 10);
		$usersInput->setOptions($users);
		$usersInput->addJavaScript('onchange', 'updateButtons(\'user\');');
		$usersInput->addCssStyle('width: 15em');
		$box = new Box($columnLayout);
		$box->setOrientation('vertical');
		$button = new Button($box, 'userAddButton');
		$button->setValue(i18n('Add User'));
		$button->addCssStyle('width: 100%; margin-bottom: 4px');
		$button = new Button($box, 'userEditButton');
		$button->setValue(i18n('Edit User'));
		$button->setEnabled(false);
		$button->addCssStyle('width: 100%; margin-bottom: 4px');
		$button = new Button($box, 'userDeleteButton');
		$button->addJavaScript('onclick', 'return confirmDelete(\'user\');');
		$button->setValue(i18n('Delete User(s)'));
		$button->setEnabled(false);
		$button->addCssStyle('width: 100%');
		$columnLayout->cell(0, 1)->addCssStyle('vertical-align: top');

		$form = new Form($gridLayout, Config::globals('baseURL').'?view=EditGroup&amp;action=DeleteGroup');
		$form->addCssStyle('width: 50%');
		$paragraph = new Paragraph($form, i18n('Groups:'));
		$paragraph->addCssStyle('font-weight: bold');
		$columnLayout = new GridLayout($form, 2);
		$groupsInput = new SelectInput($columnLayout, 'groupsSelect');
		$groupsInput->setMultiple(true, 10);
		$groupsInput->setOptions($groups);
		$groupsInput->addJavaScript('onchange', 'updateButtons(\'group\');');
		$groupsInput->addCssStyle('width: 15em');
		$box = new Box($columnLayout);
		$box->setOrientation('vertical');
		$button = new Button($box, 'groupAddButton');
		$button->setValue(i18n('Add Group'));
		$button->addCssStyle('width: 100%; margin-bottom: 4px');
		$button = new Button($box, 'groupEditButton');
		$button->setValue(i18n('Edit Group'));
		$button->setEnabled(false);
		$button->addCssStyle('width: 100%; margin-bottom: 4px');
		$button = new Button($box, 'groupDeleteButton');
		$button->addJavaScript('onclick', 'return confirmDelete(\'group\');');
		$button->setValue(i18n('Delete Group(s)'));
		$button->setEnabled(false);
		$button->addCssStyle('width: 100%');
		$columnLayout->cell(0, 1)->addCssStyle('vertical-align: top');

		return $gridLayout;
	}

	public function showGUI()
	{
		$this->mainWindow->show();
	}

	private $mainWindow;
	private $originalBaseURL;
}

?>
Return current item: Aukyla Platform