فهرست منبع

! Theme editing didn't correctly handle session errors for templates (Themes.php)
+ Admins can now end their admin session (Admin.php, Admin language)
+ Created token verification (Security.php, Subs-Auth.php)
+ Added token checks to Login, Register, Remind and Admin Configuration Panels (Lots of files).

Spuds 12 سال پیش
والد
کامیت
f9cb33a75c
46فایلهای تغییر یافته به همراه439 افزوده شده و 28 حذف شده
  1. 22 0
      Sources/Admin.php
  2. 7 1
      Sources/Load.php
  3. 5 0
      Sources/LogInOut.php
  4. 11 0
      Sources/ManageBans.php
  5. 17 2
      Sources/ManageBoards.php
  6. 3 0
      Sources/ManageCalendar.php
  7. 3 0
      Sources/ManageErrors.php
  8. 11 0
      Sources/ManageLanguages.php
  9. 30 0
      Sources/ManageMaintenance.php
  10. 7 0
      Sources/ManageMembergroups.php
  11. 5 0
      Sources/ManagePaid.php
  12. 18 0
      Sources/ManagePermissions.php
  13. 3 0
      Sources/ManagePosts.php
  14. 9 3
      Sources/ManageRegistration.php
  15. 7 0
      Sources/ManageScheduledTasks.php
  16. 10 0
      Sources/ManageSearch.php
  17. 11 0
      Sources/ManageSearchEngines.php
  18. 9 0
      Sources/ManageServer.php
  19. 12 0
      Sources/ManageSettings.php
  20. 7 0
      Sources/ManageSmileys.php
  21. 6 0
      Sources/Modlog.php
  22. 5 0
      Sources/Register.php
  23. 15 1
      Sources/Reminder.php
  24. 74 0
      Sources/Security.php
  25. 5 0
      Sources/Subs-Auth.php
  26. 4 0
      Sources/Subs-List.php
  27. 28 6
      Sources/Themes.php
  28. 13 0
      Themes/default/Admin.template.php
  29. 1 0
      Themes/default/Errors.template.php
  30. 8 0
      Themes/default/Login.template.php
  31. 3 0
      Themes/default/ManageBans.template.php
  32. 2 1
      Themes/default/ManageBoards.template.php
  33. 1 0
      Themes/default/ManageLanguages.template.php
  34. 12 0
      Themes/default/ManageMaintenance.template.php
  35. 2 0
      Themes/default/ManageMembergroups.template.php
  36. 2 0
      Themes/default/ManagePaid.template.php
  37. 8 2
      Themes/default/ManagePermissions.template.php
  38. 1 0
      Themes/default/ManageScheduledTasks.template.php
  39. 4 1
      Themes/default/ManageSearch.template.php
  40. 7 0
      Themes/default/Register.template.php
  41. 4 0
      Themes/default/Reminder.template.php
  42. 15 3
      Themes/default/Themes.template.php
  43. 2 0
      Themes/default/index.template.php
  44. 1 0
      Themes/default/languages/Admin.english.php
  45. 1 0
      Themes/default/languages/Errors.english.php
  46. 8 8
      Themes/default/license.txt

+ 22 - 0
Sources/Admin.php

@@ -86,6 +86,12 @@ function AdminMain()
 					'permission' => array('admin_forum'),
 					'select' => 'index'
 				),
+				'adminlogoff' => array(
+					'label' => $txt['admin_logoff'],
+					'function' => 'AdminEndSession',
+//					'icon' => 'administration.gif',
+				),
+
 			),
 		),
 		'config' => array(
@@ -996,4 +1002,20 @@ function AdminLogs()
 	$log_functions[$sub_action][1]();
 }
 
+/**
+ * This ends a admin session, requiring authentication to access the ACP again.
+ */
+function AdminEndSession()
+{
+	// This is so easy!
+	unset($_SESSION['admin_time']);
+
+	// Clean any admin tokens as well.
+	foreach ($_SESSION['token'] as $key => $token)
+		if (strpos($key, '-admin') !== false)
+			unset($_SESSION['token'][$key]);
+
+	redirectexit('?action=admin');
+}
+
 ?>

+ 7 - 1
Sources/Load.php

