Browse Source

Merge pull request #36 from emanuele45/master

you wanted me to fix things? Get a pull! :P
Spuds 12 years ago
parent
commit
ca4ed19ace

+ 1 - 1
Sources/Load.php

@@ -452,7 +452,7 @@ function loadUserSettings()
 		$user_info['query_see_board'] = '1=1';
 	// Otherwise just the groups in $user_info['groups'].
 	else
-		$user_info['query_see_board'] = '((FIND_IN_SET(' . implode(', b.member_groups) != 0 OR FIND_IN_SET(', $user_info['groups']) . ', b.member_groups) != 0' . (!empty($modSettings['denyBoardsAccess']) ? ') AND (FIND_IN_SET(' . implode(', b.deny_member_groups) = 0 AND FIND_IN_SET(', $user_info['groups']) . ', b.deny_member_groups) = 0)' : '') . (isset($user_info['mod_cache']) ? ' OR ' . $user_info['mod_cache']['mq'] : '') . ')';
+		$user_info['query_see_board'] = '((FIND_IN_SET(' . implode(', b.member_groups) != 0 OR FIND_IN_SET(', $user_info['groups']) . ', b.member_groups) != 0' . (!empty($modSettings['deny_boards_access']) ? ') AND (FIND_IN_SET(' . implode(', b.deny_member_groups) = 0 AND FIND_IN_SET(', $user_info['groups']) . ', b.deny_member_groups) = 0)' : '') . (isset($user_info['mod_cache']) ? ' OR ' . $user_info['mod_cache']['mq'] : '') . ')';
 
 	// Build the list of boards they WANT to see.
 	// This will take the place of query_see_boards in certain spots, so it better include the boards they can see also

+ 15 - 8
Sources/ManageBans.php

