Location: PHPKode > projects > UseBB > UseBB/sources/functions_admin.php
<?php

/*
	Copyright (C) 2003-2012 UseBB Team
	http://www.usebb.net
	
	$Id$
	
	This file is part of UseBB.
	
	UseBB 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.
	
	UseBB 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 UseBB; if not, write to the Free Software
	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

/**
 * ACP functions
 *
 * Contains the admin_functions class with functions for the ACP. This file can only be included when being admin.
 *
 * @author	UseBB Team
 * @link	http://www.usebb.net
 * @license	GPL-2
 * @version	$Revision$
 * @copyright	Copyright (C) 2003-2012 UseBB Team
 * @package	UseBB
 * @subpackage Core
 */

//
// Die when called directly in browser
//
if ( !defined('INCLUDED') )
	exit();

//
// Security check
//
if ( !defined('IS_INSTALLER') && $functions->get_user_level() < LEVEL_ADMIN )
	trigger_error('You can not load the admin functions class while the user is not an admin!', E_USER_ERROR);

/**
 * ACP functions
 *
 * Functions only usable in the ACP.
 *
 * @author	UseBB Team
 * @link	http://www.usebb.net
 * @license	GPL-2
 * @version	$Revision$
 * @copyright	Copyright (C) 2003-2012 UseBB Team
 * @package	UseBB
 * @subpackage Core
 */
class admin_functions {
	
	/**
	 * @var array Contains the ACP menu structure
	 */
	var $acp = array(
		'main' => array(
			'index',
			'version',
			'config',
			'logout'
		),
		'forums' => array(
			'categories',
			'forums',
		),
		'members' => array(
			'members',
			'activate_members',
			'register_members',
			'delete_members',
		),
		'pruning' => array(
			'prune_forums',
			'prune_members',
		),
		'security' => array(
			'bans',
			'dnsbl',
			'badwords',
		),
		'various' => array(
			'mass_email',
			'iplookup',
			'sqltoolbox',
			'modules',
		),
	);
	/**
	 * @var array Contains information about available ACP modules
	 */
	var $acp_modules = array();
	/**
	 * @var array Contains filenames of available ACP modules.
	 */
	var $acp_modules_files = array();
	/**
	 * @access private
	 */
	var $all_forums;
	
	/**
	 * Loads available ACP modules and fills $acp_modules(_files)
	 */
	function admin_functions() {
		
		global $functions;
		global $lang;
		
		//
		// Load ACP modules
		//
		$modules_dir = ROOT_PATH.'sources/modules/';
		if ( $functions->get_config('enable_acp_modules') && file_exists($modules_dir) && is_dir($modules_dir) ) {
			
			$handle = opendir($modules_dir);
			
			while ( false !== ( $module_name = readdir($handle) ) ) {
				
				$usebb_module_info = $this->check_module($module_name);
				
				//
				// If valid module and not exist yet
				//
				if ( is_array($usebb_module_info) && !array_key_exists($usebb_module_info['short_name'], $this->acp_modules) ) {
					
					//
					// Eventually create a new category
					//
					if ( !array_key_exists($usebb_module_info['acp_category'], $this->acp) ) {
						
						$this->acp[$usebb_module_info['acp_category']] = array();
						$lang['Category-'.$usebb_module_info['acp_category']] = $usebb_module_info['new_acp_category_long_name'];
						
					}
					
					//
					// Add the filename and save to module list and menu
					//
					$usebb_module_info['filename'] = $module_name;
					$this->acp_modules_files[] = $module_name;
					$this->acp_modules[$usebb_module_info['short_name']] = $usebb_module_info;
					$this->acp[$usebb_module_info['acp_category']][] = 'mod_'.$usebb_module_info['short_name'];
					
				}
				
			}
			
			closedir($handle);
			
		}
		
	}
	
	/**
	 * Read a remote URL into string
	 *
	 * @param string $url URL
	 * @returns string Contents
	 */
	function read_remote_file($url) {

		global $functions;

		return $functions->read_url($url);
		
	}
	