@@ -208,7 +208,7 @@ function reloadSettings()
 function loadUserSettings()
 {
 	global $modSettings, $user_settings, $sourcedir, $smcFunc;
-	global $cookiename, $user_info, $language;
+	global $cookiename, $user_info, $language, $context;
 
 	// Check first the integration, then the cookie, and last the session.
 	if (count($integration_ids = call_integration_hook('integrate_verify_user')) > 0)
@@ -370,6 +370,12 @@ function loadUserSettings()
 		if (isset($_COOKIE[$cookiename]))
 			$_COOKIE[$cookiename] = '';
 
+		// Create a login token if it doesn't exist yet.
+		if (!isset($_SESSION['token']['post-login']))
+			createToken('login');
+		else
+			list ($context['login_token_var'],,, $context['login_token']) = $_SESSION['token']['post-login'];
+
 		// Do we perhaps think this is a search robot? Check every five minutes just in case...
 		if ((!empty($modSettings['spider_mode']) || !empty($modSettings['spider_group'])) && (!isset($_SESSION['robot_check']) || $_SESSION['robot_check'] < time() - 300))
 		{

+ 5 - 0
Sources/LogInOut.php

@@ -58,6 +58,9 @@ function Login()
 		$_SESSION['login_url'] = $_SESSION['old_url'];
 	else
 		unset($_SESSION['login_url']);
+
+	// Create a one time token.
+	createToken('login');
 }
 
 /**
@@ -120,6 +123,8 @@ function Login2()
 		redirectexit();
 
 	// Are you guessing with a script?
+	checkSession('post');
+	validateToken('login');
 	spamProtection('login');
 
 	// Set the login_url if it's not already set (but careful not to send us to an attachment).

+ 11 - 0
Sources/ManageBans.php

@@ -364,6 +364,7 @@ function BanEdit()
 	if (!empty($_POST['add_new_trigger']) || !empty($_POST['edit_trigger']))
 	{
 		checkSession();
+		validateToken('admin-bet');
 
 		$newBan = !empty($_POST['add_new_trigger']);
 		$values = array(
@@ -520,6 +521,7 @@ function BanEdit()
 	elseif (!empty($_POST['remove_selection']) && !empty($_POST['ban_items']) && is_array($_POST['ban_items']))
 	{
 		checkSession();
+		validateToken('admin-bet');
 
 		// Making sure every deleted ban item is an integer.
 		foreach ($_POST['ban_items'] as $key => $value)
@@ -544,6 +546,7 @@ function BanEdit()
 	elseif (!empty($_POST['modify_ban']) || !empty($_POST['add_ban']))
 	{
 		checkSession();
+		validateToken('admin-bet');
 
 		$addBan = !empty($_POST['add_ban']);
 		if (empty($_POST['ban_name']))
@@ -985,6 +988,8 @@ function BanEdit()
 	}
 	else
 		$context['sub_template'] = 'ban_edit';
+
+	createToken('admin-bet');
 }
 
 /**
@@ -1074,6 +1079,8 @@ function BanEditTrigger()
 			'is_new' => false,
 		);
 	}
+
+	createToken('admin-bet');
 }
 
 /**
@@ -1368,6 +1375,7 @@ function BanLog()
 	if (!empty($_POST['removeAll']) || (!empty($_POST['removeSelected']) && !empty($_POST['remove'])))
 	{
 		checkSession();
+		validateToken('admin-bl');
 
 		// 'Delete all entries' button was pressed.
 		if (!empty($_POST['removeAll']))
@@ -1487,6 +1495,7 @@ function BanLog()
 			'href' => $context['admin_area'] == 'ban' ? $scripturl . '?action=admin;area=ban;sa=log' : $scripturl . '?action=admin;area=logs;sa=banlog',
 			'include_start' => true,
 			'include_sort' => true,
+			'token' => 'admin-bl',
 		),
 		'additional_rows' => array(
 			array(
@@ -1499,6 +1508,8 @@ function BanLog()
 		),
 	);
 
+	createToken('admin-bl');
+
 	require_once($sourcedir . '/Subs-List.php');
 	createList($listOptions);
 

+ 17 - 2
Sources/ManageBoards.php

@@ -89,6 +89,8 @@ function ManageBoardsMain()
 	if (isset($_REQUEST['sa']) && $_REQUEST['sa'] == 'move' && in_array($_REQUEST['move_to'], array('child', 'before', 'after', 'top')))
 	{
 		checkSession('get');
+		validateToken('admin-bm-' . (int) $_REQUEST['src_board'], 'request');
+
 		if ($_REQUEST['move_to'] === 'top')
 			$boardOptions = array(
 				'move_to' => $_REQUEST['move_to'],
@@ -132,6 +134,8 @@ function ManageBoardsMain()
 
 	if (!empty($context['move_board']))
 	{
+		createToken('admin-bm-' . $context['move_board'], 'request');
+
 		$context['move_title'] = sprintf($txt['mboards_select_destination'], htmlspecialchars($boards[$context['move_board']]['name']));
 		foreach ($cat_tree as $catid => $tree)
 		{
@@ -144,7 +148,7 @@ function ManageBoardsMain()
 					$context['categories'][$catid]['move_link'] = array(
 						'child_level' => 0,
 						'label' => $txt['mboards_order_before'] . ' \'' . htmlspecialchars($boards[$boardid]['name']) . '\'',
-						'href' => $scripturl . '?action=admin;area=manageboards;sa=move;src_board=' . $context['move_board'] . ';target_board=' . $boardid . ';move_to=before;' . $context['session_var'] . '=' . $context['session_id'],
+						'href' => $scripturl . '?action=admin;area=manageboards;sa=move;src_board=' . $context['move_board'] . ';target_board=' . $boardid . ';move_to=before;' . $context['session_var'] . '=' . $context['session_id'] . ';' . $context['admin-bm-' . $context['move_board'] . '_token_var'] . '=' . $context['admin-bm-' . $context['move_board'] . '_token'],
 					);
 
 				if (!$context['categories'][$catid]['boards'][$boardid]['move'])
@@ -280,6 +284,9 @@ function EditCategory()
 		$context['sub_template'] = 'confirm_category_delete';
 		$context['page_title'] = $txt['mboards_delete_cat'];
 	}
+
+	// Create a special token.
+	createToken('admin-bc-' . $_REQUEST['cat']);
 }
 
 /**
@@ -295,6 +302,7 @@ function EditCategory2()
 	global $sourcedir;
 
 	checkSession();
+	validateToken('admin-bc-' . $_REQUEST['cat']);
 
 	require_once($sourcedir . '/Subs-Categories.php');
 
@@ -321,6 +329,9 @@ function EditCategory2()
 	// If they want to delete - first give them confirmation.
 	elseif (isset($_POST['delete']) && !isset($_POST['confirmation']) && !isset($_POST['empty']))
 	{
+		// We need a new token.
+		validateToken('admin-bc-' . $_REQUEST['cat']);
+
 		EditCategory();
 		return;
 	}
@@ -550,6 +561,9 @@ function EditBoard()
 		$context['sub_template'] = 'confirm_board_delete';
 		$context['page_title'] = $txt['mboards_delete_board'];
 	}
+
+	// Create a special token.
+	createToken('admin-be-' . $_REQUEST['boardid']);
 }
 
 /**
@@ -564,11 +578,12 @@ function EditBoard2()
 {
 	global $txt, $sourcedir, $modSettings, $smcFunc, $context;
 
+	$_POST['boardid'] = (int) $_POST['boardid'];
 	checkSession();
+	validateToken('admin-be-' . $_REQUEST['boardid']);
 
 	require_once($sourcedir . '/Subs-Boards.php');
 
-	$_POST['boardid'] = (int) $_POST['boardid'];
 
 	// Mode: modify aka. don't delete.
 	if (isset($_POST['edit']) || isset($_POST['add']))

+ 3 - 0
Sources/ManageCalendar.php

@@ -72,6 +72,7 @@ function ModifyHolidays()
 	if (isset($_REQUEST['delete']) && !empty($_REQUEST['holiday']))
 	{
 		checkSession();
+		validateToken('admin-mc');
 
 		foreach ($_REQUEST['holiday'] as $id => $value)
 			$_REQUEST['holiday'][$id] = (int) $id;
@@ -81,6 +82,7 @@ function ModifyHolidays()
 		removeHolidays($_REQUEST['holiday']);
 	}
 
+	createToken('admin-mc');
 	$listOptions = array(
 		'id' => 'holiday_list',
 		'title' => $txt['current_holidays'],
@@ -153,6 +155,7 @@ function ModifyHolidays()
 		),
 		'form' => array(
 			'href' => $scripturl . '?action=admin;area=managecalendar;sa=holidays',
+			'token' => 'admin-mc',
 		),
 		'additional_rows' => array(
 			array(

+ 3 - 0
Sources/ManageErrors.php

@@ -267,6 +267,8 @@ function ViewErrorLog()
 	$context['page_title'] = $txt['errlog'];
 	$context['has_filter'] = isset($filter);
 	$context['sub_template'] = 'error_log';
+
+	createToken('admin-el');
 }
 
 /**
@@ -282,6 +284,7 @@ function deleteErrors()
 
 	// Make sure the session exists and is correct; otherwise, might be a hacker.
 	checkSession();
+	validateToken('admin-el');
 
 	// Delete all or just some?
 	if (isset($_POST['delall']) && !isset($filter))

+ 11 - 0
Sources/ManageLanguages.php

@@ -142,6 +142,7 @@ function DownloadLanguage()
 	if (!empty($_POST['do_install']) && !empty($_POST['copy_file']))
 	{
 		checkSession('get');
+		validateToken('admin-dlang');
 
 		$chmod_files = array();
 		$install_files = array();
@@ -481,6 +482,7 @@ function DownloadLanguage()
 	createList($listOptions);
 
 	$context['default_list'] = 'lang_main_files_list';
+	createToken('admin-dlang');
 }
 
 /**
@@ -495,6 +497,7 @@ function ModifyLanguages()
 	if (!empty($_POST['set_default']) && !empty($_POST['def_language']))
 	{
 		checkSession();
+		validateToken('admin-lang');
 
 		if ($_POST['def_language'] != $language)
 		{
@@ -504,6 +507,9 @@ function ModifyLanguages()
 		}
 	}
 
+	// Create another one time token here.
+	createToken('admin-lang');
+
 	$listOptions = array(
 		'id' => 'language_list',
 		'items_per_page' => 20,
@@ -567,6 +573,7 @@ function ModifyLanguages()
 		),
 		'form' => array(
 			'href' => $scripturl . '?action=admin;area=languages',
+			'token' => 'admin-lang',
 		),
 		'additional_rows' => array(
 			array(
@@ -917,6 +924,7 @@ function ModifyLanguage()
 	if (!empty($_POST['save_main']) && !$current_file)
 	{
 		checkSession();
+		validateToken('admin-mlang');
 
 		// Read in the current file.
 		$current_data = implode('', file($settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php'));
@@ -958,6 +966,7 @@ function ModifyLanguage()
 	if (isset($_POST['save_entries']) && !empty($_POST['entry']))
 	{
 		checkSession();
+		validateToken('admin-mlang');
 
 		// Clean each entry!
 		foreach ($_POST['entry'] as $k => $v)
@@ -1139,6 +1148,8 @@ function ModifyLanguage()
 	// If we saved, redirect.
 	if ($madeSave)
 		redirectexit('action=admin;area=languages;sa=editlang;lid=' . $context['lang_id']);
+
+	createToken('admin-mlang');
 }
 
 /**

+ 30 - 0
Sources/ManageMaintenance.php

@@ -113,6 +113,9 @@ function ManageMaintenance()
 	//converted to UTF-8? show a small maintenance info
 	if (isset($_GET['done']) && $_GET['done'] == 'convertutf8')
 		$context['maintenance_finished'] = $txt['utf8_title'];
+
+	// Create a maintenance token.  Kinda hard to do it any other way.
+	createToken('admin-maint');
 }
 
 /**
@@ -221,6 +224,9 @@ function MaintainFindFixErrors()
 {
 	global $sourcedir;
 
+	// Honestly, this should be done in the sub function.
+	validateToken('admin-maint');
+
 	require_once($sourcedir . '/RepairBoards.php');
 	RepairBoards();
 }
@@ -233,6 +239,9 @@ function MaintainCleanCache()
 {
 	global $context, $txt;
 
+	checkSession();
+	validateToken('admin-maint');
+
 	// Just wipe the whole cache directory!
 	clean_cache();
 
@@ -247,6 +256,7 @@ function MaintainEmptyUnimportantLogs()
 	global $context, $smcFunc, $txt;
 
 	checkSession();
+	validateToken('admin-maint');
 
 	// No one's online now.... MUHAHAHAHA :P.
 	$smcFunc['db_query']('', '
@@ -362,6 +372,8 @@ function ConvertUtf8()
 	// This is for the first screen telling backups is good.
 	if (!isset($_POST['proceed']))
 	{
+		validateToken('admin-maint');
+
 		// Character set conversions are only supported as of MySQL 4.1.2.
 		if (version_compare('4.1.2', preg_replace('~\-.+?$~', '', $smcFunc['db_server_info']())) > 0)
 			fatal_lang_error('utf8_db_version_too_low');
@@ -411,11 +423,15 @@ function ConvertUtf8()
 
 		$context['page_title'] = $txt['utf8_title'];
 		$context['sub_template'] = 'convert_utf8';
+
+		createToken('admin-maint');
 		return;
 	}
 
 	// After this point we're starting the conversion. But first: session check.
 	checkSession();
+	validateToken('admin-maint');
+	createToken('admin-maint');
 
 	// Translation table for the character sets not native for MySQL.
 	$translation_tables = array(
@@ -690,6 +706,9 @@ function ConvertEntities()
 	// The first step is just a text screen with some explanation.
 	if ($context['first_step'])
 	{
+		validateToken('admin-maint');
+		createToken('admin-maint');
+
 		$context['sub_template'] = 'convert_entities';
 		return;
 	}
@@ -700,6 +719,8 @@ function ConvertEntities()
 
 	// Now we're actually going to convert...
 	checkSession('request');
+	validateToken('admin-maint');
+	createToken('admin-maint');
 
 	// A list of tables ready for conversion.
 	$tables = array(
@@ -879,6 +900,7 @@ function OptimizeTables()
 	isAllowedTo('admin_forum');
 
 	checkSession('post');
+	validateToken('admin-maint');
 
 	ignore_user_abort(true);
 	db_extend();
@@ -953,6 +975,7 @@ function AdminBoardRecount()
 	isAllowedTo('admin_forum');
 
 	checkSession('request');
+	validateToken('admin-maint');
 
 	$context['page_title'] = $txt['not_done_title'];
 	$context['continue_post_data'] = '';
@@ -1509,6 +1532,8 @@ function MaintainDownloadBackup()
 {
 	global $sourcedir;
 
+	validateToken('admin-maint');
+
 	require_once($sourcedir . '/DumpDatabase.php');
 	DumpDatabase2();
 }
@@ -1525,6 +1550,7 @@ function MaintainPurgeInactiveMembers()
 	if (!empty($_POST['groups']) && $_POST['maxdays'])
 	{
 		checkSession();
+		validateToken('admin-maint');
 
 		$groups = array();
 		foreach ($_POST['groups'] as $id => $dummy)
@@ -1596,6 +1622,7 @@ function MaintainPurgeInactiveMembers()
 	}
 
 	$context['maintenance_finished'] = $txt['maintain_members'];
+	createToken('admin-maint');
 }
 
 /**
@@ -1605,6 +1632,8 @@ function MaintainRemoveOldPosts()
 {
 	global $sourcedir, $context, $txt;
 
+	validateToken('admin-maint');
+
 	// Actually do what we're told!
 	require_once($sourcedir . '/RemoveTopic.php');
 	RemoveOldTopics2();
@@ -1623,6 +1652,7 @@ function MaintainMassMoveTopics()
 	isAllowedTo('admin_forum');
 
 	checkSession('request');
+	validateToken('admin-maint');
 
 	// Set up to the context.
 	$context['page_title'] = $txt['not_done_title'];

+ 7 - 0
Sources/ManageMembergroups.php

@@ -325,6 +325,7 @@ function AddMembergroup()
 	if (!empty($_POST['group_name']))
 	{
 		checkSession();
+		validateToken('admin-mmg');
 
 		$postCountBasedGroup = isset($_POST['min_posts']) && (!isset($_POST['postgroup_based']) || !empty($_POST['postgroup_based']));
 		$_POST['group_type'] = !isset($_POST['group_type']) || $_POST['group_type'] < 0 || $_POST['group_type'] > 3 || ($_POST['group_type'] == 1 && !allowedTo('admin_forum')) ? 0 : (int) $_POST['group_type'];
@@ -571,6 +572,8 @@ function AddMembergroup()
 			'selected' => false
 		);
 	$smcFunc['db_free_result']($result);
+
+	createToken('admin-mmg');
 }
 
 /**
@@ -637,6 +640,7 @@ function EditMembergroup()
 	if (isset($_POST['delete']))
 	{
 		checkSession();
+		validateToken('admin-mmg');
 
 		require_once($sourcedir . '/Subs-Membergroups.php');
 		deleteMembergroups($_REQUEST['group']);
@@ -648,6 +652,7 @@ function EditMembergroup()
 	{
 		// Validate the session.
 		checkSession();
+		validateToken('admin-mmg');
 
 		// Can they really inherit from this group?
 		if ($_POST['group_inherit'] != -2 && !allowedTo('admin_forum'))
@@ -1033,6 +1038,8 @@ function EditMembergroup()
 
 	$context['sub_template'] = 'edit_group';
 	$context['page_title'] = $txt['membergroups_edit_group'];
+
+	createToken('admin-mmg');
 }
 
 /**

+ 5 - 0
Sources/ManagePaid.php

@@ -344,6 +344,7 @@ function ModifySubscription()
 	if (isset($_POST['delete_confirm']) && isset($_REQUEST['delete']))
 	{
 		checkSession();
+		validateToken('admin-pmsd');
 
 		$smcFunc['db_query']('delete_subscription', '
 			DELETE FROM {db_prefix}subscriptions
@@ -360,6 +361,7 @@ function ModifySubscription()
 	if (isset($_POST['save']))
 	{
 		checkSession();
+		validateToken('admin-pms');
 
 		// Some cleaning...
 		$isActive = isset($_POST['active']) ? 1 : 0;
@@ -573,6 +575,9 @@ function ModifySubscription()
 	while ($row = $smcFunc['db_fetch_assoc']($request))
 		$context['groups'][$row['id_group']] = $row['group_name'];
 	$smcFunc['db_free_result']($request);
+
+	// This always happens.
+	createToken($context['action_type'] == 'delete' ? 'admin-pmsd' : 'admin-pms');
 }
 
 /**

+ 18 - 0
Sources/ManagePermissions.php

@@ -334,6 +334,7 @@ function PermissionIndex()
 
 	// Load the proper template.
 	$context['sub_template'] = 'permission_index';
+	createToken('admin-mpq');
 }
 
 /**
@@ -350,6 +351,7 @@ function PermissionByBoard()
 	if (!empty($_POST['save_changes']) && !empty($_POST['boardprofile']))
 	{
 		checkSession('request');
+		validateToken('admin-mpb');
 
 		$changes = array();
 		foreach ($_POST['boardprofile'] as $board => $profile)
@@ -408,6 +410,7 @@ function PermissionByBoard()
 	}
 
 	$context['sub_template'] = 'by_board';
+	createToken('admin-mpb');
 }
 
 /**
@@ -419,6 +422,7 @@ function SetQuickGroups()
 	global $context, $smcFunc;
 
 	checkSession();
+	validateToken('admin-mpq', 'quick');
 
 	loadIllegalPermissions();
 	loadIllegalGuestPermissions();
@@ -820,6 +824,8 @@ function ModifyMembergroup()
 	}
 	$context['sub_template'] = 'modify_group';
 	$context['page_title'] = $txt['permissions_modify_group'];
+
+	createToken('admin-mp');
 }
 
 /**
@@ -830,6 +836,7 @@ function ModifyMembergroup2()
 	global $modSettings, $smcFunc, $context;
 
 	checkSession();
+	validateToken('admin-mp');
 
 	loadIllegalPermissions();
 
@@ -1806,6 +1813,7 @@ function save_inline_permissions($permissions)
 
 	// Almighty session check, verify our ways.
 	checkSession();
+	validateToken('admin-mp');
 
 	// Check they can't do certain things.
 	loadIllegalPermissions();
@@ -1898,6 +1906,7 @@ function EditPermissionProfiles()
 	if (isset($_POST['create']) && trim($_POST['profile_name']) != '')
 	{
 		checkSession();
+		validateToken('admin-mpp');
 
 		$_POST['copy_from'] = (int) $_POST['copy_from'];
 		$_POST['profile_name'] = $smcFunc['htmlspecialchars']($_POST['profile_name']);
@@ -1941,6 +1950,7 @@ function EditPermissionProfiles()
 	elseif (isset($_POST['rename']))
 	{
 		checkSession();
+		validateToken('admin-mpp');
 
 		// Just showing the boxes?
 		if (!isset($_POST['rename_profile']))
@@ -1968,6 +1978,7 @@ function EditPermissionProfiles()
 	elseif (isset($_POST['delete']) && !empty($_POST['delete_profile']))
 	{
 		checkSession('post');
+		validateToken('admin-mpp');
 
 		$profiles = array();
 		foreach ($_POST['delete_profile'] as $profile)
@@ -2030,6 +2041,8 @@ function EditPermissionProfiles()
 		// You can only delete it if you can edit it AND it's not in use.
 		$context['profiles'][$id]['can_delete'] = $context['profiles'][$id]['can_edit'] && empty($profile['in_use']) ? true : false;
 	}
+
+	createToken('admin-mpp');
 }
 
 /**
@@ -2304,6 +2317,8 @@ function ModifyPostModeration()
 	// If we're saving the changes then do just that - save them.
 	if (!empty($_POST['save_changes']) && ($context['current_profile'] == 1 || $context['current_profile'] > 4))
 	{
+		validateToken('admin-mppm');
+
 		// Start by deleting all the permissions relevant.
 		$smcFunc['db_query']('', '
 			DELETE FROM {db_prefix}board_permissions
@@ -2383,6 +2398,9 @@ function ModifyPostModeration()
 		}
 	}
 	$smcFunc['db_free_result']($request);
+
+	createToken('admin-mppm');
+
 }
 
 ?>

+ 3 - 0
Sources/ManagePosts.php

@@ -85,6 +85,7 @@ function SetCensor()
 	{
 		// Make sure censoring is something they can do.
 		checkSession();
+		validateToken('admin-censor');
 
 		$censored_vulgar = array();
 		$censored_proper = array();
@@ -153,6 +154,8 @@ function SetCensor()
 
 	$context['sub_template'] = 'edit_censored';
 	$context['page_title'] = $txt['admin_censored_words'];
+
+	createToken('admin-censor');
 }
 
 /**

+ 9 - 3
Sources/ManageRegistration.php

@@ -91,6 +91,7 @@ function AdminRegister()
 	if (!empty($_POST['regSubmit']))
 	{
 		checkSession();
+		validateToken('admin-regc');
 
 		foreach ($_POST as $key => $value)
 			if (!is_array($_POST[$key]))
@@ -124,9 +125,6 @@ function AdminRegister()
 		}
 	}
 
-	// Basic stuff.
-	$context['sub_template'] = 'admin_register';
-	$context['page_title'] = $txt['registration_center'];
 
 	// Load the assignable member groups.
 	if (allowedTo('manage_membergroups'))
@@ -156,6 +154,10 @@ function AdminRegister()
 	}
 	else
 		$context['member_groups'] = array();
+	// Basic stuff.
+	$context['sub_template'] = 'admin_register';
+	$context['page_title'] = $txt['registration_center'];
+	createToken('admin-regc');
 }
 
 /**
@@ -198,6 +200,7 @@ function EditAgreement()
 	if (isset($_POST['agreement']))
 	{
 		checkSession();
+		validateToken('admin-rega');
 
 		// Off it goes to the agreement file.
 		$fp = fopen($boarddir . '/agreement' . $context['current_agreement'] . '.txt', 'w');
@@ -213,6 +216,7 @@ function EditAgreement()
 
 	$context['sub_template'] = 'edit_agreement';
 	$context['page_title'] = $txt['registration_agreement'];
+	createToken('admin-rega');
 }
 
 /**
@@ -230,6 +234,7 @@ function SetReserved()
 	if (!empty($_POST['save_reserved_names']))
 	{
 		checkSession();
+		validateToken('admin-regr');
 
 		// Set all the options....
 		updateSettings(array(
@@ -253,6 +258,7 @@ function SetReserved()
 	// Ready the template......
 	$context['sub_template'] = 'edit_reserved_words';
 	$context['page_title'] = $txt['admin_reserved_set'];
+	createToken('admin-regr');
 }
 
 /**

+ 7 - 0
Sources/ManageScheduledTasks.php

@@ -328,6 +328,7 @@ function EditTask()
 	if (isset($_GET['save']))
 	{
 		checkSession();
+		validateToken('admin-st');
 
 		// We'll need this for calculating the next event.
 		require_once($sourcedir . '/ScheduledTasks.php');
@@ -407,6 +408,8 @@ function EditTask()
 		);
 	}
 	$smcFunc['db_free_result']($request);
+
+	createToken('admin-st');
 }
 
 /**
@@ -425,6 +428,7 @@ function TaskLog()
 	if (!empty($_POST['removeAll']))
 	{
 		checkSession();
+		validateToken('admin-tl');
 
 		$smcFunc['db_query']('truncate_table', '
 			TRUNCATE {db_prefix}log_scheduled_tasks',
@@ -490,6 +494,7 @@ function TaskLog()
 		),
 		'form' => array(
 			'href' => $context['admin_area'] == 'scheduledtasks' ? $scripturl . '?action=admin;area=scheduledtasks;sa=tasklog' : $scripturl . '?action=admin;area=logs;sa=tasklog',
+			'token' => 'admin-tl',
 		),
 		'additional_rows' => array(
 			array(
@@ -506,6 +511,8 @@ function TaskLog()
 		),
 	);
 
+	createToken('admin-tl');
+
 	require_once($sourcedir . '/Subs-List.php');
 	createList($listOptions);
 

+ 10 - 0
Sources/ManageSearch.php

@@ -163,6 +163,7 @@ function EditWeights()
 	if (isset($_POST['save']))
 	{
 		checkSession();
+		validateToken('admin-msw');
 
 		$changes = array();
 		foreach ($factors as $factor)
@@ -176,6 +177,8 @@ function EditWeights()
 
 	foreach ($factors as $factor)
 		$context['relative_weights'][$factor] = round(100 * (isset($modSettings[$factor]) ? $modSettings[$factor] : 0) / $context['relative_weights']['total'], 1);
+
+	createToken('admin-msw');
 }
 
 /**
@@ -266,6 +269,7 @@ function EditSearchMethod()
 	if (!empty($_REQUEST['sa']) && $_REQUEST['sa'] == 'createfulltext')
 	{
 		checkSession('get');
+		validateToken('admin-msm');
 
 		// Make sure it's gone before creating it.
 		$smcFunc['db_query']('', '
@@ -288,6 +292,7 @@ function EditSearchMethod()
 	elseif (!empty($_REQUEST['sa']) && $_REQUEST['sa'] == 'removefulltext' && !empty($context['fulltext_index']))
 	{
 		checkSession('get');
+		validateToken('admin-msm');
 
 		$smcFunc['db_query']('', '
 			ALTER TABLE {db_prefix}messages
@@ -309,6 +314,7 @@ function EditSearchMethod()
 	elseif (!empty($_REQUEST['sa']) && $_REQUEST['sa'] == 'removecustom')
 	{
 		checkSession('get');
+		validateToken('admin-msm');
 
 		db_extend();
 		$tables = $smcFunc['db_list_tables'](false, $db_prefix . 'log_search_words');
@@ -335,6 +341,8 @@ function EditSearchMethod()
 	elseif (isset($_POST['save']))
 	{
 		checkSession();
+		validateToken('admin-msm');
+
 		updateSettings(array(
 			'search_index' => empty($_POST['search_index']) || (!in_array($_POST['search_index'], array('fulltext', 'custom')) && !isset($context['search_apis'][$_POST['search_index']])) ? '' : $_POST['search_index'],
 			'search_force_index' => isset($_POST['search_force_index']) ? '1' : '0',
@@ -477,6 +485,8 @@ function EditSearchMethod()
 	$context['custom_index'] = !empty($modSettings['search_custom_index_config']);
 	$context['partial_custom_index'] = !empty($modSettings['search_custom_index_resume']) && empty($modSettings['search_custom_index_config']);
 	$context['double_index'] = !empty($context['fulltext_index']) && $context['custom_index'];
+
+	createToken('admin-msm');
 }
 
 /**

+ 11 - 0
Sources/ManageSearchEngines.php

@@ -157,6 +157,7 @@ function ViewSpiders()
 	elseif (!empty($_POST['removeSpiders']) && !empty($_POST['remove']) && is_array($_POST['remove']))
 	{
 		checkSession();
+		validateToken('admin-ser');
 
 		// Make sure every entry is a proper integer.
 		foreach ($_POST['remove'] as $index => $spider_id)
@@ -203,6 +204,7 @@ function ViewSpiders()
 		$context['spider_last_seen'][$row['id_spider']] = $row['last_seen_time'];
 	$smcFunc['db_free_result']($request);
 
+	createToken('admin-ser');
 	$listOptions = array(
 		'id' => 'spider_list',
 		'items_per_page' => 20,
@@ -286,6 +288,7 @@ function ViewSpiders()
 		),
 		'form' => array(
 			'href' => $scripturl . '?action=admin;area=sengines;sa=spiders',
+			'token' => 'admin-ser',
 		),
 		'additional_rows' => array(
 			array(
@@ -364,6 +367,7 @@ function EditSpider()
 	if (!empty($_POST['save']))
 	{
 		checkSession();
+		validateToken('admin-ses');
 
 		$ips = array();
 		// Check the IP range is valid.
@@ -440,6 +444,7 @@ function EditSpider()
 		$smcFunc['db_free_result']($request);
 	}
 
+	createToken('admin-ses');
 }
 
 /**
@@ -663,6 +668,7 @@ function SpiderLogs()
 	if (!empty($_POST['delete_entries']) && isset($_POST['older']))
 	{
 		checkSession();
+		validateToken('admin-sl');
 
 		$deleteTime = time() - (((int) $_POST['older']) * 24 * 60 * 60);
 
@@ -725,6 +731,9 @@ function SpiderLogs()
 				),
 			),
 		),
+		'form' => array(
+			'token' => 'admin-sl',
+		),
 		'additional_rows' => array(
 			array(
 				'position' => 'after_title',
@@ -734,6 +743,8 @@ function SpiderLogs()
 		),
 	);
 
+	createToken('admin-sl');
+
 	require_once($sourcedir . '/Subs-List.php');
 	createList($listOptions);
 

+ 9 - 0
Sources/ManageServer.php

@@ -475,6 +475,9 @@ function prepareServerSettingsContext(&$config_vars)
 			);
 		}
 	}
+
+	createToken('admin-ssc');
+	createToken('admin-dbsc');
 }
 
 /**
@@ -634,6 +637,8 @@ function prepareDBSettingContext(&$config_vars)
 			);
 		}
 	}
+
+	createToken('admin-dbsc');
 }
 
 /**
@@ -649,6 +654,8 @@ function saveSettings(&$config_vars)
 	global $boarddir, $sc, $cookiename, $modSettings, $user_settings;
 	global $sourcedir, $context, $cachedir;
 
+	validateToken('admin-ssc');
+
 	// Fix the darn stupid cookiename! (more may not be allowed, but these for sure!)
 	if (isset($_POST['cookiename']))
 		$_POST['cookiename'] = preg_replace('~[,;\s\.$]+~' . ($context['utf8'] ? 'u' : ''), '', $_POST['cookiename']);
@@ -744,6 +751,8 @@ function saveDBSettings(&$config_vars)
 {
 	global $sourcedir, $context;
 
+	validateToken('admin-dbsc');
+
 	$inlinePermissions = array();
 	foreach ($config_vars as $var)
 	{

+ 12 - 0
Sources/ManageSettings.php

@@ -338,6 +338,7 @@ function ModifyCoreFeatures($return_config = false)
 	if (isset($_POST['save']))
 	{
 		checkSession();
+		validateToken('admin-core');
 
 		$setting_changes = array('admin_features' => array());
 
@@ -409,6 +410,9 @@ function ModifyCoreFeatures($return_config = false)
 
 	$context['sub_template'] = 'core_features';
 	$context['page_title'] = $txt['core_settings_title'];
+
+	// We love our tokens.
+	createToken('admin-core');
 }
 
 /**
@@ -1273,6 +1277,7 @@ function ShowCustomProfiles()
 	if (isset($_POST['save']))
 	{
 		checkSession();
+		validateToken('admin-scp');
 
 		// Do the active ones first.
 		$disable_fields = array_flip($standard_fields);
@@ -1300,6 +1305,8 @@ function ShowCustomProfiles()
 			updateSettings($changes);
 	}
 
+	createToken('admin-scp');
+
 	require_once($sourcedir . '/Subs-List.php');
 
 	$listOptions = array(
@@ -1353,6 +1360,7 @@ function ShowCustomProfiles()
 		'form' => array(
 			'href' => $scripturl . '?action=admin;area=featuresettings;sa=profile',
 			'name' => 'standardProfileFields',
+			'token' => 'admin-scp',
 		),
 		'additional_rows' => array(
 			array(
@@ -1651,6 +1659,7 @@ function EditCustomProfiles()
 	if (isset($_POST['save']))
 	{
 		checkSession();
+		validateToken('admin-ecp');
 
 		// Everyone needs a name - even the (bracket) unknown...
 		if (trim($_POST['field_name']) == '')
@@ -1892,6 +1901,7 @@ function EditCustomProfiles()
 	elseif (isset($_POST['delete']) && $context['field']['colname'])
 	{
 		checkSession();
+		validateToken('admin-ecp');
 
 		// Delete the user data first.
 		$smcFunc['db_query']('', '
@@ -1950,6 +1960,8 @@ function EditCustomProfiles()
 		updateSettings(array('displayFields' => serialize($fields)));
 		redirectexit('action=admin;area=featuresettings;sa=profile');
 	}
+
+	createToken('admin-ecp');
 }
 
 /**

+ 7 - 0
Sources/ManageSmileys.php

@@ -176,6 +176,7 @@ function EditSmileySets()
 	if (isset($_POST[$context['session_var']]))
 	{
 		checkSession();
+		validateToken('admin-mss', 'request');
 
 		// Delete selected smiley sets.
 		if (!empty($_POST['delete']) && !empty($_POST['smiley_set']))
@@ -260,6 +261,8 @@ function EditSmileySets()
 	if ($context['sub_action'] == 'import')
 	{
 		checkSession('get');
+		validateToken('admin-mss', 'request');
+
 		$_GET['set'] = (int) $_GET['set'];
 
 		// Sanity check - then import.
@@ -338,6 +341,9 @@ function EditSmileySets()
 		}
 	}
 
+	// This is our save haven.
+	createToken('admin-mss', 'request');
+
 	$listOptions = array(
 		'id' => 'smiley_set_list',
 		'base_href' => $scripturl . '?action=admin;area=smileys;sa=editsets',
@@ -422,6 +428,7 @@ function EditSmileySets()
 		),
 		'form' => array(
 			'href' => $scripturl . '?action=admin;area=smileys;sa=editsets',
+			'token' => 'admin-mss',
 		),
 		'additional_rows' => array(
 			array(

+ 6 - 0
Sources/Modlog.php

@@ -56,6 +56,7 @@ function ViewModlog()
 	if (isset($_POST['removeall']) && $context['can_delete'])
 	{
 		checkSession();
+		validateToken('mod-ml');
 
 		$smcFunc['db_query']('', '
 			DELETE FROM {db_prefix}log_actions
@@ -70,6 +71,8 @@ function ViewModlog()
 	elseif (!empty($_POST['remove']) && isset($_POST['delete']) && $context['can_delete'])
 	{
 		checkSession();
+		validateToken('mod-ml');
+
 		$smcFunc['db_query']('', '
 			DELETE FROM {db_prefix}log_actions
 			WHERE id_log = {int:moderate_log}
@@ -267,6 +270,7 @@ function ViewModlog()
 				$context['session_var'] => $context['session_id'],
 				'params' => $context['search_params']
 			),
+			'token' => 'mod-ml',
 		),
 		'additional_rows' => array(
 			array(
@@ -287,6 +291,8 @@ function ViewModlog()
 		),
 	);
 
+	createToken('mod-ml');
+
 	// Create the watched user list.
 	createList($listOptions);
 

+ 5 - 0
Sources/Register.php

@@ -191,6 +191,8 @@ function Register($reg_errors = array())
 	if (!empty($reg_errors))
 		foreach ($reg_errors as $error)
 			$context['registration_errors'][] = $error;
+
+	createToken('register');
 }
 
 /**
@@ -203,6 +205,9 @@ function Register2($verifiedOpenID = false)
 	global $scripturl, $txt, $modSettings, $context, $sourcedir;
 	global $user_info, $options, $settings, $smcFunc;
 
+	checkSession();
+	validateToken('register');
+
 	// Start collecting together any errors.
 	$reg_errors = array();
 

+ 15 - 1
Sources/Reminder.php

@@ -59,6 +59,9 @@ function RemindMe()
 	// Any subaction?  If none, fall through to the main template, which will ask for one.
 	if (isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]))
 		$subActions[$_REQUEST['sa']]();
+	// Creating a one time token.
+	else
+		createToken('remind');
 }
 
 // Pick a reminder type.
@@ -67,6 +70,8 @@ function RemindPick()
 	global $context, $txt, $scripturl, $sourcedir, $user_info, $webmaster_email, $smcFunc, $language, $modSettings;
 
 	checkSession();
+	validateToken('remind');
+	createToken('remind');
 
 	// Coming with a known ID?
 	if (!empty($_REQUEST['uid']))
@@ -151,7 +156,7 @@ function RemindPick()
 		$context['description'] = $txt['reminder_' . (!empty($row['openid_uri']) ? 'openid_' : '') . 'sent'];
 
 		// If they were using OpenID simply email them their OpenID identity.
-		sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 0);
+		sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 1);
 		if (empty($row['openid_uri']))
 			// Set the password in the database.
 			updateMemberData($row['id_member'], array('validation_code' => substr(md5($password), 0, 10)));
@@ -194,6 +199,9 @@ function setPassword()
 		'code' => $_REQUEST['code'],
 		'memID' => (int) $_REQUEST['u']
 	);
+
+	// Tokens!
+	createToken('remind-sp');
 }
 
 function setPassword2()
@@ -201,6 +209,7 @@ function setPassword2()
 	global $context, $txt, $modSettings, $smcFunc, $sourcedir;
 
 	checkSession();
+	validateToken('remind-sp');
 
 	if (empty($_POST['u']) || !isset($_POST['passwrd1']) || !isset($_POST['passwrd2']))
 		fatal_lang_error('no_access', false);
@@ -273,6 +282,7 @@ function setPassword2()
 		'never_expire' => false,
 		'description' => $txt['reminder_password_set']
 	);
+	createToken('login');
 }
 
 // Get the secret answer.
@@ -317,6 +327,7 @@ function SecretAnswerInput()
 	$context['secret_question'] = $row['secret_question'];
 
 	$context['sub_template'] = 'ask';
+	createToken('remind-sai');
 }
 
 function SecretAnswer2()
@@ -324,6 +335,7 @@ function SecretAnswer2()
 	global $txt, $context, $modSettings, $smcFunc, $sourcedir;
 
 	checkSession();
+	validateToken('remind-sai');
 
 	// Hacker?  How did you get this far without an email or username?
 	if (empty($_REQUEST['uid']))
@@ -393,6 +405,8 @@ function SecretAnswer2()
 		'never_expire' => false,
 		'description' => $txt['reminder_password_set']
 	);
+
+	createToken('login');
 }
 
 ?>

+ 74 - 0
Sources/Security.php

@@ -759,6 +759,80 @@ function checkConfirm($action)
 	}
 }
 
+// Lets give you a token of our appreciation.
+function createToken($action, $type = 'post')
+{
+	global $modSettings, $context;
+
+	$token = md5(mt_rand() . session_id() . (string) microtime() . $modSettings['rand_seed'] . $type);
+	$token_var = substr(preg_replace('~^\d+~', '', md5(mt_rand() . (string) microtime() . mt_rand())), 0, rand(7, 12));
+
+	$_SESSION['token'][$type . '-' . $action] = array($token_var, md5($token . $_SERVER['HTTP_USER_AGENT']), time(), $token);
+
+	$context[$action . '_token'] = $token;
+	$context[$action . '_token_var'] = $token_var;
+
+	return array($token_var, $token);
+}
+
+// Only patrons with valid tokens can ride this ride.
+function validateToken($action, $type = 'post', $reset = true)
+{
+	global $modSettings;
+
+	$type = $type == 'get' || $type == 'request' ? $type : 'post';
+
+	// This nasty piece of code validates a token.
+	/*
+		1. The token exists in session.
+		2. The {$type} variable should exist.
+		3. We concat the variable we received with the user agent
+		4. Match that result against what is in the session.
+		5. If it matchs, success, otherwise we fallout.
+	*/
+	if (isset($_SESSION['token'][$type . '-' . $action], $GLOBALS['_' . strtoupper($type)][$_SESSION['token'][$type . '-' . $action][0]]) && md5($GLOBALS['_' . strtoupper($type)][$_SESSION['token'][$type . '-' . $action][0]] . $_SERVER['HTTP_USER_AGENT']) == $_SESSION['token'][$type . '-' . $action][1])
+	{
+		// Invalidate this token now.
+		unset($_SESSION['token'][$type . '-' . $action]);
+
+		return true;
+	}
+
+	// Patrons with invalid tokens get the boot.
+	if ($reset)
+	{
+		// Might as well do some cleanup on this.
+		cleanTokens();
+
+		// I'm back baby.
+		createToken($action, $type);
+
+		fatal_lang_error('token_verify_fail', false);
+	}
+	// Remove this token as its useless
+	else
+		unset($_SESSION['token'][$type . '-' . $action]);
+
+	// Randomly check if we should remove some older tokens.
+	if (mt_rand(0, 138) == 23)
+		cleanTokens();
+
+	return false;
+}
+
+// Clean up a little.
+function cleanTokens($complete = false)
+{
+	// We appreciate cleaning up after yourselves.
+	if (!isset($_SESSION['token']))
+		return;
+
+	// Clean up tokens, trying to give enough time still.
+	foreach ($_SESSION['token'] as $key => $data)
+		if ($data[2] + 10800 < time() || $complete)
+			unset($_SESSION['token'][$key]);
+}
+
 // Check whether a form has been submitted twice.
 function checkSubmitOnce($action, $is_fatal = true)
 {

+ 5 - 0
Sources/Subs-Auth.php

@@ -272,6 +272,8 @@ function adminLogin()
 		$context['incorrect_password'] = true;
 	}
 
