Browse Source

! 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 13 years ago
parent
commit
f9cb33a75c
46 changed files with 439 additions and 28 deletions
  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,