	/**
	 * Check if a .php file is a valid UseBB ACP module
	 *
	 * @param string $module_name Module filename
	 * @param string $actual_module_name Actual module filename (not checked on extension)
	 * @returns mixed Array with module info or false when module is invalid
	 */
	function check_module($module_name, $actual_module_name='') {
		
		if ( substr($module_name, -4) == '.php' ) {
			
			$module_name = ( !empty($actual_module_name) ) ? $actual_module_name : ROOT_PATH.'sources/modules/'.$module_name;
			
			ob_start();
			require($module_name);
			ob_end_clean();
			
			//
			// Valid information returned?
			//
			if ( isset($usebb_module_info) && is_array($usebb_module_info) && !empty($usebb_module_info['acp_category']) && ( array_key_exists($usebb_module_info['acp_category'], $this->acp) || !empty($usebb_module_info['new_acp_category_long_name']) ) && !empty($usebb_module_info['short_name']) && !empty($usebb_module_info['long_name']) ) {
				
				//
				// This is a valid module, return module info
				//
				return $usebb_module_info;
				
			} else {
				
				//
				// No UseBB module info found
				//
				return false;
				
			}
			
		} else {
			
			//
			// Not a .php file
			//
			return false;
			
		}
		
	}
	
	/**
	 * Run a UseBB module
	 *
	 * @param string $module_name Module short name
	 */
	function run_module($module_name) {
		
		global $lang;

		if ( !empty($this->acp_modules[$module_name]['min_version']) && version_compare(USEBB_VERSION, $this->acp_modules[$module_name]['min_version'], '<') )
			return $this->create_body('mod_'.$module_name, '<p><strong>'.sprintf($lang['RunningACPModuleMinVersion'], $this->acp_modules[$module_name]['min_version']).'</strong></p>');
		
		//
		// Load the module
		//
		define('RUN_MODULE', true);
		ob_start();
		require(ROOT_PATH.'sources/modules/'.$this->acp_modules[$module_name]['filename']);
		ob_end_clean();
		
		//
		// Able to run?
		//
		$content = ( isset($usebb_module) && is_object($usebb_module) && method_exists($usebb_module, 'run_module') ) ? $usebb_module->run_module() : '<p><strong>'.$lang['RunningBadACPModule'].'</strong></p>';
		
		$this->create_body('mod_'.$module_name, $content);
		
	}
	
	/**
	 * Create the ACP menu
	 *
	 * @param string $location Current ACP location
	 * @returns string HTML ACP menu
	 */
	function create_acp_menu($location) {
		
		global $functions, $lang;
		
		$out = '<ul>';
		foreach ( $this->acp as $category_name => $category ) {
			
			$out .= '<li>'.$lang['Category-'.$category_name].'<ul>';
			foreach ( $this->acp[$category_name] as $item ) {
				
				$selected = ( $location == $item ) ? ' class="selected"' : '';
				$use_token = ( $item == 'logout' );
				$name = ( preg_match('#^mod_([A-Za-z0-9\-_\.]+)$#', $item, $module_name) ) ? $this->acp_modules[$module_name[1]]['long_name'] : $lang['Item-'.$item];
				$out .= '<li'.$selected.'><a href="'.$functions->make_url('admin.php', array('act' => $item), true, true, false, $use_token).'">'.$name.'</a></li>';
				
			}
			$out .= '</ul></li>';
			
		}
		$out .= '</ul>';
		
		return $out;
		
	}
	
	/**
	 * Create the admin body
	 *
	 * @param string $location Current ACP location
	 * @param string $content ACP HTML content
	 */
	function create_body($location, $content) {
		
		global $functions, $template, $lang;
		
		if ( empty($content) )
			$functions->redirect('admin.php');
		
		$name = ( preg_match('#^mod_([A-Za-z0-9\-_\.]+)$#', $location, $module_name) ) ? $this->acp_modules[$module_name[1]]['long_name'] : $lang['Item-'.$location];
		
		$template->add_breadcrumb($lang['ACP'], array('admin.php'));
		if ( $location != 'index' )
			$template->add_breadcrumb($name);
		
		$template->parse('main', 'admin', array(
			'admin_menu' => $this->create_acp_menu($location),
			'admin_title' => $name,
			'admin_content' => $content
		));
		
		if ( strpos($content, '<form') !== false ) {
			
			//
			// Count input fields, disable logout for large forms
			//
			$count = substr_count($content, '<input') + substr_count($content, '<select') + substr_count($content, '<textarea');
			if ( $count >= 7 )
				$this->disable_logout();

		}
		
	}
	
	/**
	 * Transform a variable into legal PHP code using var_export().
	 *
	 * @param mixed $variable Variable to transform to PHP
	 * @returns string PHP code
	 */
	function make_php_string($variable) {
		
		return str_replace("\n", '', var_export($variable, true));
			
	}
	