+	createToken('admin-login');
+
 	// Figure out the get data and post data.
 	$context['get_data'] = '?' . construct_query_string($_GET);
 	$context['post_data'] = '';
@@ -729,6 +731,9 @@ function rebuildModCache()
 	);
 
 	$user_info['mod_cache'] = $_SESSION['mc'];
+
+	// Might as well clean up some tokens while we are at it.
+	cleanTokens();
 }
 
 ?>

+ 4 - 0
Sources/Subs-List.php

@@ -183,6 +183,10 @@ function createList($listOptions)
 		// Always add a session check field.
 		$list_context['form']['hidden_fields'][$context['session_var']] = $context['session_id'];
 
+		// Will this do a token check?
+		if (isset($listOptions['form']['token']))
+			$list_context['form']['hidden_fields'][$context[$listOptions['form']['token'] . '_token_var']] = $context[$listOptions['form']['token'] . '_token'];
+
 		// Include the starting page as hidden field?
 		if (!empty($list_context['form']['include_start']) && !empty($list_context['start']))
 			$list_context['form']['hidden_fields'][$list_context['start_var_name']] = $list_context['start'];

+ 28 - 6
Sources/Themes.php

@@ -217,10 +217,13 @@ function ThemeAdmin()
 		while (file_exists($theme_dir . $i))
 			$i++;
 		$context['new_theme_name'] = 'theme' . $i;
