Browse Source

Merge pull request #13 from emanuele45/master

what do you think? Is it time for a pull? :P
Spuds 13 years ago
parent
commit
5190290c50

+ 18 - 49
Sources/Admin.php

@@ -860,27 +860,27 @@ function AdminSearchOM()
 {
 	global $context, $sourcedir;
 
-	$docsURL = 'docs.simplemachines.org';
-	$context['doc_scripturl'] = 'http://docs.simplemachines.org/index.php';
+	$context['doc_apiurl'] = 'http://wiki.simplemachines.org/api.php';
+	$context['doc_scripturl'] = 'http://wiki.simplemachines.org/smf/';
 
 	// Set all the parameters search might expect.
-	$postVars = array(
-		'search' => $context['search_term'],
-	);
+	$postVars = explode(' ', $context['search_term']);
 
 	// Encode the search data.
 	foreach ($postVars as $k => $v)
-		$postVars[$k] = urlencode($k) . '=' . urlencode($v);
+		$postVars[$k] = urlencode($v);
 
 	// This is what we will send.
-	$postVars = implode('&', $postVars);
+	$postVars = implode('+', $postVars);
 
 	// Get the results from the doc site.
 	require_once($sourcedir . '/Subs-Package.php');
-	$search_results = fetch_web_data($context['doc_scripturl'] . '?action=search2&xml', $postVars);
+	// Demo URL:
+	// http://wiki.simplemachines.org/api.php?action=query&list=search&srprop=timestamp|snippet&format=xml&srwhat=text&srsearch=template+eval
+	$search_results = fetch_web_data($context['doc_apiurl'] . '?action=query&list=search&srprop=timestamp|snippet&format=xml&srwhat=text&srsearch=' . $postVars);
 
 	// If we didn't get any xml back we are in trouble - perhaps the doc site is overloaded?
-	if (!$search_results || preg_match('~<' . '\?xml\sversion="\d+\.\d+"\sencoding=".+?"\?' . '>\s*(<smf>.+?</smf>)~is', $search_results, $matches) != true)
+	if (!$search_results || preg_match('~<' . '\?xml\sversion="\d+\.\d+"\?>\s*(<api>.+?</api>)~is', $search_results, $matches) != true)
 		fatal_lang_error('cannot_connect_doc_site');
 
 	$search_results = $matches[1];
@@ -892,52 +892,21 @@ function AdminSearchOM()
 	// Get the results loaded into an array for processing!
 	$results = new xmlArray($search_results, false);
 
-	// Move through the smf layer.
-	if (!$results->exists('smf'))
+	// Move through the api layer.
+	if (!$results->exists('api'))
 		fatal_lang_error('cannot_connect_doc_site');
-	$results = $results->path('smf[0]');
 
 	// Are there actually some results?
-	if (!$results->exists('noresults') && !$results->exists('results'))
-		fatal_lang_error('cannot_connect_doc_site');
-	elseif ($results->exists('results'))
+	if ($results->exists('api/query/search/p'))
 	{
-		foreach ($results->set('results/result') as $result)
+		$relevance = 0;
+		foreach ($results->set('api/query/search/p') as $result)
 		{
-			if (!$result->exists('messages'))
-				continue;
-
-			$context['search_results'][$result->fetch('id')] = array(
-				'topic_id' => $result->fetch('id'),
-				'relevance' => $result->fetch('relevance'),
-				'board' => array(
-					'id' => $result->fetch('board/id'),
-					'name' => $result->fetch('board/name'),
-					'href' => $result->fetch('board/href'),
-				),
-				'category' => array(
-					'id' => $result->fetch('category/id'),
-					'name' => $result->fetch('category/name'),
-					'href' => $result->fetch('category/href'),
-				),
-				'messages' => array(),
+			$context['search_results'][$result->fetch('@title')] = array(
+				'title' => $result->fetch('@title'),
+				'relevance' => $relevance++,
+				'snippet' => str_replace('class=\'searchmatch\'', 'class="highlight"', un_htmlspecialchars($result->fetch('@snippet'))),
 			);
-
-			// Add the messages.
-			foreach ($result->set('messages/message') as $message)
-				$context['search_results'][$result->fetch('id')]['messages'][] = array(
-					'id' => $message->fetch('id'),
-					'subject' => $message->fetch('subject'),
-					'body' => $message->fetch('body'),
-					'time' => $message->fetch('time'),
-					'timestamp' => $message->fetch('timestamp'),
-					'start' => $message->fetch('start'),
-					'author' => array(
-						'id' => $message->fetch('author/id'),
-						'name' => $message->fetch('author/name'),
-						'href' => $message->fetch('author/href'),
-					),
-				);
 		}
 	}
 }

+ 5 - 3
Sources/Errors.php

@@ -125,7 +125,7 @@ function fatal_error($error, $log = 'general')
 	if (empty($txt))
 		die($error);
 
-	setup_fatal_error_context($log || (!empty($modSettings['enableErrorLogging']) && $modSettings['enableErrorLogging'] == 2) ? log_error($error, $log) : $error);
+	setup_fatal_error_context($log || (!empty($modSettings['enableErrorLogging']) && $modSettings['enableErrorLogging'] == 2) ? log_error($error, $log) : $error, $error);
 }
 
 /**
@@ -175,7 +175,7 @@ function fatal_lang_error($error, $log = 'general', $sprintf = array())
 		$error_message = empty($sprintf) ? $txt[$error] : vsprintf($txt[$error], $sprintf);
 	}
 
-	setup_fatal_error_context($error_message);
+	setup_fatal_error_context($error_message, $error);
 }
 
 /**
@@ -261,7 +261,7 @@ function error_handler($error_level, $error_string, $file, $line)
  * error sub template.
  * @param string $error_message
  */