	/**
	 * Set forum configuration
	 *
	 * @param array $settings Array containing forum settings to change
	 */
	function set_config($settings) {
		
		global $functions;
		
		if ( !is_array($settings) || !count($settings) )
			return;
		
		$config_file = ROOT_PATH.'config.php';
		
		//
		// Get the contents of config.php
		//
		$fp = fopen($config_file, 'r');
		$config_content = fread($fp, filesize($config_file));
		fclose($fp);
		
		//
		// Adjust values
		//
		foreach ( $settings as $key => $val ) {
			
			$variable = ( in_array($key, array('type', 'server', 'username', 'passwd', 'dbname', 'prefix', 'persistent')) ) ? 'dbs' : 'conf';
			
			if ( in_array($key, $functions->board_config_defined) )
				$config_content = preg_replace('#(\s)?\$'.$variable."\['".$key."'\] = .+;#", '\\1\$'.$variable."['".$key."'] = ".$this->make_php_string($val).';', $config_content);
			else
				$config_content = preg_replace('#(\s*?)?\?>#', "\n\$".$variable."['".$key."'] = ".$this->make_php_string($val).";\\1?>", $config_content);
			
		}
		
		if ( !is_writable(ROOT_PATH.'config.php') ) {
			
			//
			// Make config.php downloadable
			//
			ob_end_clean(); // get rid of gzip output buffers
			header('Content-Type: application/x-httpd-php');
			header('Content-disposition: attachment; filename="config.php"');
			die($config_content);
			
		} else {
			
			//
			// Write the new contents
			//
			$fp = fopen($config_file, 'w');
			fwrite($fp, $config_content);
			fclose($fp);
			
		}
		
	}
	
	/**
	 * Make a forum select box
	 *
	 * @param string $input_name HTML <select /> name attribute
	 * @param bool $multiple Allow multiple selections
	 * @param array $filter_ids Array containing forum ID's to exclude
	 * @param string $add HTML to add as last elements in <select />
	 * @returns string HTML <select />
	 */
	function forum_select_box($input_name, $multiple=true, $filter_ids=array(), $add='') {
		
		global $db;
		
		if ( !is_array($this->all_forums) ) {
			
			$result = $db->query("SELECT c.id AS cat_id, c.name AS cat_name, f.id, f.name FROM ".TABLE_PREFIX."cats c, ".TABLE_PREFIX."forums f WHERE c.id = f.cat_id ORDER BY c.sort_id ASC, c.name ASC, f.sort_id ASC, f.name ASC");
			$this->all_forums = array();
			while ( $forumdata = $db->fetch_result($result) )
				$this->all_forums[] = $forumdata;
			
		}
		
		$forums_input = '';
		$seen_cats = array();
		$items = 0;
		
		if ( !empty($_POST[$input_name]) ) {
			
			$_POST[$input_name] = ( $multiple ) ? $_POST[$input_name] : array($_POST[$input_name]);
			
		} else {
			
			$_POST[$input_name] = array();
			
		}
		
		$_POST[$input_name] = ( isset($_POST[$input_name]) && is_array($_POST[$input_name]) ) ? $_POST[$input_name] : array();
		foreach ( $this->all_forums as $forumdata ) {
			
			if ( is_array($filter_ids) && in_array($forumdata['id'], $filter_ids) )
				continue;
			
			if ( !in_array($forumdata['cat_id'], $seen_cats) ) {
				
				$forums_input .= ( !count($seen_cats) ) ? '' : '</optgroup>';
				$forums_input .= '<optgroup label="'.unhtml(stripslashes($forumdata['cat_name'])).'">';
				$seen_cats[] = $forumdata['cat_id'];
				$items++;
				
			}
			
			$selected = ( in_array($forumdata['id'], $_POST[$input_name]) ) ? ' selected="selected"' : '';
			$forums_input .= '<option value="'.$forumdata['id'].'"'.$selected.'>'.unhtml(stripslashes($forumdata['name'])).'</option>';
			$items++;
			
		}
		$forums_input .= '</optgroup>'.$add;

		if ( $multiple )
			return '<select name="'.$input_name.'[]" size="'.$items.'" multiple="multiple">'.$forums_input.'</select>';
		else
			return '<select name="'.$input_name.'">'.$forums_input.'</select>';
		
	}
	