+
+		createToken('admin-tm');
 	}
 	else
 	{
 		checkSession();
+		validateToken('admin-tm');
 
 		if (isset($_POST['options']['known_themes']))
 			foreach ($_POST['options']['known_themes'] as $key => $id)
@@ -254,6 +257,7 @@ function ThemeList()
 	if (isset($_POST['submit']))
 	{
 		checkSession();
+		validateToken('admin-tl');
 
 		$request = $smcFunc['db_query']('', '
 			SELECT id_theme, variable, value
@@ -357,6 +361,8 @@ function ThemeList()
 	$context['reset_url'] = $boardurl . '/Themes';
 
 	$context['sub_template'] = 'list_themes';
+	createToken('admin-tl');
+	createToken('admin-tr', 'request');
 }
 
 // Administrative global settings.
@@ -443,6 +449,7 @@ function SetThemeOptions()
 		loadTemplate('Themes');
 		$context['sub_template'] = 'reset_list';
 
+		createToken('admin-stor', 'request');
 		return;
 	}
 
@@ -450,6 +457,7 @@ function SetThemeOptions()
 	if (isset($_POST['submit']) && empty($_POST['who']))
 	{
 		checkSession();
+		validateToken('admin-sto');
 
 		if (empty($_POST['options']))
 			$_POST['options'] = array();
@@ -503,6 +511,7 @@ function SetThemeOptions()
 	elseif (isset($_POST['submit']) && $_POST['who'] == 1)
 	{
 		checkSession();
+		validateToken('admin-sto');
 
 		$_POST['options'] = empty($_POST['options']) ? array() : $_POST['options'];
 		$_POST['options_master'] = empty($_POST['options_master']) ? array() : $_POST['options_master'];
@@ -620,6 +629,7 @@ function SetThemeOptions()
 	elseif (!empty($_GET['who']) && $_GET['who'] == 2)
 	{
 		checkSession('get');
+		validateToken('admin-stor', 'request');
 
 		// Don't delete custom fields!!
 		if ($_GET['th'] == 1)
@@ -728,6 +738,7 @@ function SetThemeOptions()
 	$settings = $old_settings;
 
 	loadTemplate('Themes');
+	createToken('admin-sto');
 }
 
 // Administrative global settings.
@@ -789,6 +800,7 @@ function SetThemeSettings()
 	if (isset($_POST['submit']))
 	{
 		checkSession();
+		validateToken('admin-sts');
 
 		if (empty($_POST['options']))
 			$_POST['options'] = array();
@@ -896,6 +908,9 @@ function SetThemeSettings()
 	$settings = $old_settings;
 
 	loadTemplate('Themes');
+
+	// We like Kenny better than Token.
+	createToken('admin-sts');
 }
 
 // Remove a theme from the database.
@@ -906,6 +921,7 @@ function RemoveTheme()
 	checkSession('get');
 
 	isAllowedTo('admin_forum');
+	validateToken('admin-tr', 'request');
 
 	// The theme's ID must be an integer.
 	$_GET['th'] = isset($_GET['th']) ? (int) $_GET['th'] : (int) $_GET['id'];
@@ -1683,11 +1699,9 @@ function EditTheme()
 {
 	global $context, $settings, $scripturl, $boarddir, $smcFunc;
 
+	// !!! Should this be removed?
 	if (isset($_REQUEST['preview']))
-	{
-		// !!! Should this be removed?
-		die;
-	}
+		die('die() with fire');
 
 	isAllowedTo('admin_forum');
 	loadTemplate('Themes');
@@ -1835,7 +1849,7 @@ function EditTheme()
 
 	if (isset($_POST['submit']))
 	{
-		if (checkSession('post', '', false) == '')
+		if (checkSession('post', '', false) == '' && validateToken('admin-te-' . md5($_GET['th'] . '-' . $_REQUEST['filename']), 'post', false) == true)
 		{
 			if (is_array($_POST['entire_file']))
 				$_POST['entire_file'] = implode("\n", $_POST['entire_file']);
@@ -1888,7 +1902,12 @@ function EditTheme()
 			$context['sub_template'] = 'edit_file';
 
 			// Recycle the submitted data.
-			$context['entire_file'] = htmlspecialchars($_POST['entire_file']);
+			if (is_array($_POST['entire_file']))
+				$context['entire_file'] = htmlspecialchars(implode("\n", $_POST['entire_file']));
+			else
+				$context['entire_file'] = htmlspecialchars($_POST['entire_file']);
+
+			$context['edit_filename'] = htmlspecialchars($_POST['filename']);
 
 			// You were able to submit it, so it's reasonable to assume you are allowed to save.
 			$context['allow_save'] = true;
@@ -1947,6 +1966,9 @@ function EditTheme()
 
 		$context['entire_file'] = htmlspecialchars(strtr(file_get_contents($theme_dir . '/' . $_REQUEST['filename']), array("\t" => '   ')));
 	}
+
+	// Create a special token to allow editing of multiple files.
+	createToken('admin-te-' . md5($_GET['th'] . '-' . $_REQUEST['filename']));
 }
 
 function get_file_listing($path, $relative)

+ 13 - 0
Themes/default/Admin.template.php

@@ -667,6 +667,7 @@ function template_edit_censored()
 			</div>
 
 			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+			<input type="hidden" name="', $context['admin-censor_token_var'], '" value="', $context['admin-censor_token'], '" />
 		</form>
 	</div>
 	<br class="clear" />';
@@ -979,6 +980,16 @@ function template_show_settings()
 				<span class="botslice"><span></span></span>
 			</div>';
 
+
+	// At least one token has to be used!
+	if (isset($context['admin-ssc_token']))
+		echo '
+		<input type="hidden" name="', $context['admin-ssc_token_var'], '" value="', $context['admin-ssc_token'], '" />';
+
+	if (isset($context['admin-dbsc_token']))
+		echo '
+		<input type="hidden" name="', $context['admin-dbsc_token_var'], '" value="', $context['admin-dbsc_token'], '" />';
+
 	echo '
 		<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
 		</form>
@@ -1257,6 +1268,7 @@ function template_edit_profile_field()
 				<span class="botslice"><span></span></span>
 			</div>
 			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+			<input type="hidden" name="', $context['admin-ecp_token_var'], '" value="', $context['admin-ecp_token'], '" />
 		</form>
 	</div>
 	<br class="clear" />';
@@ -1415,6 +1427,7 @@ function template_core_features()
 	echo '
 			<div class="righttext">
 				<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+				<input type="hidden" name="', $context['admin-core_token_var'], '" value="', $context['admin-core_token'], '" />
 				<input type="hidden" value="0" name="js_worked" id="js_worked" />
 				<input type="submit" value="', $txt['save'], '" name="save" class="button_submit" />
 			</div>

+ 1 - 0
Themes/default/Errors.template.php

@@ -168,6 +168,7 @@ function template_error_log()
 			<input type="hidden" name="desc" value="1" />';
 	echo '
 			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+			<input type="hidden" name="', $context['admin-el_token_var'], '" value="', $context['admin-el_token'], '" />
 		</form>';
 }
 

+ 8 - 0
Themes/default/Login.template.php

@@ -71,6 +71,8 @@ function template_login()
 				<p><input type="submit" value="', $txt['login'], '" class="button_submit" /></p>
 				<p class="smalltext"><a href="', $scripturl, '?action=reminder">', $txt['forgot_your_password'], '</a></p>
 				<input type="hidden" name="hash_passwrd" value="" />
+				<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+				<input type="hidden" name="', $context['login_token_var'], '" value="', $context['login_token'], '" />
 			</div>
 			<span class="lowerframe"><span></span></span>
 		</div></form>';
@@ -139,6 +141,8 @@ function template_kick_guest()
 				<p class="centertext smalltext"><a href="', $scripturl, '?action=reminder">', $txt['forgot_your_password'], '</a></p>
 			</div>
 			<span class="lowerframe"><span></span></span>
+			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+			<input type="hidden" name="', $context['login_token_var'], '" value="', $context['login_token'], '" />
 			<input type="hidden" name="hash_passwrd" value="" />
 		</div>
 	</form>';
@@ -186,6 +190,8 @@ function template_maintenance()
 		</div>
 		<span class="lowerframe"><span></span></span>
 		<input type="hidden" name="hash_passwrd" value="" />
+		<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+		<input type="hidden" name="', $context['login_token_var'], '" value="', $context['login_token'], '" />
 	</div>
 </form>';
 }
@@ -217,6 +223,8 @@ function template_admin_login()
 			<strong>', $txt['password'], ':</strong>
 			<input type="password" name="admin_pass" size="24" class="input_password" />
 			<a href="', $scripturl, '?action=helpadmin;help=securityDisable_why" onclick="return reqWin(this.href);" class="help"><img src="', $settings['images_url'], '/helptopics.gif" alt="', $txt['help'], '" /></a><br />
+			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+			<input type="hidden" name="', $context['admin-login_token_var'], '" value="', $context['admin-login_token'], '" />
 			<input type="submit" style="margin-top: 1em;" value="', $txt['login'], '" class="button_submit" />';
 
 	// Make sure to output all the old post data.

+ 3 - 0
Themes/default/ManageBans.template.php

@@ -169,6 +169,7 @@ function template_ban_edit()
 							<input type="hidden" name="old_expire" value="', $context['ban']['expiration']['days'], '" />
 							<input type="hidden" name="bg" value="', $context['ban']['id'], '" />
 							<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+							<input type="hidden" name="', $context['admin-bet_token_var'], '" value="', $context['admin-bet_token'], '" />
 						</div>
 					</form>
 				</div>
@@ -233,6 +234,7 @@ function template_ban_edit()
 				<br class="clear" />
 				<input type="hidden" name="bg" value="', $context['ban']['id'], '" />
 				<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+				<input type="hidden" name="', $context['admin-bet_token_var'], '" value="', $context['admin-bet_token'], '" />
 			</form>';
 
 	}
@@ -337,6 +339,7 @@ function template_ban_edit_trigger()
 			<input type="hidden" name="bi" value="' . $context['ban_trigger']['id'] . '" />
 			<input type="hidden" name="bg" value="' . $context['ban_trigger']['group'] . '" />
 			<input type="hidden" name="' . $context['session_var'] . '" value="' . $context['session_id'] . '" />
+			<input type="hidden" name="', $context['admin-bet_token_var'], '" value="', $context['admin-bet_token'], '" />
 		</form>
 	</div>
 	<br class="clear" />

+ 2 - 1
Themes/default/ManageBoards.template.php

@@ -487,7 +487,8 @@ function template_modify_board()
 
 	echo '
 					<input type="hidden" name="rid" value="', $context['redirect_location'], '" />
-					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />';
+					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-be-' . $context['board']['id'] . '_token_var'], '" value="', $context['admin-be-' . $context['board']['id'] . '_token'], '" />';
 
 	// If this board has no children don't bother with the next confirmation screen.
 	if ($context['board']['no_children'])

+ 1 - 0
Themes/default/ManageLanguages.template.php

@@ -348,6 +348,7 @@ function template_modify_language_entries()
 	echo '
 					</select>
 					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-mlang_token_var'], '" value="', $context['admin-mlang_token'], '" />
 					<input type="submit" value="', $txt['go'], '" class="button_submit" />
 			</div>';
 

+ 12 - 0
Themes/default/ManageMaintenance.template.php

@@ -34,6 +34,7 @@ function template_maintain_database()
 					<p>', $txt['maintain_optimize_info'], '</p>
 					<span><input type="submit" value="', $txt['maintain_run_now'], '" class="button_submit" /></span>
 					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-maint_token_var'], '" value="', $context['admin-maint_token'], '" />
 				</form>
 			</div>
 			<span class="botslice"><span></span></span>
@@ -63,6 +64,7 @@ function template_maintain_database()
 
 	echo '
 					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-maint_token_var'], '" value="', $context['admin-maint_token'], '" />
 				</form>
 			</div>
 			<span class="botslice"><span></span></span>
@@ -83,6 +85,7 @@ function template_maintain_database()
 					', !empty($modSettings['search_index']) && $modSettings['search_index'] == 'fulltext' ? '<p class="error">' . $txt['utf8_cannot_convert_fulltext'] . '</p>' : '', '
 					<span><input type="submit" value="', $txt['maintain_run_now'], '" class="button_submit" ', !empty($modSettings['search_index']) && $modSettings['search_index'] == 'fulltext' ? 'disabled="disabled"' : '', '/></span>
 					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-maint_token_var'], '" value="', $context['admin-maint_token'], '" />
 				</form>
 			</div>
 			<span class="botslice"><span></span></span>
@@ -103,6 +106,7 @@ function template_maintain_database()
 					<p>', $txt['entity_convert_introduction'], '</p>
 					<span><input type="submit" value="', $txt['maintain_run_now'], '" class="button_submit" /></span>
 					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-maint_token_var'], '" value="', $context['admin-maint_token'], '" />
 				</form>
 			</div>
 			<span class="botslice"><span></span></span>
@@ -153,6 +157,7 @@ function template_maintain_routine()
 					<p>', $txt['maintain_errors_info'], '</p>
 					<span><input type="submit" value="', $txt['maintain_run_now'], '" class="button_submit" /></span>
 					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-maint_token_var'], '" value="', $context['admin-maint_token'], '" />
 				</form>
 			</div>
 			<span class="botslice"><span></span></span>
@@ -167,6 +172,7 @@ function template_maintain_routine()
 					<p>', $txt['maintain_recount_info'], '</p>
 					<span><input type="submit" value="', $txt['maintain_run_now'], '" class="button_submit" /></span>
 					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-maint_token_var'], '" value="', $context['admin-maint_token'], '" />
 				</form>
 			</div>
 			<span class="botslice"><span></span></span>
@@ -181,6 +187,7 @@ function template_maintain_routine()
 					<p>', $txt['maintain_logs_info'], '</p>
 					<span><input type="submit" value="', $txt['maintain_run_now'], '" class="button_submit" /></span>
 					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-maint_token_var'], '" value="', $context['admin-maint_token'], '" />
 				</form>
 			</div>
 			<span class="botslice"><span></span></span>
@@ -195,6 +202,7 @@ function template_maintain_routine()
 					<p>', $txt['maintain_cache_info'], '</p>
 					<span><input type="submit" value="', $txt['maintain_run_now'], '" class="button_submit" /></span>
 					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-maint_token_var'], '" value="', $context['admin-maint_token'], '" />
 				</form>
 			</div>
 			<span class="botslice"><span></span></span>
@@ -303,6 +311,7 @@ function template_maintain_members()
 					</p>
 					<span><input type="submit" id="do_attribute" value="', $txt['reattribute'], '" onclick="if (!checkAttributeValidity()) return false; return confirm(warningMessage);" class="button_submit" /></span>
 					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-maint_token_var'], '" value="', $context['admin-maint_token'], '" />
 				</form>
 			</div>
 			<span class="botslice"><span></span></span>
@@ -336,6 +345,7 @@ function template_maintain_members()
 					</div>
 					<span><input type="submit" value="', $txt['maintain_old_remove'], '" onclick="return confirm(\'', $txt['maintain_members_confirm'], '\');" class="button_submit" /></span>
 					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-maint_token_var'], '" value="', $context['admin-maint_token'], '" />
 				</form>
 			</div>
 			<span class="botslice"><span></span></span>
@@ -462,6 +472,7 @@ function template_maintain_topics()
 					</div>
 					<span><input type="submit" value="', $txt['maintain_old_remove'], '" onclick="return confirm(\'', $txt['maintain_old_confirm'], '\');" class="button_submit" /></span>
 					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-maint_token_var'], '" value="', $context['admin-maint_token'], '" />
 				</form>
 			</div>
 			<span class="botslice"><span></span></span>
@@ -587,6 +598,7 @@ function template_convert_utf8()
 					</dl>
 					<input type="submit" value="', $txt['utf8_proceed'], '" class="button_submit" />
 					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-maint_token_var'], '" value="', $context['admin-maint_token'], '" />
 					<input type="hidden" name="proceed" value="1" />
 				</form>
 			</div>

+ 2 - 0
Themes/default/ManageMembergroups.template.php

@@ -153,6 +153,7 @@ function template_new_group()
 	}
 	echo '
 			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+			<input type="hidden" name="', $context['admin-mmg_token_var'], '" value="', $context['admin-mmg_token'], '" />
 		</form>
 	</div>
 	<br class="clear" />';