-function setup_fatal_error_context($error_message)
+function setup_fatal_error_context($error_message, $error_code)
 {
 	global $context, $txt, $ssi_on_error_method;
 	static $level = 0;
@@ -282,6 +282,8 @@ function setup_fatal_error_context($error_message)
 		$context['error_title'] = $txt['error_occured'];
 	$context['error_message'] = isset($context['error_message']) ? $context['error_message'] : $error_message;
 
+	$context['error_code'] = isset($error_code) ? 'id="' . $error_code . '" ' : '';
+
 	if (empty($context['page_title']))
 		$context['page_title'] = $context['error_title'];
 

+ 2 - 5
Sources/ManageLanguages.php

@@ -85,7 +85,7 @@ function AddLanguage()
 		$language_list = new xmlArray(fetch_web_data($url), true);
 
 		// Check it exists.
-		if (!$language_list->exists('languages'))
+		if (!$language_list->exists('languages/language'))
 			$context['smf_error'] = 'no_response';
 		else
 		{
@@ -833,10 +833,6 @@ function ModifyLanguage()
 			if (preg_match('~^([A-Za-z]+)\.' . $context['lang_id'] . '\.php$~', $entry, $matches) == 0)
 				continue;
 
-			// @todo Temp!
-			if ($matches[1] == 'EmailTemplates')
-				continue;
-
 			if (!isset($context['possible_files'][$theme]))
 				$context['possible_files'][$theme] = array(
 					'id' => $theme,
@@ -851,6 +847,7 @@ function ModifyLanguage()
 			);
 		}
 		$dir->close();
+		usort($context['possible_files'][$theme]['files'], create_function('$val1, $val2', 'return strcmp($val1[\'name\'], $val2[\'name\']);'));
 	}
 
 	// We no longer wish to speak this language.

+ 22 - 10
Sources/ManageSettings.php