	/**
	 * Cleanly delete forums
	 *
	 * @param string $condition SQL condition to match forums
	 * @param bool $change_stats Change the global statistics
	 */
	function delete_forums($condition, $change_stats=true) {
		
		global $functions, $db;
		
		//
		// Get the forum ID's and counts
		//
		$result = $db->query("SELECT id, topics, posts FROM ".TABLE_PREFIX."forums WHERE ".$condition);
		$forum_ids = array();
		$topics = $posts = 0;
		while ( $forumdata = $db->fetch_result($result) ) {
			
			$forum_ids[] = $forumdata['id'];
			$topics = $topics + $forumdata['topics'];
			$posts = $posts + $forumdata['posts'];
			
		}
		
		if ( count($forum_ids) == 0 )
			return;
			
		//
		// Delete the forums
		//
		$db->query("DELETE FROM ".TABLE_PREFIX."forums WHERE id IN(".join(', ', $forum_ids).")");
		
		//
		// Delete the posts and topic subscriptions
		//
		$result = $db->query("SELECT id FROM ".TABLE_PREFIX."topics WHERE forum_id IN(".join(', ', $forum_ids).")");
		while ( $topicdata = $db->fetch_result($result) ) {
			
			$db->query("DELETE FROM ".TABLE_PREFIX."posts WHERE topic_id = ".$topicdata['id']);
			$db->query("DELETE FROM ".TABLE_PREFIX."subscriptions WHERE topic_id = ".$topicdata['id']);
			
		}
		
		//
		// Delete the topics
		//
		$db->query("DELETE FROM ".TABLE_PREFIX."topics WHERE forum_id IN(".join(', ', $forum_ids).")");
		
		//
		// Update the stats
		//
		if ( $change_stats ) {
			
			$functions->set_stats('topics', - $topics, true);
			$functions->set_stats('posts', - $posts, true);
			
		}
		
		//
		// Reload moderator perms
		//
		$this->reload_moderator_perms();
		
	}