@@ -332,6 +333,7 @@ function template_edit_group()
 				<span class="botslice"><span></span></span>
 			</div>
 			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+			<input type="hidden" name="', $context['admin-mmg_token_var'], '" value="', $context['admin-mmg_token'], '" />
 		</form>
 	</div>
 	<br class="clear" />

+ 2 - 0
Themes/default/ManagePaid.template.php

@@ -206,6 +206,7 @@ function template_modify_subscription()
 					<div class="righttext">
 						<input type="submit" name="save" value="', $txt['paid_settings_save'], '" class="button_submit" />
 						<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+						<input type="hidden" name="', $context['admin-pms_token_var'], '" value="', $context['admin-pms_token'], '" />
 					</div>
 				</div>
 				<span class="botslice"><span></span></span>
@@ -233,6 +234,7 @@ function template_delete_subscription()
 
 					<input type="submit" name="delete_confirm" value="', $txt['paid_delete_subscription'], '" class="button_submit" />
 					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-pmsd_token_var'], '" value="', $context['admin-pmsd_token'], '" />
 				</div>
 				<span class="botslice"><span></span></span>
 			</div>

+ 8 - 2
Themes/default/ManagePermissions.template.php

@@ -245,7 +245,8 @@ function template_permission_index()
 			<input type="hidden" name="pid" value="', $context['profile']['id'], '" />';
 
 		echo '
