* Copyright 2001-2012 Strangecode, LLC
*
* This file is part of The Strangecode Codebase.
*
* The Strangecode Codebase 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 3 of the License, or (at your option)
* any later version.
*
* The Strangecode Codebase 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
* The Strangecode Codebase. If not, see .
*/
/**
* admins.php
*/
// require_once dirname(__FILE__) . '/_config.inc.php';
$auth->requireLogin();
require_once 'codebase/lib/PageNumbers.inc.php';
require_once 'codebase/lib/Cache.inc.php';
require_once 'codebase/lib/FormValidator.inc.php';
require_once 'codebase/lib/SortOrder.inc.php';
require_once 'codebase/lib/HTML.inc.php';
require_once 'codebase/lib/Prefs.inc.php';
require_once 'codebase/lib/Lock.inc.php';
require_once 'codebase/lib/Version.inc.php';
/********************************************************************
* CONFIG
********************************************************************/
// Titles and navigation header.
$nav->add(_("Administrators"), null);
$nav->set('id', 'admins');
// The object to validate form input.
$fv = new FormValidator();
// Configure the prefs object.
$tmp_prefs = new Prefs('admins');
$tmp_prefs->setParam(array('persistent' => false));
// Configure the cache object.
$cache =& Cache::getInstance('admins');
$cache->setParam(array('enabled' => false)); // Better leave disabled; the list gets out of sync with the db otherwise, somehow.
// Instantiate a sorting object with the default sort and order. Add SQL for each column.
$so = new SortOrder('admin_id', 'DESC');
$so->setColumn('admin_id', $auth->getParam('db_primary_key') . ' ASC', $auth->getParam('db_primary_key') . ' DESC');
$so->setColumn('username', $auth->getParam('db_username_column') . ' ASC', $auth->getParam('db_username_column') . ' DESC');
$so->setColumn('userpass', $auth->getParam('db_table') . '.userpass ASC', $auth->getParam('db_table') . '.userpass DESC');
$so->setColumn('first_name', $auth->getParam('db_table') . '.first_name ASC', $auth->getParam('db_table') . '.first_name DESC');
$so->setColumn('last_name', $auth->getParam('db_table') . '.last_name ASC', $auth->getParam('db_table') . '.last_name DESC');
$so->setColumn('email', $auth->getParam('db_table') . '.email ASC', $auth->getParam('db_table') . '.email DESC');
$so->setColumn('seconds_online', $auth->getParam('db_table') . '.seconds_online ASC', $auth->getParam('db_table') . '.seconds_online DESC');
$so->setColumn('last_login_datetime', $auth->getParam('db_table') . '.last_login_datetime ASC', $auth->getParam('db_table') . '.last_login_datetime DESC');
$so->setColumn('last_access_datetime', $auth->getParam('db_table') . '.last_access_datetime ASC', $auth->getParam('db_table') . '.last_access_datetime DESC');
$so->setColumn('last_login_ip', $auth->getParam('db_table') . '.last_login_ip ASC', $auth->getParam('db_table') . '.last_login_ip DESC');
$so->setColumn('added_by_user_id', $auth->getParam('db_table') . '.added_by_user_id ASC', $auth->getParam('db_table') . '.added_by_user_id DESC');
$so->setColumn('modified_by_user_id', $auth->getParam('db_table') . '.modified_by_user_id ASC', $auth->getParam('db_table') . '.modified_by_user_id DESC');
$so->setColumn('added_datetime', $auth->getParam('db_table') . '.added_datetime ASC', $auth->getParam('db_table') . '.added_datetime DESC');
$so->setColumn('modified_datetime', $auth->getParam('db_table') . '.modified_datetime ASC', $auth->getParam('db_table') . '.modified_datetime DESC');
// Instantiate page numbers. Total items are set and calculation is done in the getRecordList function.
$page = new PageNumbers();
$page->setPerPage(getFormData('per_page'), 50);
$page->setPageNumber(getFormData('page_number', (getFormData('sort') ? 1 : null)));
// Query parameters to retain only locally.
$locally_carried_queries = array(
'search_query',
'break_list_cache' => $app->validBoomerangURL('accounts'),
);
/********************************************************************
* MAIN
********************************************************************/
// We may want to use the add/edit interface from another script, so this
// allows us to remember which page we came from so we can go back there.
if (getFormData('boomerang', false) && isset($_SERVER['HTTP_REFERER'])) {
$app->setBoomerangURL($_SERVER['HTTP_REFERER'], 'admins');
}
if (getFormData('break_list_cache', false)) {
// Remove any stale cached list data.
$cache->delete('list');
}
// What action to take.
switch (getFormData('op')) {
case 'add' :
// Initialize variables for the form template.
$frm =& addRecordForm();
$nav->add(_("Add Administrator"));
$main_template = 'admin_form.ihtml';
break;
case 'edit' :
// Initialize variables for the form template.
$frm =& editRecordForm(getFormData('admin_id'));
$nav->add(_("Edit Administrator"));
$main_template = 'admin_form.ihtml';
break;
case 'del' :
deleteRecord(getFormData('admin_id'));
if ($app->validBoomerangURL('admins')) {
// Display boomerang page.
$app->dieBoomerangURL('admins', $locally_carried_queries);
}
// Display default page.
$app->dieURL($_SERVER['PHP_SELF'], $locally_carried_queries);
break;
case 'insert' :
if (getFormdata('btn_cancel', false)) {
if ($app->validBoomerangURL('admins')) {
// Display boomerang page.
$app->dieBoomerangURL('admins', $locally_carried_queries);
}
// Display default page.
$app->dieURL($_SERVER['PHP_SELF'], $locally_carried_queries);
}
validateInput();
if ($fv->anyErrors()) {
$frm =& addRecordForm();
$frm = array_merge($frm, getFormData());
$nav->add(_("Add Administrator"));
$main_template = 'admin_form.ihtml';
} else {
$admin_id = insertRecord(getFormData());
if (getFormdata('btn_repeat', false)) {
// Display function again.
$app->dieURL($_SERVER['PHP_SELF'] . '?op=add', $locally_carried_queries);
} else if ($app->validBoomerangURL('admins')) {
// Display boomerang page.
$app->dieBoomerangURL('admins', $locally_carried_queries);
}
// Display default page.
$app->dieURL($_SERVER['PHP_SELF'], $locally_carried_queries);
}
break;
case 'update' :
if (getFormdata('btn_reset', false)) {
$app->raiseMsg(_("Saved values have been reloaded."), MSG_NOTICE, __FILE__, __LINE__);
$app->dieURL($_SERVER['PHP_SELF'] . '?op=edit&admin_id=' . getFormData('admin_id'), $locally_carried_queries);
}
if (getFormdata('btn_cancel', false)) {
// Remove lock
$lock->select($auth->getParam('db_table'), $auth->getParam('db_primary_key'), getFormData('admin_id'));
$lock->remove();
if ($app->validBoomerangURL('admins')) {
// Display boomerang page.
$app->dieBoomerangURL('admins', $locally_carried_queries);
}
// Display default page.
$app->dieURL($_SERVER['PHP_SELF'], $locally_carried_queries);
}
validateInput();
if ($fv->anyErrors()) {
$frm =& editRecordForm(getFormData('admin_id'));
$frm = array_merge($frm, getFormData());
$nav->add(_("Edit Administrator"));
$main_template = 'admin_form.ihtml';
} else {
updateRecord(getFormData());
if (getFormdata('btn_repeat', false)) {
// Display edit function with next available ID.
$qid = $db->query("SELECT " . $auth->getParam('db_primary_key') . " FROM " . $auth->getParam('db_table') . " WHERE " . $auth->getParam('db_primary_key') . " > '" . $db->escapeString(getFormData('admin_id')) . "' ORDER BY " . $auth->getParam('db_primary_key') . " ASC LIMIT 1");
if (list($next_id) = mysql_fetch_row($qid)) {
$app->dieURL($_SERVER['PHP_SELF'] . '?op=edit&admin_id=' . $next_id, $locally_carried_queries);
} else {
$app->raiseMsg(_("Cannot edit next, the end of the list was reached"), MSG_NOTICE, __FILE__, __LINE__);
}
} else if ($app->validBoomerangURL('admins')) {
// Display boomerang page.
$app->dieBoomerangURL('admins', $locally_carried_queries);
}
// Display default page.
$app->dieURL($_SERVER['PHP_SELF'], $locally_carried_queries);
}
break;
default :
$list =& getRecordList();
$main_template = 'admin_list.ihtml';
break;
}
/******************************************************************************
* TEMPLATE INITIALIZATION
*****************************************************************************/
$nav->set('id', 'admins');
include 'header.' . $app->getParam('template_ext');
$app->carryQuery($locally_carried_queries);
include 'codebase/services/templates/' . $main_template;
include 'footer.' . $app->getParam('template_ext');
/********************************************************************
* FUNCTIONS
********************************************************************/
function validateInput()
{
global $fv, $auth;
// If the username was changed during edit, verify.
if (((getFormData('username') != getFormData('old_username')) && 'update' == getFormData('op'))
|| 'insert' == getFormData('op')) {
if ($auth->usernameExists(getFormData('username'))) {
$fv->addError('username', sprintf(_("The username %s already exists. Please choose another."), getFormData('username')));
}
}
$fv->numericRange('admin_id', 0, 32767, _("Admin ID must be a valid number between 0 and 32767."));
$fv->isEmpty('username', _("Username cannot be blank."));
$fv->stringLength('username', 0, 255, _("Username must contain less than 256 characters."));
if ('insert' == getFormData('op')) {
$fv->isEmpty('userpass', _("Password cannot be blank."));
}
if ('insert' == getFormData('op') || ('update' == getFormData('op') && strlen(getFormData('userpass')) > 0)) {
$fv->stringLength('userpass', 8, 100, _("Password must be between 8 and 100 characters long."));
}
$fv->stringLength('first_name', 0, 255, _("First name must contain less than 256 characters."));
$fv->stringLength('last_name', 0, 255, _("Last name must contain less than 256 characters."));
$fv->isEmpty('email', _("Email cannot be blank."));
$fv->validateEmail('email');
}
function &addRecordForm()
{
// Set default values for the reset of the fields.
$frm = array(
'admin_id' => '',
'old_username' => '',
'username' => '',
'userpass' => '',
'first_name' => '',
'last_name' => '',
'email' => '',
'seconds_online' => '0',
'last_login_datetime' => '',
'last_access_datetime' => '',
'last_login_ip' => '0.0.0.0',
'added_by_user_id' => '',
'modified_by_user_id' => '',
'added_datetime' => '',
'modified_datetime' => '',
'new_op' => 'insert',
'user_type' => '',
'submit_buttons' => array(
array('name' => 'btn_submit', 'value' => _("Add Administrator"), 'accesskey' => 's'),
array('name' => 'btn_repeat', 'class' => 'secondary', 'value' => _("Add & repeat"), 'accesskey' => 'r'),
array('name' => 'btn_cancel', 'class' => 'secondary', 'value' => _("Cancel"), 'accesskey' => 'c'),
),
);
return $frm;
}
function &editRecordForm($id)
{
global $auth;
global $lock;
global $locally_carried_queries;
$app =& App::getInstance();
$db =& DB::getInstance();
$lock->select($auth->getParam('db_table'), $auth->getParam('db_primary_key'), $id);
if ($lock->isLocked() && !$lock->isMine()) {
$lock->dieErrorPage();
}
// Get the information for the form.
$qid = $db->query("
SELECT *,
" . $auth->getParam('db_primary_key') . " AS admin_id
FROM " . $auth->getParam('db_table') . "
WHERE " . $auth->getParam('db_primary_key') . " = '" . $db->escapeString($id) . "'
");
if (!$frm = mysql_fetch_assoc($qid)) {
$app->logMsg('Could not find record with admin_id: ' . $id, LOG_WARNING, __FILE__, __LINE__);
$app->raiseMsg(sprintf(_("The requested user %s could not be found."), $id), MSG_ERR, __FILE__, __LINE__);
$app->dieBoomerangURL('admins', $locally_carried_queries);
}
// Lock this record.
$lock->set($auth->getParam('db_table'), $auth->getParam('db_primary_key'), $id, $frm['username']);
// Set misc values for the form.
$frm = array_merge(array(
'admin_id' => '',
'old_username' => $frm['username'],
'username' => '',
'userpass' => '',
'first_name' => '',
'last_name' => '',
'email' => '',
'seconds_online' => '0',
'last_login_datetime' => '',
'last_access_datetime' => '',
'last_login_ip' => '',
'added_by_user_id' => '',
'modified_by_user_id' => '',
'added_datetime' => '',
'modified_datetime' => '',
'new_op' => 'update',
'old_username' => $frm['username'],
'submit_buttons' => array(
array('name' => 'btn_submit', 'value' => _("Save changes"), 'accesskey' => 's'),
array('name' => 'btn_repeat', 'class' => 'secondary', 'value' => _("Save & edit next"), 'accesskey' => 'e'),
array('name' => 'btn_reset', 'class' => 'secondary', 'value' => _("Reset"), 'accesskey' => 'r'),
array('name' => 'btn_cancel', 'class' => 'secondary', 'value' => _("Cancel"), 'accesskey' => 'c'),
),
), $frm);
return $frm;
}
function deleteRecord($id)
{
global $auth;
global $lock;
global $cache;
global $locally_carried_queries;
$app =& App::getInstance();
$db =& DB::getInstance();
$lock->select($auth->getParam('db_table'), $auth->getParam('db_primary_key'), $id);
if ($lock->isLocked() && !$lock->isMine()) {
$lock->dieErrorPage();
}
// Remove any stale cached list data.
$cache->delete('list');
// Get the information for this object.
$qid = $db->query("
SELECT " . $auth->getParam('db_username_column') . "
FROM " . $auth->getParam('db_table') . "
WHERE " . $auth->getParam('db_primary_key') . " = '" . $db->escapeString($id) . "'
");
if (! list($name) = mysql_fetch_row($qid)) {
$app->logMsg('Could not find record with admin_id: ' . $id, LOG_WARNING, __FILE__, __LINE__);
$app->raiseMsg(sprintf(_("The requested user %s could not be found."), $id), MSG_ERR, __FILE__, __LINE__);
$app->dieBoomerangURL('admins', $locally_carried_queries);
}
// Get the information for this object.
$qid = $db->query("SELECT COUNT(*) from " . $auth->getParam('db_table') . "");
list($num_admins) = mysql_fetch_row($qid);
if ($num_admins <= 1) {
// There must always be at least one administrator!
$app->raiseMsg(_("You cannot delete the only user in the database. There must be at least one to log in and create other users."), MSG_NOTICE, __FILE__, __LINE__);
} else if ($auth->get('user_id') == $id) {
// Do not delete yourself!
$app->raiseMsg(_("You cannot delete yourself."), MSG_NOTICE, __FILE__, __LINE__);
} else {
// Delete the record.
$db->query("DELETE FROM " . $auth->getParam('db_table') . " WHERE " . $auth->getParam('db_primary_key') . " = '" . $db->escapeString($id) . "'");
$app->raiseMsg(sprintf(_("The admin %s has been deleted."), $name), MSG_SUCCESS, __FILE__, __LINE__);
}
// Unlock record.
$lock->remove();
}
function insertRecord($frm)
{
global $auth;
global $cache;
$app =& App::getInstance();
$db =& DB::getInstance();
// Remove any stale cached list data.
$cache->delete('list');
// Insert record data.
$db->query("
INSERT INTO " . $auth->getParam('db_table') . " (
" . $auth->getParam('db_username_column') . ",
first_name,
last_name,
email,
added_by_user_id,
added_datetime
) VALUES (
'" . $db->escapeString($frm['username']) . "',
'" . $db->escapeString($frm['first_name']) . "',
'" . $db->escapeString($frm['last_name']) . "',
'" . $db->escapeString($frm['email']) . "',
'" . $db->escapeString($auth->get('user_id')) . "',
NOW()
)
");
$last_insert_id = mysql_insert_id($db->getDBH());
// Set admin password.
$auth->setPassword($last_insert_id, $frm['userpass']);
// Create version.
$version = Version::getInstance($auth);
$version->create($auth->getParam('db_table'), $auth->getParam('db_primary_key'), $last_insert_id, $frm['username']);
$app->raiseMsg(sprintf(_("The user %s has been added."), $frm['username']), MSG_SUCCESS, __FILE__, __LINE__);
return $last_insert_id;
}
function updateRecord($frm)
{
global $auth;
global $lock;
global $cache;
$app =& App::getInstance();
$db =& DB::getInstance();
$lock->select($auth->getParam('db_table'), $auth->getParam('db_primary_key'), $frm['admin_id']);
if ($lock->isLocked() && !$lock->isMine()) {
$lock->dieErrorPage();
}
// Remove any stale cached list data.
$cache->delete('list');
// If the userpass is left blank or with the filler **** characters, we don't want to update it.
if (!empty($frm['userpass']) && !preg_match('/[\*]{4,}/', $frm['userpass'])) {
// Set user password.
$auth->setPassword($frm['admin_id'], $frm['userpass']);
}
// Update record data.
$db->query("
UPDATE " . $auth->getParam('db_table') . " SET
" . $auth->getParam('db_username_column') . " = '" . $db->escapeString($frm['username']) . "',
first_name = '" . $db->escapeString($frm['first_name']) . "',
last_name = '" . $db->escapeString($frm['last_name']) . "',
email = '" . $db->escapeString($frm['email']) . "',
modified_by_user_id = '" . $db->escapeString($auth->get('user_id')) . "',
modified_datetime = NOW()
WHERE " . $auth->getParam('db_primary_key') . " = '" . $db->escapeString($frm['admin_id']) . "'
");
// Create version.
$version = Version::getInstance($auth);
$version->create($auth->getParam('db_table'), $auth->getParam('db_primary_key'), $frm['admin_id'], $frm['username']);
$app->raiseMsg(sprintf(_("The user %s has been updated."), $frm['username']), MSG_SUCCESS, __FILE__, __LINE__);
// Unlock record.
$lock->remove();
}
function &getRecordList()
{
global $page;
global $so;
global $tmp_prefs;
global $cache;
global $auth;
$db =& DB::getInstance();
$where_clause = '';
// Build search query if available.
if (getFormData('search_query', false)) {
$qry_words = preg_split('/[^\w]/', getFormData('search_query'));
for ($i=0; $igetParam('db_table') . "." . $auth->getParam('db_username_column') . " LIKE '%" . $db->escapeString($qry_words[$i]) . "%'
OR " . $auth->getParam('db_table') . ".first_name LIKE '%" . $db->escapeString($qry_words[$i]) . "%'
OR " . $auth->getParam('db_table') . ".last_name LIKE '%" . $db->escapeString($qry_words[$i]) . "%'
OR " . $auth->getParam('db_table') . ".email LIKE '%" . $db->escapeString($qry_words[$i]) . "%'
)
";
}
}
if (getFormData('filter_user_type', false)) {
// Limit by filter.
$where_clause .= (empty($where_clause) ? 'WHERE' : 'AND') . " " . $auth->getParam('db_table') . ".user_type = '" . $db->escapeString(getFormData('filter_user_type')) . "'";
}
// Count the total number of records so we can do something about the page numbers.
$qid = $db->query("
SELECT COUNT(*)
FROM " . $auth->getParam('db_table') . "
$where_clause
");
list($num_results) = mysql_fetch_row($qid);
// Set page numbers now we know (needed for next step).
$page->setTotalItems($num_results);
$page->calculate();
// Final SQL, with sort and page limiters.
$sql = "
SELECT
" . $auth->getParam('db_table') . ".*,
" . $auth->getParam('db_table') . "." . $auth->getParam('db_primary_key') . " AS admin_id,
a1." . $auth->getParam('db_username_column') . " AS added_admin_username,
a2." . $auth->getParam('db_username_column') . " AS modified_admin_username
FROM " . $auth->getParam('db_table') . "
LEFT JOIN " . $auth->getParam('db_table') . " a1 ON (" . $auth->getParam('db_table') . ".added_by_user_id = a1." . $auth->getParam('db_primary_key') . ")
LEFT JOIN " . $auth->getParam('db_table') . " a2 ON (" . $auth->getParam('db_table') . ".modified_by_user_id = a2." . $auth->getParam('db_primary_key') . ")
$where_clause
" . $so->getSortOrderSQL() . "
" . $page->getLimitSQL() . "
";
// Use a cache hash to determine if the result-set has changed.
// A unique key for this query, with the total_items in case db records
// were added since the last cache. This identifies a unique set of
// cached data, but we must refer to the list that is cached by a more
// generic name. so that we can flush the cache (if records updated)
// without knowing the hash.
$cache_hash = md5($sql . '|' . $page->total_items);
if ($tmp_prefs->get('cache_hash') != $cache_hash) {
$cache->delete('list');
$tmp_prefs->set('cache_hash', $cache_hash);
}
// First try to return from the cache.
if ($cache->exists('list')) {
return $cache->get('list');
}
// The list was not cached, so issue the real query.
$qid = $db->query($sql);
$list = array();
while ($row = mysql_fetch_assoc($qid)) {
$list[] = $row;
}
// Save this list into the cache.
if (isset($list) && !empty($list)) {
$cache->set('list', $list);
}
return $list;
}