@@ -187,7 +187,6 @@ function ModifyCoreFeatures($return_config = false)
 	/* This is an array of all the features that can be enabled/disabled - each option can have the following:
 		title		- Text title of this item (If standard string does not exist).
 		desc		- Description of this feature (If standard string does not exist).
-		image		- Custom image to show next to feature.
 		settings	- Array of settings to change (For each name => value) on enable - reverse is done for disable. If > 1 will not change value if set.
 		setting_callback- Function that returns an array of settings to save - takes one parameter which is value for this feature.
 		save_callback	- Function called on save, takes state as parameter.
@@ -354,18 +353,24 @@ function ModifyCoreFeatures($return_config = false)
 	if (isset($_POST['save']))
 	{
 		checkSession();
+
+	if (isset($_GET['xml']))
+	{
+		$tokenValidation = validateToken('admin-core', 'post', false);
+
+		if (empty($tokenValidation))
+			return 'token_verify_fail';
+	}
+	else
 		validateToken('admin-core');
 
 		$setting_changes = array('admin_features' => array());
 
-		// Are we using the javascript stuff or radios to submit?
-		$post_var_prefix = empty($_POST['js_worked']) ? 'feature_plain_' : 'feature_';
-
 		// Cycle each feature and change things as required!
 		foreach ($core_features as $id => $feature)
 		{
 			// Enabled?
-			if (!empty($_POST[$post_var_prefix . $id]))
+			if (!empty($_POST['feature_' . $id]))
 				$setting_changes['admin_features'][] = $id;
 
 			// Setting values to change?
@@ -373,14 +378,14 @@ function ModifyCoreFeatures($return_config = false)
 			{
 				foreach ($feature['settings'] as $key => $value)
 				{
-					if (empty($_POST[$post_var_prefix . $id]) || (!empty($_POST[$post_var_prefix . $id]) && ($value < 2 || empty($modSettings[$key]))))
-						$setting_changes[$key] = !empty($_POST[$post_var_prefix . $id]) ? $value : !$value;
+					if (empty($_POST['feature_' . $id]) || (!empty($_POST['feature_' . $id]) && ($value < 2 || empty($modSettings[$key]))))
+						$setting_changes[$key] = !empty($_POST['feature_' . $id]) ? $value : !$value;
 				}
 			}
 			// Is there a call back for settings?
 			if (isset($feature['setting_callback']))
 			{
-				$returned_settings = $feature['setting_callback'](!empty($_POST[$post_var_prefix . $id]));
+				$returned_settings = $feature['setting_callback'](!empty($_POST['feature_' . $id]));
 				if (!empty($returned_settings))
 					$setting_changes = array_merge($setting_changes, $returned_settings);
 			}
@@ -404,10 +409,11 @@ function ModifyCoreFeatures($return_config = false)
 		{
 			// Standard save callback?
 			if (isset($feature['save_callback']))
-				$feature['save_callback'](!empty($_POST[$post_var_prefix . $id]));
+				$feature['save_callback'](!empty($_POST['feature_' . $id]));
 		}
 
-		redirectexit('action=admin;area=corefeatures;' . $context['session_var'] . '=' . $context['session_id']);
+		if (!isset($_REQUEST['xml']))
+			redirectexit('action=admin;area=corefeatures;' . $context['session_var'] . '=' . $context['session_id']);
 	}
 
 	// Put them in context.
@@ -417,7 +423,9 @@ function ModifyCoreFeatures($return_config = false)
 			'title' => isset($feature['title']) ? $feature['title'] : $txt['core_settings_item_' . $id],
 			'desc' => isset($feature['desc']) ? $feature['desc'] : $txt['core_settings_item_' . $id . '_desc'],
 			'enabled' => in_array($id, $context['admin_features']),
+			'state' => in_array($id, $context['admin_features']) ? 'on' : 'off',
 			'url' => !empty($feature['url']) ? $scripturl . '?' . $feature['url'] . ';' . $context['session_var'] . '=' . $context['session_id'] : '',
+			'image' => (file_exists($settings['theme_dir'] . '/images/admin/feature_' . $id . '.png') ? $settings['images_url'] : $settings['default_images_url']) . '/admin/feature_' . $id . '.png',
 		);
 
 	// Are they a new user?
@@ -427,6 +435,10 @@ function ModifyCoreFeatures($return_config = false)
 	if ($context['is_new_install'])
 		updateSettings(array('admin_features' => ''));
 
+	// sub_template is already generic_xml and the token is created somewhere else
+	if (isset($_REQUEST['xml']))
+		return;
+
 	$context['sub_template'] = 'core_features';
 	$context['page_title'] = $txt['core_settings_title'];
 

+ 92 - 9
Sources/Profile-Actions.php

@@ -236,6 +236,9 @@ function issueWarning($memID)
 
 	$context['page_title'] = $txt['profile_issue_warning'];
 
+	// Let's use a generic list to get all the current warnings
+	require_once($sourcedir . '/Subs-List.php');
+
 	// Work our the various levels.
 	$context['level_effects'] = array(
 		0 => $txt['profile_warning_effect_none'],
@@ -248,16 +251,96 @@ function issueWarning($memID)
 		if ($context['member']['warning'] >= $limit)
 			$context['current_level'] = $limit;
 
-	// Load up all the old warnings - count first!
-	$context['total_warnings'] = list_getUserWarningCount($memID);
-
-	// Make the page index.
-	$context['start'] = (int) $_REQUEST['start'];
-	$perPage = (int) $modSettings['defaultMaxMessages'];
-	$context['page_index'] = constructPageIndex($scripturl . '?action=profile;u=' . $memID . ';area=issuewarning', $context['start'], $context['total_warnings'], $perPage);
+	$listOptions = array(
+		'id' => 'view_warnings',
+		'title' => $txt['profile_viewwarning_previous_warnings'],
+		'items_per_page' => $modSettings['defaultMaxMessages'],
+		'no_items_label' => $txt['profile_viewwarning_no_warnings'],
+		'base_href' => $scripturl . '?action=profile;area=issuewarning;sa=user;u=' . $memID,
+		'default_sort_col' => 'log_time',
+		'get_items' => array(
+			'function' => 'list_getUserWarnings',
+			'params' => array(
+				$memID,
+			),
+		),
+		'get_count' => array(
+			'function' => 'list_getUserWarningCount',
+			'params' => array(
+				$memID,
+			),
+		),
+		'columns' => array(
+			'issued_by' => array(
+				'header' => array(
+					'value' => $txt['profile_warning_previous_issued'],
+					'style' => 'width: 20%;',
+				),
+				'data' => array(
+					'function' => create_function('$warning', '
+						return $warning[\'issuer\'][\'link\'];
+					'
+					),
+				),
+				'sort' => array(
+					'default' => 'lc.member_name DESC',
+					'reverse' => 'lc.member_name',
+				),
+			),
+			'log_time' => array(
+				'header' => array(
+					'value' => $txt['profile_warning_previous_time'],
+					'style' => 'width: 30%;',
+				),
+				'data' => array(
+					'db' => 'time',
+				),
+				'sort' => array(
+					'default' => 'lc.log_time DESC',
+					'reverse' => 'lc.log_time',
+				),
+			),
+			'reason' => array(
+				'header' => array(
+					'value' => $txt['profile_warning_previous_reason'],
+				),
+				'data' => array(
+					'function' => create_function('$warning', '
+						global $scripturl, $txt, $settings;
+
+						$ret = \'
+						<div class="floatleft">
+							\' . $warning[\'reason\'] . \'
+						</div>\';
+
+						if (!empty($warning[\'id_notice\']))
+							$ret .= \'
+						<div class="floatright">
+							<a href="\' . $scripturl . \'?action=moderate;area=notice;nid=\' . $warning[\'id_notice\'] . \'" onclick="window.open(this.href, \\\'\\\', \\\'scrollbars=yes,resizable=yes,width=400,height=250\\\');return false;" target="_blank" class="new_win" title="\' . $txt[\'profile_warning_previous_notice\'] . \'"><img src="\' . $settings[\'images_url\'] . \'/filter.png" alt="" /></a>
+						</div>\';
+
+						return $ret;'),
+				),
+			),
+			'level' => array(
+				'header' => array(
+					'value' => $txt['profile_warning_previous_level'],
+					'style' => 'width: 6%;',
+				),
+				'data' => array(
+					'db' => 'counter',
+				),
+				'sort' => array(
+					'default' => 'lc.counter DESC',
+					'reverse' => 'lc.counter',
+				),
+			),
+		),
+	);
 
-	// Now do the data itself.
-	$context['previous_warnings'] = list_getUserWarnings($context['start'], $perPage, 'log_time DESC', $memID);
+	// Create the list for viewing.
+	require_once($sourcedir . '/Subs-List.php');
+	createList($listOptions);
 
 	// Are they warning because of a message?
 	if (isset($_REQUEST['msg']) && 0 < (int) $_REQUEST['msg'])

+ 0 - 1
Sources/Profile-View.php

@@ -2129,7 +2129,6 @@ function viewWarning($memID)
 	);
 
 	// Create the list for viewing.
-	require_once($sourcedir . '/Subs-List.php');
 	createList($listOptions);
 
 	// Create some common text bits for the template.

+ 1 - 1
Sources/Profile.php

@@ -142,7 +142,7 @@ function ModifyProfile($post_errors = array())
 				),
 				'viewwarning' => array(
 					'label' => $txt['profile_view_warnings'],
-					'enabled' => in_array('w', $context['admin_features']) && $modSettings['warning_settings'][0] == 1 && $cur_profile['warning'] && $context['user']['is_owner'] && !empty($modSettings['warning_show']),
+					'enabled' => in_array('w', $context['admin_features']) && $modSettings['warning_settings'][0] == 1 && $cur_profile['warning'] && (!empty($modSettings['warning_show']) && ($context['user']['is_owner'] || $modSettings['warning_show'] == 2)),
 					'file' => 'Profile-View.php',
 					'function' => 'viewWarning',
 					'permission' => array(

+ 4 - 1
Sources/Security.php

@@ -83,7 +83,10 @@ function validateSession($type = 'admin')
 	}
 
 	// Need to type in a password for that, man.
-	adminLogin($type);
+	if (!isset($_GET['xml']))
+		adminLogin($type);
+	else
+		return 'session_verify_fail';
 }
 
 /**

+ 90 - 0
Sources/Xml.php

@@ -28,6 +28,9 @@ function XMLhttpMain()
 		'messageicons' => array(
 			'function' => 'ListMessageIcons',
 		),
+		'corefeatures' => array(
+			'function' => 'EnableCoreFeatures',
+		),
 	);
 	if (!isset($_REQUEST['sa'], $sub_actions[$_REQUEST['sa']]))
 		fatal_lang_error('no_access', false);
@@ -71,4 +74,91 @@ function ListMessageIcons()
 	$context['sub_template'] = 'message_icons';
 }
 
+function EnableCoreFeatures()
+{
+	global $context, $smcFunc, $sourcedir, $modSettings, $txt;
+
+	$context['xml_data'] = array();
+	// Just in case, maybe we don't need it
+	loadLanguage('Errors');
+
+	$errors = array();
+	$returns = array();
+	$tokens = array();
+	if (allowedTo('admin_forum'))
+	{
+		$validation = validateSession();
+		if (empty($validation))
+		{
+			require_once($sourcedir . '/ManageSettings.php');
+			$result = ModifyCoreFeatures();
+
+			if (empty($result))
+			{
+				$id = isset($_POST['feature_id']) ? $_POST['feature_id'] : '';
+
+				if (!empty($id) && isset($context['features'][$id]))
+				{
+					$feature = $context['features'][$id];
+
+					$returns[] = array(
+						'value' => (!empty($_POST['feature_' . $id]) && $feature['url'] ? '<a href="' . $feature['url'] . '">' . $feature['title'] . '</a>' : $feature['title']),
+					);
+
+					createToken('admin-core', 'post');
+					$tokens = array(
+						array(
+							'value' => $context['admin-core_token'],
+							'attributes' => array('type' => 'token_var'),
+						),
+						array(
+							'value' => $context['admin-core_token_var'],
+							'attributes' => array('type' => 'token'),
+						),
+					);
+				}
+				else
+				{
+					$errors[] = array(
+						'value' => $txt['feature_no_exists'],
+					);
+				}
+			}
+			else
+			{
+				$errors[] = array(
+					'value' => $txt[$result],
+				);
+			}
+		}
+		else
+		{
+			$errors[] = array(
+				'value' => $txt[$validation],
+			);
+		}
+	}
+	else
+	{
+		$errors[] = array(
+			'value' => $txt['cannot_admin_forum']
+		);
+	}
+
+	$context['sub_template'] = 'generic_xml';
+	$context['xml_data'] = array (
+		'corefeatures' => array (
+			'identifier' => 'corefeature',
+			'children' => $returns,
+		),
+		'tokens' => array (
+			'identifier' => 'token',
+			'children' => $tokens,
+		),
+		'errors' => array (
+			'identifier' => 'error',
+			'children' => $errors,
+		),
+	);
+}
 ?>

+ 83 - 55
Themes/default/Admin.template.php

@@ -1297,12 +1297,10 @@ function template_admin_search_results()
 				echo '
 				<li>
 					<p>
-						<a href="', $context['doc_scripturl'], '?topic=', $result['topic_id'], '.0" target="_blank" class="new_win"><strong>', $result['messages'][0]['subject'], '</strong></a>
-						<br /><span class="smalltext"><a href="', $result['category']['href'], '" target="_blank" class="new_win">', $result['category']['name'], '</a> &nbsp;/&nbsp;
-						<a href="', $result['board']['href'], '" target="_blank" class="new_win">', $result['board']['name'], '</a> /</span>
+						<a href="', $context['doc_scripturl'], str_replace(' ', '_', $result['title']), '" target="_blank" class="new_win"><strong>', $result['title'], '</strong></a>
 					</p>
 					<p class="double_height">
-						', $result['messages'][0]['body'], '
+						', $result['snippet'], '
 					</p>
 				</li>';
 			}
@@ -1339,20 +1337,73 @@ function template_core_features()
 
 	echo '
 	<script type="text/javascript"><!-- // --><![CDATA[
-		function toggleItem(itemID)
-		{
-			// Toggle the hidden item.
-			var itemValueHandle = document.getElementById("feature_" + itemID);
-			itemValueHandle.value = itemValueHandle.value == 1 ? 0 : 1;
-
-			// Change the image, alternative text and the title.
-			document.getElementById("switch_" + itemID).src = \'', $settings['images_url'], '/admin/switch_\' + (itemValueHandle.value == 1 ? \'on\' : \'off\') + \'.png\';
-			document.getElementById("switch_" + itemID).alt = itemValueHandle.value == 1 ? \'', $txt['core_settings_switch_off'], '\' : \'', $txt['core_settings_switch_on'], '\';
-			document.getElementById("switch_" + itemID).title = itemValueHandle.value == 1 ? \'', $txt['core_settings_switch_off'], '\' : \'', $txt['core_settings_switch_on'], '\';
-
-			// Don\'t reload.
-			return false;
-		}
+		var token_name;
+		var token_value;
+		$(document).ready(function() {
+			$(".core_features_hide").css(\'display\', \'none\');
+			$(".core_features_img").css({\'cursor\': \'pointer\', \'display\': \'\'});
+			$("#core_features_submit").css(\'display\', \'none\');
+			if (token_name == undefined)
+				token_name = $("#core_features_token").attr("name")
+			if (token_value == undefined)
+				token_value = $("#core_features_token").attr("value")
+			$(".core_features_img").click(function(){
+				var cc = $(this);
+				var cf = $(this).attr("id").substring(7);
+				var imgs = new Array("', $settings['images_url'], '/admin/switch_off.png", "', $settings['images_url'], '/admin/switch_on.png");
+				var new_state = !$("#feature_" + cf).attr("checked");
+				$("#feature_" + cf).attr("checked", new_state);
+
+				data = {save: "save", feature_id: cf};
+				data[$("#core_features_session").attr("name")] = $("#core_features_session").attr("value");
+				data[token_name] = token_value;
+				$(".core_features_status_box").each(function(){
+					data[$(this).attr("name")] = !$(this).attr("checked") ? 0 : 1;
+				});
+
+				// Launch AJAX request.
+				$.ajax({
+					// The link we are accessing.
+					url: "', $scripturl, '?action=xmlhttp;sa=corefeatures;xml",
+					// The type of request.
+					type: "post",
+					// The type of data that is getting returned.
+					data: data,
+					error: function(error){
+							$("#activation_message").html(error).slideDown(\'fast\');
+					},
+
+					success: function(request){
+						if ($(request).find("errors").find("error").length != 0)
+						{
+							$("#activation_message").attr(\'class\', \'errorbox\');
+							$("#activation_message").html($(request).find("errors").find("error").text()).slideDown(\'fast\');
+						}
+						else if ($(request).find("smf").length != 0)
+						{
+							$("#feature_link_" + cf).html($(request).find("corefeatures").find("corefeature").text());
+							cc.attr("src", imgs[new_state ? 1 : 0]);
+							$("#feature_link_" + cf).fadeOut().fadeIn();
+							$("#activation_message").attr(\'class\', \'infobox\');
+							var message = new_state ? ' . JavaScriptEscape($txt['core_settings_activation_message']) . ' : ' . JavaScriptEscape($txt['core_settings_deactivation_message']) . ';
+							$("#activation_message").html(message.replace(\'{core_feature}\', $(request).find("corefeatures").find("corefeature").text())).slideDown(\'fast\');
+							setTimeout(function() {
+								$("#activation_message").slideUp();
+							}, 5000);
+
+							token_name = $(request).find("tokens").find(\'[type="token"]\').text();
+							token_value = $(request).find("tokens").find(\'[type="token_var"]\').text();
+						}
+						else
+						{
+							$("#activation_message").attr(\'class\', \'errorbox\');
+							$("#activation_message").html(' . JavaScriptEscape($txt['core_settings_generic_error']) . ').slideDown(\'fast\');
+							
+						}
+					}
+				});
+			});
+		});
 	// ]]></script>
 	<div id="admincenter">';
 	if ($context['is_new_install'])
@@ -1369,12 +1420,13 @@ function template_core_features()
 	}
 
 	echo '
-		<form action="', $scripturl, '?action=admin;area=corefeatures;" method="post" accept-charset="', $context['character_set'], '">
+		<form id="core_features" action="', $scripturl, '?action=admin;area=corefeatures" method="post" accept-charset="', $context['character_set'], '">
 			<div class="cat_bar">
 				<h3 class="catbg">
 					', $txt['core_settings_title'], '
 				</h3>
-			</div>';
+			</div>
+			<div style="display:none" id="activation_message" class="errorbox"></div>';
 
 	$alternate = true;
 	$num = 0;
@@ -1386,32 +1438,14 @@ function template_core_features()
 			<div class="windowbg', $alternate ? '2' : '', '">
 				<span class="topslice"><span></span></span>
 				<div class="content features">
-					<img class="features_image" src="', $settings['images_url'], '/admin/feature_', $id, '.png" alt="', $feature['title'], '" />
-					<div class="features_switch" id="js_feature_', $id, '" style="display: none;">
-						<a href="', $scripturl, '?action=admin;area=featuresettings;sa=core;', $context['session_var'], '=', $context['session_id'], ';toggle=', $id, ';state=', $feature['enabled'] ? 0 : 1, '" onclick="return toggleItem(\'', $id, '\');">
-							<input type="hidden" name="feature_', $id, '" id="feature_', $id, '" value="', $feature['enabled'] ? 1 : 0, '" /><img src="', $settings['images_url'], '/admin/switch_', $feature['enabled'] ? 'on' : 'off', '.png" id="switch_', $id, '" style="margin-top: 1.3em;" alt="', $txt['core_settings_switch_' . ($feature['enabled'] ? 'off' : 'on')], '" title="', $txt['core_settings_switch_' . ($feature['enabled'] ? 'off' : 'on')], '" />
-						</a>
+					<img class="features_image" src="', $feature['image'], '" alt="', $feature['title'], '" />
+					<div class="features_switch" id="js_feature_', $id, '">
+							<label class="core_features_hide" for="feature_', $id, '">', $txt['core_settings_enabled'], '<input class="core_features_status_box" type="checkbox" name="feature_', $id, '" id="feature_', $id, '"', $feature['enabled'] ? ' checked="checked"' : '', ' /></label>
+							<img class="core_features_img ', $feature['state'], '" src="', $settings['images_url'], '/admin/switch_', $feature['state'], '.png" id="switch_', $id, '" style="margin-top: 1.3em;display:none" alt="', $txt['core_settings_switch_' . $feature['state']], '" title="', $txt['core_settings_switch_' . $feature['state']], '" />
 					</div>
-					<h4>', ($feature['enabled'] && $feature['url'] ? '<a href="' . $feature['url'] . '">' . $feature['title'] . '</a>' : $feature['title']), '</h4>
+					<h4 id="feature_link_' . $id . '">', ($feature['enabled'] && $feature['url'] ? '<a href="' . $feature['url'] . '">' . $feature['title'] . '</a>' : $feature['title']), '</h4>
 					<p>', $feature['desc'], '</p>
-					<div id="plain_feature_', $id, '">
-						<label for="plain_feature_', $id, '_radio_on"><input type="radio" name="feature_plain_', $id, '" id="plain_feature_', $id, '_radio_on" value="1"', $feature['enabled'] ? ' checked="checked"' : '', ' class="input_radio" />', $txt['core_settings_enabled'], '</label>
-						<label for="plain_feature_', $id, '_radio_off"><input type="radio" name="feature_plain_', $id, '" id="plain_feature_', $id, '_radio_off" value="0"', !$feature['enabled'] ? ' checked="checked"' : '', ' class="input_radio" />', $txt['core_settings_disabled'], '</label>
-					</div>
-				</div>';
-				
-		// last feature, show the save button
-		if ($num == $num_features)
-			echo '
-				<div class="content">
-					<hr class="color clear" />
-					<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>';
-	
-		echo '
+				</div>
 				<span class="botslice clear_right"><span></span></span>
 			</div>';
 
@@ -1419,20 +1453,14 @@ function template_core_features()
 	}
 
 	echo '
+			<div class="righttext">
+				<input id="core_features_session" type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+				<input id="core_features_token" type="hidden" name="', $context['admin-core_token_var'], '" value="', $context['admin-core_token'], '" />
+				<input id="core_features_submit" type="submit" value="', $txt['save'], '" name="save" class="button_submit" />
+			</div>
 		</form>
 	</div>
 	<br class="clear" />';
-
-	// Turn on the pretty javascript if we can!
-	echo '
-	<script type="text/javascript"><!-- // --><![CDATA[
-		document.getElementById(\'js_worked\').value = "1";';
-		foreach ($context['features'] as $id => $feature)
-			echo '
-		document.getElementById(\'js_feature_', $id, '\').style.display = "";
-		document.getElementById(\'plain_feature_', $id, '\').style.display = "none";';
-	echo '
-	// ]]></script>';
 }
 
 

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

@@ -30,7 +30,7 @@ function template_fatal_error()
 		</div>
 		<div class="windowbg">
 			<span class="topslice"><span></span></span>
-			<div class="padding">', $context['error_message'], '</div>
+			<div ', $context['error_code'], 'class="padding">', $context['error_message'], '</div>
 			<span class="botslice"><span></span></span>
 		</div>
 	</div>';

+ 1 - 1
Themes/default/ManageBans.template.php

@@ -40,7 +40,7 @@ function template_ban_edit()
 							<input type="text" name="ban_name" id="ban_name" value="', $context['ban']['name'], '" size="47" maxlength="60" class="input_text" />
 						</dd>
 						<dt>
-							<strong><label for="reason">', $txt['ban_reason'], ':<label></strong><br />
+							<strong><label for="reason">', $txt['ban_reason'], ':</label></strong><br />
 							<span class="smalltext">', $txt['ban_reason_desc'], '</span>
 						</dt>
 						<dd>

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

@@ -26,7 +26,7 @@ function template_new_group()
 
 	echo '
 	<div id="admincenter">
-		<form action="', $scripturl, '?action=admin;area=membergroups;sa=add" method="post" accept-charset="', $context['character_set'], '">
+		<form id="new_group" action="', $scripturl, '?action=admin;area=membergroups;sa=add" method="post" accept-charset="', $context['character_set'], '">
 			<div class="cat_bar">
 				<h3 class="catbg">', $txt['membergroups_new_group'], '</h3>
 			</div>
@@ -128,7 +128,7 @@ function template_new_group()
 	{
 		echo '
 									<li class="category">
-										<a href="javascript:void(0);" onclick="selectBoards([', implode(', ', $category['child_ids']), ']); return false;">', $category['name'], '</a>
+										<a href="javascript:void(0);" onclick="selectBoards([', implode(', ', $category['child_ids']), '], \'new_group\'); return false;">', $category['name'], '</a>
 									<ul>';
 
 		foreach ($category['boards'] as $board)
@@ -336,7 +336,7 @@ function template_edit_group()
 		{
 			echo '
 									<li class="category">
-										<a href="javascript:void(0);" onclick="selectBoards([', implode(', ', $category['child_ids']), ']); return false;">', $category['name'], '</a>
+										<a href="javascript:void(0);" onclick="selectBoards([', implode(', ', $category['child_ids']), '], \'groupForm\'); return false;">', $category['name'], '</a>
 										<ul>';
 
 			foreach ($category['boards'] as $board)

+ 9 - 59
Themes/default/Profile.template.php

@@ -1970,7 +1970,7 @@ function template_ignoreboards()
 
 		echo '
 					<li class="category">
-						<a href="javascript:void(0);" onclick="selectBoards([', implode(', ', $category['child_ids']), ']); return false;">', $category['name'], '</a>
+						<a href="javascript:void(0);" onclick="selectBoards([', implode(', ', $category['child_ids']), '], \'creator\'); return false;">', $category['name'], '</a>
 						<ul>';
 
 		foreach ($category['boards'] as $board)
@@ -2041,13 +2041,14 @@ function template_viewWarning()
 	template_load_warning_variables();
 
 	echo '
-		<div class="title_bar">
-			<h3 class="titlebg">
+		<div class="cat_bar">
+			<h3 class="catbg">
 				<span class="ie6_header floatleft"><img src="', $settings['images_url'], '/icons/profile_sm.png" alt="" class="icon" />
 				', sprintf($txt['profile_viewwarning_for_user'], $context['member']['name']), '
 				</span>
 			</h3>
 		</div>
+		<p class="description">', $txt['viewWarning_help'], '</p>
 		<div class="windowbg">
 			<span class="topslice"><span></span></span>
 			<div class="content">
@@ -2165,6 +2166,7 @@ function template_issueWarning()
 			size = barWidth * (percent/100);
 
 			setInnerHTML(document.getElementById(\'warning_text\'), percent + "%");
+			document.getElementById(\'warning_text\').innerHTML = percent + "%";
 			document.getElementById(\'warning_level\').value = percent;
 			document.getElementById(\'warning_progress\').style.width = size + "px";
 
@@ -2346,66 +2348,14 @@ function template_issueWarning()
 					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
 					<input type="submit" name="save" value="', $context['user']['is_owner'] ? $txt['change_profile'] : $txt['profile_warning_issue'], '" class="button_submit" />
 				</div>
+				<br class="clear" />
 			</div>
 			<span class="botslice"><span></span></span>
 		</div>
-	</form>';
-
-	// Previous warnings?
-	echo '<br />
-		<div class="cat_bar">
-			<h3 class="catbg">
-				', $txt['profile_warning_previous'], '
-			</h3>
-		</div>
-		<table border="0" width="100%" cellspacing="0" cellpadding="5" class="table_grid">
-			<thead>
-				<tr class="titlebg lefttext">
-					<th class="first_th" scope="col" width="20%">', $txt['profile_warning_previous_issued'], '</th>
-					<th scope="col" width="30%">', $txt['profile_warning_previous_time'], '</th>
-					<th scope="col">', $txt['profile_warning_previous_reason'], '</th>
-					<th class="last_th" scope="col" width="6%">', $txt['profile_warning_previous_level'], '</th>
-				</tr>
-			</thead>
-			<tbody>';
-
-	// Print the warnings.
-	$alternate = 0;
-	foreach ($context['previous_warnings'] as $warning)
-	{
-		$alternate = !$alternate;
-		echo '
-				<tr class="', $alternate ? 'windowbg' : 'windowbg2', '">
-					<td class="smalltext">', $warning['issuer']['link'], '</td>
-					<td class="smalltext">', $warning['time'], '</td>
-					<td class="smalltext">
-						<div class="floatleft">
-							', $warning['reason'], '
-						</div>';
-
-		if (!empty($warning['id_notice']))
-			echo '
-						<div class="floatright">
-							<a href="', $scripturl, '?action=moderate;area=notice;nid=', $warning['id_notice'], '" onclick="window.open(this.href, \'\', \'scrollbars=yes,resizable=yes,width=400,height=250\');return false;" target="_blank" class="new_win" title="', $txt['profile_warning_previous_notice'], '"><img src="', $settings['images_url'], '/filter.png" alt="" /></a>
-						</div>';
-		echo '
-					</td>
-					<td class="smalltext">', $warning['counter'], '</td>
-				</tr>';
-	}
-
-	if (empty($context['previous_warnings']))
-		echo '
-				<tr class="windowbg2">
-					<td align="center" colspan="4">
-						', $txt['profile_warning_previous_none'], '
-					</td>
-				</tr>';
+	</form>
+	<br />';
 
-	echo '
-			</tbody>
-		</table>
-		<div class="pagesection">', $txt['pages'], ': ', $context['page_index'], '</div>';
+	template_show_list('view_warnings');
 
 	// Do our best to get pretty javascript enabled.
 	echo '

+ 1 - 1
Themes/default/Search.template.php

@@ -172,7 +172,7 @@ function template_main()
 	{
 		echo '
 						<li class="category">
-							<a href="javascript:void(0);" onclick="selectBoards([', implode(', ', $category['child_ids']), ']); return false;">', $category['name'], '</a>
+							<a href="javascript:void(0);" onclick="selectBoards([', implode(', ', $category['child_ids']), '], \'searchform\'); return false;">', $category['name'], '</a>
 							<ul>';
 
 		foreach ($category['boards'] as $board)

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

@@ -588,6 +588,10 @@ $txt['signature_settings_short'] = 'Signatures';
 $txt['custom_profile_shorttitle'] = 'Profile Fields';
 $txt['pruning_title'] = 'Log Pruning';
 
+$txt['core_settings_activation_message'] = 'The Feature {core_feature} has been activated, click on the title to configure it';
+$txt['core_settings_deactivation_message'] = 'The Feature {core_feature} has been deactivated';
+$txt['core_settings_generic_error'] = 'An unforeseen error occurred, please relod the page and try again';
+
 $txt['boardsEdit'] = 'Modify Boards';
 $txt['mboards_new_cat'] = 'Create New Category';
 $txt['manage_holidays'] = 'Manage Holidays';

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

@@ -34,6 +34,7 @@ $txt['not_enough_posts_karma'] = 'Sorry, you don\'t have enough posts to modify
 $txt['cant_change_own_karma'] = 'Sorry, you are not permitted to modify your own karma.';
 $txt['karma_wait_time'] = 'Sorry, you can\'t repeat a karma action without waiting %1$s %2$s.';
 $txt['feature_disabled'] = 'Sorry, this feature is disabled.';
+$txt['feature_no_exists'] = 'Sorry, this feature doesn\'t exists.';
 $txt['cant_access_upload_path'] = 'Cannot access attachments upload path!';
 $txt['file_too_big'] = 'Your file is too large. The maximum attachment size allowed is %1$d kB.';
 $txt['attach_timeout'] = 'Your attachment couldn\'t be saved. This might happen because it took too long to upload or the file is bigger than the server will allow.<br /><br />Please consult your server administrator for more information.';

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

@@ -151,6 +151,7 @@ $txt['showPosts_help'] = 'This section allows you to view all posts made by this
 $txt['showMessages'] = 'Messages';
 $txt['showTopics'] = 'Topics';
 $txt['showAttachments'] = 'Attachments';
+$txt['viewWarning_help'] = 'This section allows you to view all warnings issued to this member.';
 $txt['statPanel'] = 'Show Stats';
 $txt['editBuddyIgnoreLists'] = 'Buddies/Ignore List';
 $txt['editBuddies'] = 'Edit Buddies';

+ 4 - 3
Themes/default/scripts/script.js

@@ -1495,15 +1495,16 @@ function initSearch()
 		document.forms.searchform.search.value = unescape(document.forms.searchform.search.value);
 }
 
-function selectBoards(ids)
+function selectBoards(ids, aFormID)
 {
 	var toggle = true;
+	var aForm = document.getElementById(aFormID);
 
 	for (i = 0; i < ids.length; i++)
-		toggle = toggle & document.forms.searchform["brd" + ids[i]].checked;
+		toggle = toggle & aForm["brd" + ids[i]].checked;
 
 	for (i = 0; i < ids.length; i++)
-		document.forms.searchform["brd" + ids[i]].checked = !toggle;
+		aForm["brd" + ids[i]].checked = !toggle;
 }
 
 function expandCollapseBoards()

+ 9 - 0
other/install_2-1_postgresql.sql

@@ -72,6 +72,15 @@ CREATE OR REPLACE FUNCTION FIND_IN_SET(needle integer, haystack text) RETURNS in
 	LIMIT 1'
 LANGUAGE 'sql';
 
+CREATE OR REPLACE FUNCTION FIND_IN_SET(needle smallint, haystack text) RETURNS integer AS '
+	SELECT i AS result
+	FROM generate_series(1, array_upper(string_to_array($2,'',''), 1)) AS g(i)
+	WHERE  (string_to_array($2,'',''))[i] = CAST($1 AS text)
+		UNION ALL
+	SELECT 0
+	LIMIT 1'
+LANGUAGE 'sql';
+
 CREATE OR REPLACE FUNCTION LEFT (text, int4) RETURNS text AS
   'SELECT SUBSTRING($1 FROM 0 FOR $2) AS result'
 LANGUAGE 'sql';