-			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />';
+			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+			<input type="hidden" name="', $context['admin-mpq_token_var'], '" value="', $context['admin-mpq_token'], '" />';
 	}
 	else
 		echo '
@@ -350,6 +351,7 @@ function template_by_board()
 
 	echo '
 			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+			<input type="hidden" name="', $context['admin-mpb_token_var'], '" value="', $context['admin-mpb_token'], '" />
 		</div>
 	</form>
 	<br class="clear" />';
@@ -406,7 +408,8 @@ function template_edit_profiles()
 				</tbody>
 			</table>
 			<div class="righttext padding">
-				<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />';
+				<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+				<input type="hidden" name="', $context['admin-mpp_token_var'], '" value="', $context['admin-mpp_token'], '" />';
 
 	if ($context['can_edit_something'])
 		echo '
@@ -447,6 +450,7 @@ function template_edit_profiles()
 					</dl>
 					<div class="righttext">
 						<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+						<input type="hidden" name="', $context['admin-mpp_token_var'], '" value="', $context['admin-mpp_token'], '" />
 						<input type="submit" name="create" value="', $txt['permissions_profile_new_create'], '" class="button_submit" />
 					</div>
 				</div>
@@ -554,6 +558,7 @@ function template_modify_group()
 
 	echo '
 			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+			<input type="hidden" name="', $context['admin-mp_token_var'], '" value="', $context['admin-mp_token'], '" />
 		</form>
 	</div>
 	<br class="clear" />';