	/**
	 * Cleanly delete members
	 *
	 * @param string $condition SQL condition to match members
	 * @param bool $delete_posts Delete posts, or assign to guest
	 * @param bool $ban_email Ban associated email addresses
	 * @returns int Member count
	 */
	function delete_members($condition, $delete_posts=false, $ban_email=false) {

		global $db, $functions;
		
		$fields = array('id');
		if ( !$delete_posts )
			$fields[] = 'name';
		if ( $ban_email )
			$fields[] = 'email';

		$result = $db->query("SELECT ".implode(',', $fields)." FROM ".TABLE_PREFIX."members WHERE ".$condition);
		$users = array();
		while ( $userdata = $db->fetch_result($result) ) {
			
			$users[$userdata['id']] = array(
				isset($userdata['name'])  ? $userdata['name']  : '', 
				isset($userdata['email']) ? $userdata['email'] : ''
			);

		}

		$count = count($users);
		
		if ( $count == 0 )
			return;
		
		$user_ids = implode(',', array_keys($users));

		if ( $delete_posts ) {
			
			//
			// Delete the posts
			// This is a tiresome process since there is no ORM or API in 1.0.
			// A small one could have been added, but since this code was added
			// after the closing of 1.0 development it is faster this way.
			// It is unlikely this code will have to be edited a lot. 
			//
			
			$topics = $posts = 0;
			$topic_replies = $topic_firsts = $topic_lasts = $delete_topics = array();
			
			// 1. Delete post entries
			$result = $db->query("SELECT t.id AS topic_id, t.count_replies, t.first_post_id, t.last_post_id, p.id AS post_id FROM ".TABLE_PREFIX."posts p, ".TABLE_PREFIX."topics t WHERE t.id = p.topic_id AND p.poster_id IN(".$user_ids.")");
			while ( $data = $db->fetch_result($result) ) {
				
				// Calculate the remanining replies in the end
				if ( !array_key_exists($data['topic_id'], $topic_replies) )
					$topic_replies[$data['topic_id']] = $data['count_replies']-1;
				else
					$topic_replies[$data['topic_id']]--;
				
				// Collect topics with to reset first/last ID
				if ( $data['first_post_id'] == $data['post_id'] )
					$topic_firsts[] = $data['topic_id'];
				if ( $data['last_post_id']  == $data['post_id'] )
					$topic_lasts[]  = $data['topic_id'];

			}
			$db->query("DELETE FROM ".TABLE_PREFIX."posts WHERE poster_id IN(".$user_ids.")");
			
			// 2. Delete topic entries with no replies
			foreach ( $topic_replies as $topic => $replies ) {
				
				// Collect empty topics
				if ( $replies < 0 ) # Smaller than zero, because 0 = no replies but one post
					$delete_topics[] = $topic;
				
			}
			if ( count($delete_topics) > 0 ) {
				
				$db->query("DELETE FROM ".TABLE_PREFIX."topics WHERE id IN(".implode(',', $delete_topics).")");
				$db->query("DELETE FROM ".TABLE_PREFIX."subscriptions WHERE topic_id IN(".implode(',', $delete_topics).")");
				
			}

			// 3. Adjust topic first and last post IDs
			$topic_firsts = array_diff($topic_firsts, $delete_topics);
			$topic_lasts  = array_diff($topic_lasts,  $delete_topics);
			foreach ( $topic_firsts as $topic ) {
				
				// Get the first ASC
				$result = $db->query("SELECT id FROM ".TABLE_PREFIX."posts WHERE topic_id = ".$topic." ORDER BY id ASC LIMIT 1");
				$data = $db->fetch_result($result);
				$db->query("UPDATE ".TABLE_PREFIX."topics SET first_post_id = ".$data['id']." WHERE id = ".$topic);	
			}
			foreach ( $topic_lasts as $topic ) {
				
				// Get the first DESC
				$result = $db->query("SELECT id FROM ".TABLE_PREFIX."posts WHERE topic_id = ".$topic." ORDER BY id DESC LIMIT 1");
				$data = $db->fetch_result($result);
				$db->query("UPDATE ".TABLE_PREFIX."topics SET last_post_id = ".$data['id']." WHERE id = ".$topic);	
			}
			
			// 4. Adjust topic reply counts
			foreach ( $topic_replies as $topic => $replies ) {
				
				if ( in_array($topic, $delete_topics) )
					continue;

				$db->query("UPDATE ".TABLE_PREFIX."topics SET count_replies = ".$replies." WHERE id = ".$topic);

			}
			
			// 5. Adjust forum latest updated topic and counters
			// Simply do this for all forums, or it gets too complicated above
			$result = $db->query("SELECT forum_id, COUNT(id) AS topics, SUM(count_replies) AS replies FROM ".TABLE_PREFIX."topics GROUP BY forum_id");
			while ( $forum = $db->fetch_result($result) ) {
				
				$topics += $forum['topics'];
				$posts += ($forum['topics'] + $forum['replies']); # Because replies does not include the first post

				if ( $forum['topics'] > 0 ) {
					
					// Select last updated topic in forum
					$topicresult = $db->query("SELECT id FROM ".TABLE_PREFIX."topics WHERE forum_id = ".$forum['forum_id']." ORDER BY last_post_id DESC LIMIT 1");
					$topic = $db->fetch_result($topicresult);
					$last_topic_id = $topic['id'];

				} else {
					
					$last_topic_id = 0;

				}
				$db->query("UPDATE ".TABLE_PREFIX."forums SET topics = ".$forum['topics'].", posts = ".($forum['topics'] + $forum['replies']).", last_topic_id = ".$last_topic_id." WHERE id = ".$forum['forum_id']);

			}
			
			// 6. Adjust global stats
			$functions->set_stats('topics', $topics);
			$functions->set_stats('posts', $posts);

			unset($topics, $posts, $topic_replies, $topic_firsts, $topic_lasts, $delete_topics, $data, $forum);
			
		} else {
			
			//
			// Reassign the posts to guest
			//
			foreach ( $users as $id => $vals ) {
				
				list($name, ) = $vals;
				$db->query("UPDATE ".TABLE_PREFIX."posts SET poster_id = 0, poster_guest = '".$name."' WHERE poster_id = ".$id);

			}
			
		}

		//
		// Ban email address
		//
		if ( $ban_email ) {
			
			foreach ( $users as $vals ) {
				
				list(, $email) = $vals;
				$db->query("DELETE FROM ".TABLE_PREFIX."bans WHERE email = '".$email."'");
				$db->query("INSERT INTO ".TABLE_PREFIX."bans VALUES(NULL, '', '".$email."', '')");
				
			}

		}
		
		$db->query("UPDATE ".TABLE_PREFIX."posts SET post_edit_by = 0 WHERE post_edit_by IN(".$user_ids.")");
		$db->query("DELETE FROM ".TABLE_PREFIX."subscriptions WHERE user_id IN(".$user_ids.")");
		$db->query("DELETE FROM ".TABLE_PREFIX."moderators WHERE user_id IN(".$user_ids.")");
		$db->query("DELETE FROM ".TABLE_PREFIX."members WHERE id IN(".$user_ids.")");
		$db->query("DELETE FROM ".TABLE_PREFIX."sessions WHERE user_id IN(".$user_ids.")");

		$functions->set_stats('members', - $count, true);

		return $count;

	}
	