@@ -1261,18 +1261,26 @@ function BanBrowseTriggers()
 					$rowData[\'ip_low1\'],
 					$rowData[\'ip_low2\'],
 					$rowData[\'ip_low3\'],
-					$rowData[\'ip_low4\']
+					$rowData[\'ip_low4\'],
+					$rowData[\'ip_low5\'],
+					$rowData[\'ip_low6\'],
+					$rowData[\'ip_low7\'],
+					$rowData[\'ip_low8\']
 				), array(
 					$rowData[\'ip_high1\'],
 					$rowData[\'ip_high2\'],
 					$rowData[\'ip_high3\'],
-					$rowData[\'ip_high4\']
+					$rowData[\'ip_high4\'],
+					$rowData[\'ip_high5\'],
+					$rowData[\'ip_high6\'],
+					$rowData[\'ip_high7\'],
+					$rowData[\'ip_high8\']
 				));
 			'),
 		);
 		$listOptions['columns']['banned_entity']['sort'] = array(
-			'default' => 'bi.ip_low1, bi.ip_high1, bi.ip_low2, bi.ip_high2, bi.ip_low3, bi.ip_high3, bi.ip_low4, bi.ip_high4',
-			'reverse' => 'bi.ip_low1 DESC, bi.ip_high1 DESC, bi.ip_low2 DESC, bi.ip_high2 DESC, bi.ip_low3 DESC, bi.ip_high3 DESC, bi.ip_low4 DESC, bi.ip_high4 DESC',
+			'default' => 'bi.ip_low1, bi.ip_high1, bi.ip_low2, bi.ip_high2, bi.ip_low3, bi.ip_high3, bi.ip_low4, bi.ip_high4, bi.ip_low5, bi.ip_high5, bi.ip_low6, bi.ip_high6, bi.ip_low7, bi.ip_high7, bi.ip_low8, bi.ip_high8',
+			'reverse' => 'bi.ip_low1 DESC, bi.ip_high1 DESC, bi.ip_low2 DESC, bi.ip_high2 DESC, bi.ip_low3 DESC, bi.ip_high3 DESC, bi.ip_low4 DESC, bi.ip_high4 DESC, bi.ip_low5 DESC, bi.ip_high5 DESC, bi.ip_low6 DESC, bi.ip_high6 DESC, bi.ip_low7 DESC, bi.ip_high7 DESC, bi.ip_low8 DESC, bi.ip_high8 DESC',
 		);
 	}
 	elseif ($context['selected_entity'] === 'hostname')
@@ -1348,7 +1356,7 @@ function list_getBanTriggers($start, $items_per_page, $sort, $trigger_type)
 
 	$request = $smcFunc['db_query']('', '
 		SELECT
-			bi.id_ban, bi.ip_low1, bi.ip_high1, bi.ip_low2, bi.ip_high2, bi.ip_low3, bi.ip_high3, bi.ip_low4, bi.ip_high4, bi.hostname, bi.email_address, bi.hits,
+			bi.id_ban, bi.ip_low1, bi.ip_high1, bi.ip_low2, bi.ip_high2, bi.ip_low3, bi.ip_high3, bi.ip_low4, bi.ip_high4, bi.ip_low5, bi.ip_high5, bi.ip_low6, bi.ip_high6, bi.ip_low7, bi.ip_high7, bi.ip_low8, bi.ip_high8, bi.hostname, bi.email_address, bi.hits,
 			bg.id_ban_group, bg.name' . ($trigger_type === 'member' ? ',
 			mem.id_member, mem.real_name' : '') . '
 		FROM {db_prefix}ban_items AS bi
@@ -1625,7 +1633,7 @@ function list_getNumBanLogEntries()
 function range2ip($low, $high)
 {
 	// IPv6 check.
-	if (!empty($low[5]))
+	if (!empty($high[4]) || !empty($high[5]) || !empty($high[6]) || !empty($high[7]))
 	{
 		if (count($low) != 8 || count($high) != 8)
 			return '';
@@ -1646,8 +1654,7 @@ function range2ip($low, $high)
 
 	// Legacy IPv4 stuff.
 	// (count($low) != 4 || count($high) != 4) would not work because $low and $high always contain 8 elements!
-	for ($i = 4; $i < 8; $i++)
-		if (!empty($low[$i]) || !empty($high[$i]))
+	if ((count($low) != 4 || count($high) != 4) && (count($low) != 8 || count($high) != 8))
 			return '';
 
 	$ip = array();

+ 1 - 1
Sources/ManageBoards.php

@@ -799,7 +799,7 @@ function EditBoardSettings($return_config = false)
 			array('check', 'recycle_enable', 'onclick' => 'document.getElementById(\'recycle_board\').disabled = !this.checked;'),
 			array('select', 'recycle_board', $recycle_boards),
 			array('check', 'allow_ignore_boards'),
-			array('check', 'denyBoardsAccess'),
+			array('check', 'deny_boards_access'),
 	);
 
 	call_integration_hook('integrate_modify_board_settings', array(&$config_vars));

+ 1 - 1
Sources/ManageMembers.php

@@ -797,7 +797,7 @@ function MembersAwaitingActivation()
 
 	$listOptions = array(
 		'id' => 'approve_list',
-		'title' => $txt['members_approval_title'],
+// 		'title' => $txt['members_approval_title'],
 		'items_per_page' => $modSettings['defaultMaxMembers'],
 		'base_href' => $scripturl . '?action=admin;area=viewmembers;sa=browse;type=' . $context['browse_type'] . (!empty($context['show_filter']) ? ';filter=' . $context['current_filter'] : ''),
 		'default_sort_col' => 'date_registered',

+ 2 - 2
Sources/Poll.php

@@ -303,7 +303,6 @@ function EditPoll()
 	loadLanguage('Post');
 	loadTemplate('Poll');
 
-	$context['can_moderate_poll'] = isset($_REQUEST['add']) ? 1 : allowedTo('moderate_board');
 	$context['start'] = (int) $_REQUEST['start'];
 	$context['is_edit'] = isset($_REQUEST['add']) ? 0 : 1;
 
@@ -341,6 +340,7 @@ function EditPoll()
 		isAllowedTo('poll_edit_' . ($user_info['id'] == $pollinfo['id_member_started'] || ($pollinfo['poll_starter'] != 0 && $user_info['id'] == $pollinfo['poll_starter']) ? 'own' : 'any'));
 	elseif (!$context['is_edit'] && !allowedTo('poll_add_any'))
 		isAllowedTo('poll_add_' . ($user_info['id'] == $pollinfo['id_member_started'] ? 'own' : 'any'));
+	$context['can_moderate_poll'] = isset($_REQUEST['add']) ? true : allowedTo('poll_edit_' . ($user_info['id'] == $pollinfo['id_member_started'] || ($pollinfo['poll_starter'] != 0 && $user_info['id'] == $pollinfo['poll_starter']) ? 'own' : 'any'));
 
 	// Do we enable guest voting?
 	require_once($sourcedir . '/Subs-Members.php');
@@ -490,7 +490,7 @@ function EditPoll()
 		);
 
 		// Poll expiration time?
-		$context['poll']['expiration'] = empty($pollinfo['expire_time']) || !allowedTo('moderate_board') ? '' : ceil($pollinfo['expire_time'] <= time() ? -1 : ($pollinfo['expire_time'] - time()) / (3600 * 24));
+		$context['poll']['expiration'] = empty($pollinfo['expire_time']) || !$context['can_moderate_poll'] ? '' : ceil($pollinfo['expire_time'] <= time() ? -1 : ($pollinfo['expire_time'] - time()) / (3600 * 24));
 
 		// Get all the choices - if this is an edit.
 		if ($context['is_edit'])

+ 5 - 21
Sources/Profile-View.php

@@ -125,29 +125,13 @@ function summary($memID)
 			'time' => time(),
 		);
 		$ban_query[] = 'id_member = ' . $context['member']['id'];
-
-		// Valid IP?
-		if (preg_match('/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/', $memberContext[$memID]['ip'], $ip_parts) == 1)
+		$ban_query[] = constructBanQueryIP($memberContext[$memID]['ip']);
+		// Do we have a hostname already?
+		if (!empty($context['member']['hostname']))
 		{
-			$ban_query[] = '((' . $ip_parts[1] . ' BETWEEN bi.ip_low1 AND bi.ip_high1)
-						AND (' . $ip_parts[2] . ' BETWEEN bi.ip_low2 AND bi.ip_high2)
-						AND (' . $ip_parts[3] . ' BETWEEN bi.ip_low3 AND bi.ip_high3)
-						AND (' . $ip_parts[4] . ' BETWEEN bi.ip_low4 AND bi.ip_high4))';
-
-			// Do we have a hostname already?
-			if (!empty($context['member']['hostname']))
-			{
-				$ban_query[] = '({string:hostname} LIKE hostname)';
-				$ban_query_vars['hostname'] = $context['member']['hostname'];
-			}
+			$ban_query[] = '({string:hostname} LIKE hostname)';
+			$ban_query_vars['hostname'] = $context['member']['hostname'];
 		}
-		// Use '255.255.255.255' for 'unknown' - it's not valid anyway.
-		elseif ($memberContext[$memID]['ip'] == 'unknown')
-			$ban_query[] = '(bi.ip_low1 = 255 AND bi.ip_high1 = 255
-						AND bi.ip_low2 = 255 AND bi.ip_high2 = 255
-						AND bi.ip_low3 = 255 AND bi.ip_high3 = 255
-						AND bi.ip_low4 = 255 AND bi.ip_high4 = 255)';
-
 		// Check their email as well...
 		if (strlen($context['member']['email']) != 0)
 		{

+ 1 - 0
Sources/Profile.php

@@ -288,6 +288,7 @@ function ModifyProfile($post_errors = array())
 					'file' => 'Profile-Actions.php',
 					'function' => 'issueWarning',
 					'token' => 'profile-iw%u',
+					'enabled' => !$context['user']['is_owner'],
 					'permission' => array(
 						'own' => array('issue_warning'),
 						'any' => array('issue_warning'),

+ 2 - 2
Sources/QueryString.php

@@ -308,7 +308,7 @@ function isValidIPv6($ip)
 /**
  * Converts IPv6s to numbers.  This makes ban checks much easier.
  * @param string $ip ip address to be converted
- * @return string 
+ * @return array 
  */
 function convertIPv6toInts($ip)
 {
@@ -326,7 +326,7 @@ function convertIPv6toInts($ip)
 		$new_ip[] = hexdec($int);
 
 	// Save this incase of repeated use.
-	$expanded[$ip] = implode($new_ip, '-');
+	$expanded[$ip] = $new_ip;
 
 	return $expanded[$ip];
 }

+ 46 - 49
Sources/Security.php

@@ -192,59 +192,19 @@ function is_not_banned($forceCheck = false)
 		// Check both IP addresses.
 		foreach (array('ip', 'ip2') as $ip_number)
 		{
-			// First attempt a IPv6 address.
-			if (strpos($user_info[$ip_number], ':') !== false)
+			if ($ip_number == 'ip2' && $user_info['ip2'] == $user_info['ip'])
+				continue;
+			$ban_query[] = constructBanQueryIP($user_info[$ip_number]);
+			// IP was valid, maybe there's also a hostname...
+			if (empty($modSettings['disableHostnameLookup']) && $user_info[$ip_number] != 'unknown')
 			{
-				if ($ip_number == 'ip2' && $user_info['ip2'] == $user_info['ip'])
-					continue;
-
-				$ip_parts = array_map('hexdec', explode(':', expandIPv6($user_info[$ip_number])));
-
-				$ban_query[] = '((' . $ip_parts[0] . ' BETWEEN bi.ip_low1 AND bi.ip_high1)
-							AND (' . $ip_parts[1] . ' BETWEEN bi.ip_low2 AND bi.ip_high2)
-							AND (' . $ip_parts[2] . ' BETWEEN bi.ip_low3 AND bi.ip_high3)
-							AND (' . $ip_parts[3] . ' BETWEEN bi.ip_low4 AND bi.ip_high4)
-							AND (' . $ip_parts[4] . ' BETWEEN bi.ip_low5 AND bi.ip_high5)
-							AND (' . $ip_parts[5] . ' BETWEEN bi.ip_low6 AND bi.ip_high6)
-							AND (' . $ip_parts[6] . ' BETWEEN bi.ip_low7 AND bi.ip_high7)
-							AND (' . $ip_parts[7] . ' BETWEEN bi.ip_low8 AND bi.ip_high8))';
-
-				// IP was valid, maybe there's also a hostname...
-				if (empty($modSettings['disableHostnameLookup']))
+				$hostname = host_from_ip($user_info[$ip_number]);
+				if (strlen($hostname) > 0)
 				{
-					$hostname = host_from_ip($user_info[$ip_number]);
-					if (strlen($hostname) > 0)
-					{
-						$ban_query[] = '({string:hostname} LIKE bi.hostname)';
-						$ban_query_vars['hostname'] = $hostname;
-					}
-				}
-			}
-			// Check if we have a valid IPv4 address.
-			elseif (preg_match('/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/', $user_info[$ip_number], $ip_parts) == 1)
-			{
-				$ban_query[] = '((' . $ip_parts[1] . ' BETWEEN bi.ip_low1 AND bi.ip_high1)
-							AND (' . $ip_parts[2] . ' BETWEEN bi.ip_low2 AND bi.ip_high2)
-							AND (' . $ip_parts[3] . ' BETWEEN bi.ip_low3 AND bi.ip_high3)
-							AND (' . $ip_parts[4] . ' BETWEEN bi.ip_low4 AND bi.ip_high4))';
-
-				// IP was valid, maybe there's also a hostname...
-				if (empty($modSettings['disableHostnameLookup']))
-				{
-					$hostname = host_from_ip($user_info[$ip_number]);
-					if (strlen($hostname) > 0)
-					{
-						$ban_query[] = '({string:hostname} LIKE bi.hostname)';
-						$ban_query_vars['hostname'] = $hostname;
-					}
+					$ban_query[] = '({string:hostname} LIKE bi.hostname)';
+					$ban_query_vars['hostname'] = $hostname;
 				}
 			}
-			// We use '255.255.255.255' for 'unknown' since it's not valid anyway.
-			elseif ($user_info['ip'] == 'unknown')
-				$ban_query[] = '(bi.ip_low1 = 255 AND bi.ip_high1 = 255
-							AND bi.ip_low2 = 255 AND bi.ip_high2 = 255
-							AND bi.ip_low3 = 255 AND bi.ip_high3 = 255
-							AND bi.ip_low4 = 255 AND bi.ip_high4 = 255)';
 		}
 
 		// Is their email address banned?
@@ -1255,4 +1215,41 @@ else
 		return true;
 }
 
+/**
+ * Another helper function that put together the 
+ * @param string $fullip An IP address either IPv6 or not
+ * @return string A SQL condition
+ */
+function constructBanQueryIP($fullip)
+{
+	// First attempt a IPv6 address.
+	if (isValidIPv6($fullip))
+	{
+		$ip_parts = convertIPv6toInts($fullip);
+
+		$ban_query = '((' . $ip_parts[0] . ' BETWEEN bi.ip_low1 AND bi.ip_high1)
+			AND (' . $ip_parts[1] . ' BETWEEN bi.ip_low2 AND bi.ip_high2)
+			AND (' . $ip_parts[2] . ' BETWEEN bi.ip_low3 AND bi.ip_high3)
+			AND (' . $ip_parts[3] . ' BETWEEN bi.ip_low4 AND bi.ip_high4)
+			AND (' . $ip_parts[4] . ' BETWEEN bi.ip_low5 AND bi.ip_high5)
+			AND (' . $ip_parts[5] . ' BETWEEN bi.ip_low6 AND bi.ip_high6)
+			AND (' . $ip_parts[6] . ' BETWEEN bi.ip_low7 AND bi.ip_high7)
+			AND (' . $ip_parts[7] . ' BETWEEN bi.ip_low8 AND bi.ip_high8))';
+	}
+	// Check if we have a valid IPv4 address.
+	elseif (preg_match('/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/', $fullip, $ip_parts) == 1)
+		$ban_query = '((' . $ip_parts[1] . ' BETWEEN bi.ip_low1 AND bi.ip_high1)
+			AND (' . $ip_parts[2] . ' BETWEEN bi.ip_low2 AND bi.ip_high2)
+			AND (' . $ip_parts[3] . ' BETWEEN bi.ip_low3 AND bi.ip_high3)
+			AND (' . $ip_parts[4] . ' BETWEEN bi.ip_low4 AND bi.ip_high4))';
+	// We use '255.255.255.255' for 'unknown' since it's not valid anyway.
+	else
+		$ban_query = '(bi.ip_low1 = 255 AND bi.ip_high1 = 255
+			AND bi.ip_low2 = 255 AND bi.ip_high2 = 255
+			AND bi.ip_low3 = 255 AND bi.ip_high3 = 255
+			AND bi.ip_low4 = 255 AND bi.ip_high4 = 255)';
+
+	return $ban_query;
+}
+
 ?>

+ 4 - 4
Sources/Subs.php

@@ -848,7 +848,7 @@ function parse_bbc($message, $smileys = true, $cache_id = '', $parse_tags = arra
 	// Don't waste cycles
 	if ($message === '')
 		return '';
-		
+
 	// Just in case it wasn't determined yet whether UTF-8 is enabled.
 	if (!isset($context['utf8']))
 		$context['utf8'] = (empty($modSettings['global_character_set']) ? $txt['lang_character_set'] : $modSettings['global_character_set']) === 'UTF-8';
@@ -862,7 +862,7 @@ function parse_bbc($message, $smileys = true, $cache_id = '', $parse_tags = arra
 		$context['disabled_parse_bbc'] = true;
 		return $message;
 	}
-	
+
 	// Never show smileys for wireless clients.  More bytes, can't see it anyway :P.
 	if (WIRELESS)
 		$smileys = false;
@@ -3331,7 +3331,7 @@ function getLegacyAttachmentFilename($filename, $attachment_id, $dir = null, $ne
  * internal function used to convert a user-readable format to a format suitable for the database.
  *
  * @param string $fullip
- * @return array|string 'unknown' if the ip in the input was '255.255.255.255'
+ * @return array 
  */
 function ip2range($fullip)
 {
@@ -4084,7 +4084,7 @@ function sanitizeMSCutPaste($string)
 	global $context;
 	
 	if (empty($string))
-		return;
+		return $string;
 		
 	// UTF-8 occurences of MS special characters
 	$findchars_utf8 = array(

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

@@ -1709,6 +1709,7 @@ function template_clean_cache_button_below()
 				<input type="hidden" name="', $context['admin-maint_token_var'], '" value="', $context['admin-maint_token'], '" />
 			</form>
 		</div>
+		<br class="clear" />
 		<span class="botslice"><span></span></span>
 	</div>';
 }

+ 31 - 16
Themes/default/ManageBoards.template.php

@@ -257,10 +257,6 @@ function template_modify_board()
 {
 	global $context, $settings, $options, $scripturl, $txt, $modSettings;
 
-	if (!empty($modSettings['denyBoardsAccess']))
-		echo '
-		<div class="information">', $txt['boardsaccess_option_desc'], '</div>';
-
 	// The main table header.
 	echo '
 	<div id="manage_boards">
@@ -358,11 +354,13 @@ function template_modify_board()
 						</dd>
 						<dt>
 							<strong>', $txt['mboards_groups'], ':</strong><br />
-							<span class="smalltext">', $txt['mboards_groups_desc'], '</span>
+							<span class="smalltext">', empty($modSettings['deny_boards_access']) ? $txt['mboards_groups_desc'] : $txt['boardsaccess_option_desc'], '</span>';
+
+	echo '
 						</dt>
 						<dd>';
 
-	if (!empty($modSettings['denyBoardsAccess']))
+	if (!empty($modSettings['deny_boards_access']))
 		echo '
 							<table>
 								<tr>
@@ -374,10 +372,10 @@ function template_modify_board()
 
 	// List all the membergroups so the user can choose who may access this board.
 	foreach ($context['groups'] as $group)
-		if (empty($modSettings['denyBoardsAccess']))
+		if (empty($modSettings['deny_boards_access']))
 			echo '
 							<label for="groups_', $group['id'], '">
-								<input type="checkbox" name="groups[', $group['id'], ']" value="allow" id="groups_', $group['id'], '"', $group['checked'] ? ' checked="checked"' : '', ' class="input_check" />
+								<input type="checkbox" name="groups[', $group['id'], ']" value="allow" id="groups_', $group['id'], '"', $group['allow'] ? ' checked="checked"' : '', ' class="input_check" />
 								<span', $group['is_post_group'] ? ' class="post_group" title="' . $txt['mboards_groups_post_group'] . '"' : '', $group['id'] == 0 ? ' class="regular_members" title="' . $txt['mboards_groups_regular_members'] . '"' : '', '>
 									', $group['name'], '
 								</span>
@@ -393,24 +391,41 @@ function template_modify_board()
 										</label>
 									</td>
 									<td>
-										<input type="radio" name="groups[', $group['id'], ']" value="allow" id="groups_', $group['id'], '"', $group['allow'] ? ' checked="checked"' : '', ' class="input_radio" />
+										<input type="radio" name="groups[', $group['id'], ']" value="allow" id="groups_', $group['id'], '_a"', $group['allow'] ? ' checked="checked"' : '', ' class="input_radio" />
 									</td>
 									<td>
-										<input type="radio" name="groups[', $group['id'], ']" value="ignore" id="groups_', $group['id'], '"', !$group['allow'] && !$group['deny'] ? ' checked="checked"' : '', ' class="input_radio" />
+										<input type="radio" name="groups[', $group['id'], ']" value="ignore" id="groups_', $group['id'], '_x"', !$group['allow'] && !$group['deny'] ? ' checked="checked"' : '', ' class="input_radio" />
 									</td>
 									<td>
-										<input type="radio" name="groups[', $group['id'], ']" value="deny" id="groups_', $group['id'], '"', $group['deny'] ? ' checked="checked"' : '', ' class="input_radio" />
+										<input type="radio" name="groups[', $group['id'], ']" value="deny" id="groups_', $group['id'], '_d"', $group['deny'] ? ' checked="checked"' : '', ' class="input_radio" />
 									</td>
-';
+									<td></td>
+								</tr>';
 
-	if (!empty($modSettings['denyBoardsAccess']))
+	if (empty($modSettings['deny_boards_access']))
 		echo '
-							</table>
+							<em>', $txt['check_all'], '</em> <input type="checkbox" class="input_check" onclick="invertAll(this, this.form, \'groups[]\');" /><br />
+							<br />
 						</dd>';
 	else
 		echo '
-							<em>', $txt['check_all'], '</em> <input type="checkbox" class="input_check" onclick="invertAll(this, this.form, \'groups[]\');" /><br />
-							<br />
+								<tr>
+									<td>
+									</td>
+									<td>
+										<input type="radio" name="select_all" class="input_radio" onclick="selectAllRadio(this, this.form, \'groups\', \'allow\');" />
+									</td>
+									<td>
+										<input type="radio" name="select_all" class="input_radio" onclick="selectAllRadio(this, this.form, \'groups\', \'ignore\');" />
+									</td>
+									<td>
+										<input type="radio" name="select_all" class="input_radio" onclick="selectAllRadio(this, this.form, \'groups\', \'deny\');" />
+									</td>
+									<td>
+										<em>', $txt['check_all'], '</em>
+									</td>
+								</tr>
+							</table>
 						</dd>';
 
 	// Options to choose moderators, specifiy as announcement board and choose whether to count posts here.

+ 2 - 2
Themes/default/ManageLanguages.template.php

@@ -423,13 +423,13 @@ function template_modify_language_entries()
 
 		echo '
 				</div>
+				<br class="clear" />
 				<span class="botslice"><span></span></span>
 			</div>';
 	}
 	echo '
 		</form>
-	</div>
-	<br class="clear" />';
+	</div>';
 }
 
 /**

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

@@ -424,6 +424,7 @@ function template_edit_profiles()
 
 	echo '
 				<input type="submit" name="delete" value="', $txt['quickmod_delete_selected'], '" class="button_submit" />
+				<br class="clear" />
 			</div>
 		</form>
 		<br />

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

@@ -1305,6 +1305,7 @@ function template_prune()
 				<div class="righttext">
 					<input type="submit" value="', $txt['delete'], '" class="button_submit" />
 				</div>
+				<br class="clear" />
 			</div>
 			<span class="botslice"><span></span></span>
 		</div>

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

@@ -145,6 +145,7 @@ function template_main()
 					<div class="righttext padding">
 						<input type="submit" name="post" value="', $txt['save'], '" onclick="return submitThisOnce(this);" accesskey="s" class="button_submit" />
 					</div>
+					<br class="clear" />
 				</div>
 				<span class="lowerframe"><span></span></span>
 			</div>
@@ -152,7 +153,7 @@ function template_main()
 			<input type="hidden" name="' . $context['session_var'] . '" value="' . $context['session_id'] . '" />
 		</form>
 	</div>
-	<br class="clear" />';
+';
 }
 
 ?>

+ 1 - 1
Themes/default/languages/ManageBoards.english.php

@@ -88,7 +88,7 @@ $txt['recycle_board'] = 'Board for recycled topics';
 $txt['recycle_board_unselected_notice'] = 'You have enabled the recycling of topics without specifying a board to place them in.  This feature will not be enabled until you specify a board to place recycled topics into.';
 $txt['countChildPosts'] = 'Count child\'s posts in parent\'s totals';
 $txt['allow_ignore_boards'] = 'Allow boards to be ignored';
-$txt['denyBoardsAccess'] = 'Enable the option to deny boards access to a group';
+$txt['deny_boards_access'] = 'Enable the option to deny boards access to a group';
 $txt['boardsaccess_option_desc'] = 'For each permission you can pick either \'Allow\' (A), \'Ignore\' (X), or <span class="alert">\'Deny\' (D)</span>.<br /><br />Remember that if you deny access, any member - whether moderator or otherwise - that is in that group will be denied that as well.<br />For this reason, you should use deny carefully, only when <strong>necessary</strong>. Ignore, on the other hand, denies unless otherwise granted.';
 
 $txt['mboards_select_destination'] = 'Select destination for board \'<strong>%1$s</strong>\'';

+ 7 - 0
Themes/default/scripts/script.js

@@ -530,6 +530,13 @@ function selectRadioByName(oRadioGroup, sName)
 	return false;
 }
 
+function selectAllRadio(oInvertCheckbox, oForm, sMask, sValue)
+{
+	for (var i = 0; i < oForm.length; i++)
+		if (oForm[i].name.substr(0, sMask.length) == sMask && oForm[i].value == sValue)
+			oForm[i].checked = true;
+}
+
 // Invert all checkboxes at once by clicking a single checkbox.
 function invertAll(oInvertCheckbox, oForm, sMask, bIgnoreDisabled)
 {