@@ -1177,6 +1182,7 @@ function template_postmod_permissions()
 			</table>
 			<div class="righttext padding">
 				<input type="submit" name="save_changes" value="', $txt['permissions_commit'], '" class="button_submit" />
+				<input type="hidden" name="', $context['admin-mppm_token_var'], '" value="', $context['admin-mppm_token'], '" />
 			</div>
 		</form>
 		<p class="smalltext" style="padding-left: 10px;">

+ 1 - 0
Themes/default/ManageScheduledTasks.template.php

@@ -82,6 +82,7 @@ function template_edit_scheduled_tasks()
 					</dl>
 					<div class="righttext">
 						<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+						<input type="hidden" name="', $context['admin-st_token_var'], '" value="', $context['admin-st_token'], '" />
 						<input type="submit" name="save" value="', $txt['scheduled_tasks_save_changes'], '" class="button_submit" />
 					</div>
 				</div>

+ 4 - 1
Themes/default/ManageSearch.template.php

@@ -81,7 +81,8 @@ function template_modify_weights()
 						</dd>
 					</dl>
 					<input type="submit" name="save" value="', $txt['search_weights_save'], '" class="button_submit floatright" />
-					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" /><br class="clear" />
+					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-msw_token_var'], '" value="', $context['admin-msw_token'], '" /><br class="clear" />
 				</div>
 				<span class="botslice"><span></span></span>
 			</div>
@@ -225,6 +226,7 @@ function template_select_search_method()
 					<div class="clear">
 						<input type="submit" name="save" value="', $txt['search_method_save'], '" class="button_submit floatright" />
 						<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+						<input type="hidden" name="', $context['admin-msm_token_var'], '" value="', $context['admin-msm_token'], '" />
 					</div>
 				</div>
 				<span class="botslice clear"><span></span></span>
@@ -381,6 +383,7 @@ function template_spider_edit()
 						</dd>
 					</dl>
 					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-ses_token_var'], '" value="', $context['admin-ses_token'], '" />
 					<input type="submit" name="save" value="', $context['page_title'], '" class="button_submit" />
 				</div>
 				<span class="botslice"><span></span></span>

+ 7 - 0
Themes/default/Register.template.php

@@ -37,6 +37,8 @@ function template_registration_agreement()
 				<input type="submit" name="accept_agreement" value="', $txt['agreement_agree'], '" class="button_submit" />';
 
 	echo '
+			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+			<input type="hidden" name="', $context['register_token_var'], '" value="', $context['register_token'], '" />
 			</div>
 			<input type="hidden" name="step" value="1" />
 		</form>';
@@ -349,6 +351,8 @@ function template_registration_form()
 			<div id="confirm_buttons">
 				<input type="submit" name="regSubmit" value="', $txt['register'], '" tabindex="', $context['tabindex']++, '" class="button_submit" />
 			</div>
+			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+			<input type="hidden" name="', $context['register_token_var'], '" value="', $context['register_token'], '" />
 			<input type="hidden" name="step" value="2" />
 		</form>
 		<script type="text/javascript"><!-- // --><![CDATA[