	/**
	 * Reload moderator permissions
	 *
	 * - Deletes moderator entries for unexisting forums
	 * - Set user level for moderators to 2 when set to 1
	 * - Set user level for non-moderators to 1 when set to 2
	 */
	function reload_moderator_perms() {
		
		global $db;
		
		//
		// Get an array of existing forums
		//
		$existing_forums = $this->get_forums_array();
		$existing_forums = array_keys($existing_forums);
		
		if ( count($existing_forums) ) {
			
			//
			// Delete moderator entries from unexisting forums
			//
			$db->query("DELETE FROM ".TABLE_PREFIX."moderators WHERE forum_id NOT IN(".join(', ', $existing_forums).")");
			
			//
			// Get all moderator user ID's
			//
			$result = $db->query("SELECT DISTINCT(user_id) as user_id FROM ".TABLE_PREFIX."moderators");
			$all_moderators = array();
			while ( $modsdata = $db->fetch_result($result) )
				$all_moderators[] = $modsdata['user_id'];
			
			//
			// Set user levels right
			//
			if ( count($all_moderators) ) {
				
				$db->query("UPDATE ".TABLE_PREFIX."members SET level = 2 WHERE level = 1 AND id IN(".join(', ', $all_moderators).")");
				$db->query("UPDATE ".TABLE_PREFIX."members SET level = 1 WHERE level = 2 AND id NOT IN(".join(', ', $all_moderators).")");
				
			} else {
				
				$db->query("UPDATE ".TABLE_PREFIX."members SET level = 1 WHERE level = 2");
				
			}
			
		} else {
			
			//
			// Remove all moderator permissions
			//
			$db->query("DELETE FROM ".TABLE_PREFIX."moderators");
			$db->query("UPDATE ".TABLE_PREFIX."members SET level = 1 WHERE level = 2");
			
		}
		
	}
	
	/**
	 * Get categories
	 *
	 * @returns array Array containing category information
	 */
	function get_cats_array() {
		
		global $db;
		
		$result = $db->query("SELECT * FROM ".TABLE_PREFIX."cats ORDER BY sort_id ASC, name");
		$cats = array();
		while ( $catinfo = $db->fetch_result($result) )
			$cats[$catinfo['id']] = $catinfo;
		
		return $cats;
		
	}
	
	/**
	 * Get forums
	 *
	 * @returns array Array containing forum information
	 */
	function get_forums_array() {
		
		global $db;
		
		$result = $db->query("SELECT f.*, c.id as cat_id, c.name as cat_name FROM ".TABLE_PREFIX."forums f, ".TABLE_PREFIX."cats c WHERE c.id = f.cat_id ORDER BY c.sort_id ASC, c.name ASC, f.sort_id ASC, f.name ASC");
		$forums = array();
		while ( $foruminfo = $db->fetch_result($result) )
			$forums[$foruminfo['id']] = $foruminfo;
		
		return $forums;
		
	}

	/**
	 * Disable automatic logout
	 */
	function disable_logout() {
		
		//
		// This variable is used in admin.php
		//
		$_SESSION['admin_disable_logout'] = true;

	}

	/**
	 * Form token input field
	 *
	 * @returns string Input field
	 */
	function form_token() {

		global $functions;
		
		$token = $functions->generate_token();
		
		return '<input type="hidden" name="_form_token_" value="'.$token.'" />';

	}

	/**
	 * Set ACP info message
	 *
	 * @param string $msg Message
	 */
	function set_acp_msg($msg) {

		$_SESSION['acp_msg'] = $msg;

	}

	/**
	 * Show ACP info message
	 *
	 * @returns string Message
	 */
	function show_acp_msg() {

		if ( empty($_SESSION['acp_msg']) )
			return '';

		$result = '<p>'.$_SESSION['acp_msg'].'</p>';
		unset($_SESSION['acp_msg']);

		return $result;

	}
	
}

?>
Return current item: UseBB