@@ -606,6 +610,7 @@ function template_admin_register()
 			</div>
 			<span class="botslice"><span></span></span>
 			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+			<input type="hidden" name="', $context['admin-regc_token_var'], '" value="', $context['admin-regc_token'], '" />
 		</form>
 	</div>
 	<br class="clear" />';
@@ -672,6 +677,7 @@ function template_edit_agreement()
 						<input type="hidden" name="agree_lang" value="', $context['current_agreement'], '" />
 						<input type="hidden" name="sa" value="agreement" />
 						<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+						<input type="hidden" name="', $context['admin-rega_token_var'], '" value="', $context['admin-rega_token'], '" />
 					</div>
 				</form>
 			</div>
@@ -708,6 +714,7 @@ function template_edit_reserved_words()
 			<span class="botslice"><span></span></span>
 			<input type="hidden" name="sa" value="reservednames" />
 			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+			<input type="hidden" name="', $context['admin-regr_token_var'], '" value="', $context['admin-regr_token'], '" />
 		</form>
 		<br class="clear" />';
 }

+ 4 - 0
Themes/default/Reminder.template.php

@@ -33,6 +33,7 @@ function template_main()
 			<span class="lowerframe"><span></span></span>
 		</div>
 		<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+		<input type="hidden" name="', $context['remind_token_var'], '" value="', $context['remind_token'], '" />
 	</form>';
 }
 
@@ -64,6 +65,7 @@ function template_reminder_pick()
 		</div>
 		<input type="hidden" name="uid" value="', $context['current_member']['id'], '" />
 		<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+		<input type="hidden" name="', $context['remind_token_var'], '" value="', $context['remind_token'], '" />
 	</form>';
 }
 
@@ -118,6 +120,7 @@ function template_set_password()
 		<input type="hidden" name="code" value="', $context['code'], '" />
 		<input type="hidden" name="u" value="', $context['memID'], '" />
 		<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+		<input type="hidden" name="', $context['remind-sp_token_var'], '" value="', $context['remind-sp_token'], '" />
 	</form>
 	<script type="text/javascript"><!-- // --><![CDATA[
 	var regTextStrings = {
@@ -177,6 +180,7 @@ function template_ask()
 		</div>
 		<input type="hidden" name="uid" value="', $context['remind_user'], '" />
 		<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+		<input type="hidden" name="', $context['remind-sai_token_var'], '" value="', $context['remind-sai_token'], '" />
 	</form>';
 
 	if ($context['account_type'] == 'password')

+ 15 - 3
Themes/default/Themes.template.php

@@ -96,6 +96,7 @@ function template_main()
 				<span class="botslice"><span></span></span>
 			</div>
 			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+			<input type="hidden" name="', $context['admin-tm_token_var'], '" value="', $context['admin-tm_token'], '" />
 		</form>';
 
 	// Link to simplemachines.org for latest themes and info!
@@ -171,6 +172,7 @@ function template_main()
 				<span class="botslice"><span></span></span>
 			</div>
 			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+			<input type="hidden" name="', $context['admin-tm_token_var'], '" value="', $context['admin-tm_token'], '" />
 		</form>
 	</div>
 	<br class="clear" />
@@ -237,7 +239,7 @@ function template_list_themes()
 			// You *cannot* delete the default theme. It's important!
 			if ($theme['id'] != 1)
 				echo '
-					<span class="floatright"><a href="', $scripturl, '?action=admin;area=theme;sa=remove;th=', $theme['id'], ';', $context['session_var'], '=', $context['session_id'], '" onclick="return confirm(\'', $txt['theme_remove_confirm'], '\');"><img src="', $settings['images_url'], '/icons/delete.gif" alt="', $txt['theme_remove'], '" title="', $txt['theme_remove'], '" /></a></span>';
+					<span class="floatright"><a href="', $scripturl, '?action=admin;area=theme;sa=remove;th=', $theme['id'], ';', $context['session_var'], '=', $context['session_id'], ';', $context['admin-tr_token_var'], '=', $context['admin-tr_token'], '" onclick="return confirm(\'', $txt['theme_remove_confirm'], '\');"><img src="', $settings['images_url'], '/icons/delete.gif" alt="', $txt['theme_remove'], '" title="', $txt['theme_remove'], '" /></a></span>';
 
 			echo '
 				</h3>
@@ -283,6 +285,7 @@ function template_list_themes()
 					</dl>
 					<input type="submit" name="submit" value="', $txt['themeadmin_list_reset_go'], '" class="button_submit" />
 					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-tl_token_var'], '" value="', $context['admin-tl_token'], '" />
 				</div>
 				<span class="botslice"><span></span></span>
 			</div>
@@ -327,7 +330,7 @@ function template_reset_list()
 						<a href="', $scripturl, '?action=admin;area=theme;th=', $theme['id'], ';', $context['session_var'], '=', $context['session_id'], ';sa=reset;who=1">', $txt['themeadmin_reset_members'], '</a>
 					</li>
 					<li>
-						<a href="', $scripturl, '?action=admin;area=theme;th=', $theme['id'], ';', $context['session_var'], '=', $context['session_id'], ';sa=reset;who=2" onclick="return confirm(\'', $txt['themeadmin_reset_remove_confirm'], '\');">', $txt['themeadmin_reset_remove'], '</a> <em class="smalltext">(', $theme['num_members'], ' ', $txt['themeadmin_reset_remove_current'], ')</em>
+						<a href="', $scripturl, '?action=admin;area=theme;th=', $theme['id'], ';', $context['session_var'], '=', $context['session_id'], ';sa=reset;who=2;', $context['admin-stor_token_var'], '=', $context['admin-stor_token'], '" onclick="return confirm(\'', $txt['themeadmin_reset_remove_confirm'], '\');">', $txt['themeadmin_reset_remove'], '</a> <em class="smalltext">(', $theme['num_members'], ' ', $txt['themeadmin_reset_remove_current'], ')</em>
 					</li>
 				</ul>
 			</div>
@@ -411,6 +414,7 @@ function template_set_options()
 					<div class="righttext">
 						<input type="submit" name="submit" value="', $txt['save'], '" class="button_submit" />
 						<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+						<input type="hidden" name="', $context['admin-sto_token_var'], '" value="', $context['admin-sto_token'], '" />
 					</div>
 				</div>
 				<span class="botslice"><span></span></span>
@@ -626,6 +630,7 @@ function template_set_settings()
 				<span class="botslice"><span></span></span>
 			</div>
 			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+			<input type="hidden" name="', $context['admin-sts_token_var'], '" value="', $context['admin-sts_token'], '" />
 		</form>
 	</div>
 	<br class="clear" />';
@@ -1167,7 +1172,14 @@ function template_edit_file()
 					<textarea name="entire_file" id="entire_file" cols="80" rows="20" class="edit_file">', $context['entire_file'], '</textarea><br />
 					<input type="submit" name="submit" value="', $txt['theme_edit_save'], '"', $context['allow_save'] ? '' : ' disabled="disabled"', ' class="button_submit" />
 					<input type="hidden" name="filename" value="', $context['edit_filename'], '" />
-					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />';
+
+	// Hopefully it exists.
+	if (isset($context['admin-te-' . md5($context['theme_id'] . '-' . $context['edit_filename']) . '_token']))
+		echo '
+					<input type="text" name="', $context['admin-te-' . md5($context['theme_id'] . '-' . $context['edit_filename']) . '_token_var'], '" value="', $context['admin-te-' . md5($context['theme_id'] . '-' . $context['edit_filename']) . '_token'], '" />';
+
+	echo '
 				</div>
 				<span class="botslice"><span></span></span>
 			</div>

+ 2 - 0
Themes/default/index.template.php

@@ -242,6 +242,8 @@ function template_body_above()
 
 		echo '
 					<input type="hidden" name="hash_passwrd" value="" />
+					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['login_token_var'], '" value="', $context['login_token'], '" />
 				</form>';
 	}
 

+ 1 - 0
Themes/default/languages/Admin.english.php

@@ -38,6 +38,7 @@ $txt['admin_config'] = 'Configuration';
 $txt['admin_version_check'] = 'Detailed Version Check';
 $txt['admin_smffile'] = 'SMF File';
 $txt['admin_smfpackage'] = 'SMF Package';
+$txt['admin_logoff'] = 'Admin End Session';
 $txt['admin_maintenance'] = 'Maintenance';
 $txt['admin_image_text'] = 'Show buttons as images instead of text';
 $txt['admin_credits'] = 'Credits';

+ 1 - 0
Themes/default/languages/Errors.english.php

@@ -56,6 +56,7 @@ $txt['already_a_mod'] = 'You have chosen a username of an already existing moder
 $txt['session_timeout'] = 'Your session timed out while posting.  Please go back and try again.';
 $txt['session_verify_fail'] = 'Session verification failed.  Please try logging out and back in again, and then try again.';
 $txt['verify_url_fail'] = 'Unable to verify referring url.  Please go back and try again.';
+$txt['token_verify_fail'] = 'Token verification failed.  Please go back and try again.';
 $txt['guest_vote_disabled'] = 'Guests cannot vote in this poll.';
 
 $txt['cannot_access_mod_center'] = 'You do not have permission to access the moderation center.';

+ 8 - 8
Themes/default/license.txt

@@ -1,20 +1,20 @@
 Copyright © 2011 Simple Machines.  All rights reserved.
 
 Developed by: Simple Machines Forum Project
-              Simple Machines
-              http://www.simplemachines.org
+				  Simple Machines
+				  http://www.simplemachines.org
 
 Redistribution and use in source and binary forms, with or without 
 modification, are permitted provided that the following conditions are met:
   1. Redistributions of source code must retain the above copyright notice,
-     this list of conditions and the following disclaimers.
+	  this list of conditions and the following disclaimers.
   2. Redistributions in binary form must reproduce the above copyright
-     notice, this list of conditions and the following disclaimers in the
-     documentation and/or other materials provided with the distribution.
+	  notice, this list of conditions and the following disclaimers in the
+	  documentation and/or other materials provided with the distribution.
   3. Neither the names of Simple Machines Forum, Simple Machines, nor
-     the names of its contributors may be used to endorse or promote 
-     products derived from this Software without specific prior written
-     permission.
+	  the names of its contributors may be used to endorse or promote 
+	  products derived from this Software without specific prior written
+	  permission.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,