Browse Source

Merge pull request #46 from emanuele45/master

couple of issues
Norv 12 years ago
parent
commit
d454abc2b3
41 changed files with 645 additions and 244 deletions
  1. 1 1
      Sources/Admin.php
  2. 33 0
      Sources/Display.php
  3. 3 3
      Sources/Load.php
  4. 1 1
      Sources/ManageBoards.php
  5. 84 58
      Sources/ManageMembergroups.php
  6. 15 15
      Sources/ManagePermissions.php
  7. 1 0
      Sources/ManagePosts.php
  8. 1 0
      Sources/ManageServer.php
  9. 1 1
      Sources/ManageSmileys.php
  10. 6 6
      Sources/MessageIndex.php
  11. 172 2
      Sources/Printpage.php
  12. 4 0
      Sources/Profile-View.php
  13. 1 1
      Sources/Subs.php
  14. 5 3
      Sources/Themes.php
  15. 57 15
      Themes/default/Display.template.php
  16. 12 2
      Themes/default/ManageBoards.template.php
  17. 95 67
      Themes/default/ManageMembergroups.template.php
  18. 29 8
      Themes/default/Printpage.template.php
  19. 1 0
      Themes/default/Profile.template.php
  20. 2 1
      Themes/default/Settings.template.php
  21. 3 3
      Themes/default/Themes.template.php
  22. 3 0
      Themes/default/css/admin.css
  23. 1 2
      Themes/default/css/index.css
  24. 1 1
      Themes/default/index.template.php
  25. 6 0
      Themes/default/languages/Admin.english.php
  26. 1 0
      Themes/default/languages/Errors.english.php
  27. 11 11
      Themes/default/languages/Help.english.php
  28. 2 1
      Themes/default/languages/ManageSettings.english.php
  29. 1 0
      Themes/default/languages/Profile.english.php
  30. 0 2
      Themes/default/languages/Reports.english.php
  31. 8 0
      Themes/default/scripts/admin.js
  32. 1 1
      Themes/default/scripts/script.js
  33. 6 2
      Themes/default/scripts/topic.js
  34. 60 26
      Themes/penguin/Display.template.php
  35. 1 0
      Themes/penguin/Profile.template.php
  36. 1 0
      Themes/penguin/Settings.template.php
  37. 3 0
      Themes/penguin/css/admin.css
  38. 1 2
      Themes/penguin/css/index.css
  39. 8 0
      Themes/penguin/scripts/admin.js
  40. 2 8
      other/install.php
  41. 1 1
      other/install_2-1_mysql.sql

+ 1 - 1
Sources/Admin.php

@@ -167,7 +167,7 @@ function AdminMain()
 					'label' => $txt['theme_current_settings'],
 					'file' => 'Themes.php',
 					'function' => 'ThemesMain',
-					'custom_url' => $scripturl . '?action=admin;area=theme;sa=settings;th=' . $settings['theme_id'],
+					'custom_url' => $scripturl . '?action=admin;area=theme;sa=list;th=' . $settings['theme_id'],
 					'icon' => 'current_theme.png',
 				),
 				'theme' => array(

+ 33 - 0
Sources/Display.php

@@ -1042,6 +1042,7 @@ function Display()
 	$context['can_mark_unread'] = !$user_info['is_guest'] && $settings['show_mark_read'];
 
 	$context['can_send_topic'] = (!$modSettings['postmod_active'] || $topicinfo['approved']) && allowedTo('send_topic');
+	$context['can_print'] = empty($modSettings['disable_print_topic']);
 
 	// Start this off for quick moderation - it will be or'd for each post.
 	$context['can_remove_post'] = allowedTo('delete_any') || (allowedTo('delete_replies') && $context['user']['started']);
@@ -1063,6 +1064,38 @@ function Display()
 		checkSubmitOnce('register');
 		$context['name'] = isset($_SESSION['guest_name']) ? $_SESSION['guest_name'] : '';
 		$context['email'] = isset($_SESSION['guest_email']) ? $_SESSION['guest_email'] : '';
+		if ($options['display_quick_reply'] == 3 && $context['can_reply'])
+		{
+			// Needed for the editor and message icons.
+			require_once($sourcedir . '/Subs-Editor.php');
+
+			// Now create the editor.
+			$editorOptions = array(
+				'id' => 'message',
+				'value' => '',
+				'labels' => array(
+					'post_button' => $txt['post'],
+				),
+				// add height and width for the editor
+				'height' => '175px',
+				'width' => '100%',
+				// We do XML preview here.
+				'preview_type' => 0,
+			);
+			create_control_richedit($editorOptions);
+
+			// Store the ID.
+			$context['post_box_name'] = $editorOptions['id'];
+
+			$context['attached'] = '';
+			$context['make_poll'] = isset($_REQUEST['poll']);
+
+			// Message icons - customized icons are off?
+			$context['icons'] = getMessageIcons($board);
+
+			if (!empty($context['icons']))
+				$context['icons'][count($context['icons']) - 1]['is_last'] = true;
+		}
 	}
 }
 

+ 3 - 3
Sources/Load.php

@@ -678,7 +678,7 @@ function loadBoard()
 
 		if (count(array_intersect($user_info['groups'], $board_info['groups'])) == 0 && !$user_info['is_admin'])
 			$board_info['error'] = 'access';
-		if (count(array_intersect($user_info['groups'], $board_info['deny_groups'])) != 0 && !$user_info['is_admin'])
+		if (!empty($modSettings['deny_boards_access']) && count(array_intersect($user_info['groups'], $board_info['deny_groups'])) != 0 && !$user_info['is_admin'])
 			$board_info['error'] = 'access';
 
 		// Build up the linktree.
@@ -702,7 +702,7 @@ function loadBoard()
 	$context['current_board'] = $board;
 
 	// Hacker... you can't see this topic, I'll tell you that. (but moderators can!)
-	if (!empty($board_info['error']) && ($board_info['error'] != 'access' || !$user_info['is_mod']))
+	if (!empty($board_info['error']) && (!empty($modSettings['deny_boards_access']) || $board_info['error'] != 'access' || !$user_info['is_mod']))
 	{
 		// The permissions and theme need loading, just to make sure everything goes smoothly.
 		loadPermissions();
@@ -1813,7 +1813,7 @@ function loadTemplate($template_name, $style_sheets = array(), $fatal = true)
 			loadLanguage('Errors');
 			echo '
 <div class="alert errorbox">
-	<a href="', $scripturl . '?action=admin;area=theme;sa=settings;th=1;' . $context['session_var'] . '=' . $context['session_id'], '" class="alert">', $txt['theme_dir_wrong'], '</a>
+	<a href="', $scripturl . '?action=admin;area=theme;sa=list;th=1;' . $context['session_var'] . '=' . $context['session_id'], '" class="alert">', $txt['theme_dir_wrong'], '</a>
 </div>';
 		}
 

+ 1 - 1
Sources/ManageBoards.php

@@ -402,7 +402,7 @@ function EditBoard()
 		// Some things that need to be setup for a new board.
 		$curBoard = array(
 			'member_groups' => array(0, -1),
-			'deny_group' => array(),
+			'deny_groups' => array(),
 			'category' => (int) $_REQUEST['cat']
 		);
 		$context['board_order'] = array();

+ 84 - 58
Sources/ManageMembergroups.php

@@ -499,23 +499,30 @@ function AddMembergroup()
 		}
 
 		// Make sure all boards selected are stored in a proper array.
-		$_POST['boardaccess'] = empty($_POST['boardaccess']) || !is_array($_POST['boardaccess']) ? array() : $_POST['boardaccess'];
-		foreach ($_POST['boardaccess'] as $key => $value)
-			$_POST['boardaccess'][$key] = (int) $value;
-
-		// Only do this if they have special access requirements.
-		if (!empty($_POST['boardaccess']))
-			$smcFunc['db_query']('', '
-				UPDATE {db_prefix}boards
-				SET member_groups = CASE WHEN member_groups = {string:blank_string} THEN {string:group_id_string} ELSE CONCAT(member_groups, {string:comma_group}) END
-				WHERE id_board IN ({array_int:board_list})',
-				array(
-					'board_list' => $_POST['boardaccess'],
-					'blank_string' => '',
-					'group_id_string' => (string) $id_group,
-					'comma_group' => ',' . $id_group,
-				)
-			);
+		$accesses = empty($_POST['boardaccess']) || !is_array($_POST['boardaccess']) ? array() : $_POST['boardaccess'];
+		$changed_boards['allow'] = array();
+		$changed_boards['deny'] = array();
+		$changed_boards['ignore'] = array();
+		foreach ($accesses as $group_id => $action)
+			$changed_boards[$action][] = (int) $group_id;
+
+		foreach (array('allow', 'deny') as $board_action)
+		{
+			// Only do this if they have special access requirements.
+			if (!empty($changed_boards[$board_action]))
+				$smcFunc['db_query']('', '
+					UPDATE {db_prefix}boards
+					SET {raw:column} = CASE WHEN {raw:column} = {string:blank_string} THEN {string:group_id_string} ELSE CONCAT({raw:column}, {string:comma_group}) END
+					WHERE id_board IN ({array_int:board_list})',
+					array(
+						'board_list' => $changed_boards[$board_action],
+						'blank_string' => '',
+						'group_id_string' => (string) $id_group,
+						'comma_group' => ',' . $id_group,
+						'column' => $board_action == 'allow' ? 'member_groups' : 'deny_member_groups',
+					)
+				);
+		}
 
 		// If this is joinable then set it to show group membership in people's profiles.
 		if (empty($modSettings['show_group_membership']) && $_POST['group_type'] > 1)
@@ -540,6 +547,9 @@ function AddMembergroup()
 	$context['undefined_group'] = !isset($_REQUEST['postgroup']) && !isset($_REQUEST['generalgroup']);
 	$context['allow_protected'] = allowedTo('admin_forum');
 
+	if (!empty($modSettings['deny_boards_access']))
+		loadLanguage('ManagePermissions');
+
 	$result = $smcFunc['db_query']('', '
 		SELECT id_group, group_name
 		FROM {db_prefix}membergroups
@@ -588,7 +598,8 @@ function AddMembergroup()
 			'id' => $row['id_board'],
 			'name' => $row['name'],
 			'child_level' => $row['child_level'],
-			'selected' => false
+			'allow' => false,
+			'deny' => false
 		);
 
 	}
@@ -648,6 +659,10 @@ function EditMembergroup()
 
 	$_REQUEST['group'] = isset($_REQUEST['group']) && $_REQUEST['group'] > 0 ? (int) $_REQUEST['group'] : 0;
 
+	if (!empty($modSettings['deny_boards_access']))
+		loadLanguage('ManagePermissions');
+
+
 	// Make sure this group is editable.
 	if (!empty($_REQUEST['group']))
 	{
@@ -744,48 +759,57 @@ function EditMembergroup()
 		// Time to update the boards this membergroup has access to.
 		if ($_REQUEST['group'] == 2 || $_REQUEST['group'] > 3)
 		{
-			$_POST['boardaccess'] = empty($_POST['boardaccess']) || !is_array($_POST['boardaccess']) ? array() : $_POST['boardaccess'];
-			foreach ($_POST['boardaccess'] as $key => $value)
-				$_POST['boardaccess'][$key] = (int) $value;
-
-			// Find all board this group is in, but shouldn't be in.
-			$request = $smcFunc['db_query']('', '
-				SELECT id_board, member_groups
-				FROM {db_prefix}boards
-				WHERE FIND_IN_SET({string:current_group}, member_groups) != 0' . (empty($_POST['boardaccess']) ? '' : '
-					AND id_board NOT IN ({array_int:board_access_list})'),
-				array(
-					'current_group' => (int) $_REQUEST['group'],
-					'board_access_list' => $_POST['boardaccess'],
-				)
-			);
-			while ($row = $smcFunc['db_fetch_assoc']($request))
-				$smcFunc['db_query']('', '
-					UPDATE {db_prefix}boards
-					SET member_groups = {string:member_group_access}
-					WHERE id_board = {int:current_board}',
-					array(
-						'current_board' => $row['id_board'],
-						'member_group_access' => implode(',', array_diff(explode(',', $row['member_groups']), array($_REQUEST['group']))),
-					)
-				);
-			$smcFunc['db_free_result']($request);
-
-			// Add the membergroup to all boards that hadn't been set yet.
-			if (!empty($_POST['boardaccess']))
-				$smcFunc['db_query']('', '
-					UPDATE {db_prefix}boards
-					SET member_groups = CASE WHEN member_groups = {string:blank_string} THEN {string:group_id_string} ELSE CONCAT(member_groups, {string:comma_group}) END
-					WHERE id_board IN ({array_int:board_list})
-						AND FIND_IN_SET({int:current_group}, member_groups) = 0',
+			$accesses = empty($_POST['boardaccess']) || !is_array($_POST['boardaccess']) ? array() : $_POST['boardaccess'];
+			$changed_boards['allow'] = array();
+			$changed_boards['deny'] = array();
+			$changed_boards['ignore'] = array();
+			foreach ($accesses as $group_id => $action)
+				$changed_boards[$action][] = (int) $group_id;
+
+			foreach (array('allow', 'deny') as $board_action)
+			{
+				// Find all board this group is in, but shouldn't be in.
+				$request = $smcFunc['db_query']('', '
+					SELECT id_board, {raw:column}
+					FROM {db_prefix}boards
+					WHERE FIND_IN_SET({string:current_group}, {raw:column}) != 0' . (empty($changed_boards[$board_action]) ? '' : '
+						AND id_board NOT IN ({array_int:board_access_list})'),
 					array(
-						'board_list' => $_POST['boardaccess'],
-						'blank_string' => '',
 						'current_group' => (int) $_REQUEST['group'],
-						'group_id_string' => (string) (int) $_REQUEST['group'],
-						'comma_group' => ',' . $_REQUEST['group'],
+						'board_access_list' => $changed_boards[$board_action],
+						'column' => $board_action == 'allow' ? 'member_groups' : 'deny_member_groups',
 					)
 				);
+				while ($row = $smcFunc['db_fetch_assoc']($request))
+					$smcFunc['db_query']('', '
+						UPDATE {db_prefix}boards
+						SET {raw:column} = {string:member_group_access}
+						WHERE id_board = {int:current_board}',
+						array(
+							'current_board' => $row['id_board'],
+							'member_group_access' => implode(',', array_diff(explode(',', $row['member_groups']), array($_REQUEST['group']))),
+							'column' => $board_action == 'allow' ? 'member_groups' : 'deny_member_groups',
+						)
+					);
+				$smcFunc['db_free_result']($request);
+
+				// Add the membergroup to all boards that hadn't been set yet.
+				if (!empty($changed_boards[$board_action]))
+					$smcFunc['db_query']('', '
+						UPDATE {db_prefix}boards
+						SET {raw:column} = CASE WHEN {raw:column} = {string:blank_string} THEN {string:group_id_string} ELSE CONCAT({raw:column}, {string:comma_group}) END
+						WHERE id_board IN ({array_int:board_list})
+							AND FIND_IN_SET({int:current_group}, {raw:column}) = 0',
+						array(
+							'board_list' => $changed_boards[$board_action],
+							'blank_string' => '',
+							'current_group' => (int) $_REQUEST['group'],
+							'group_id_string' => (string) (int) $_REQUEST['group'],
+							'comma_group' => ',' . $_REQUEST['group'],
+							'column' => $board_action == 'allow' ? 'member_groups' : 'deny_member_groups',
+						)
+					);
+			}
 		}
 
 		// Remove everyone from this group!
@@ -1032,7 +1056,8 @@ function EditMembergroup()
 	if ($_REQUEST['group'] == 2 || $_REQUEST['group'] > 3)
 	{
 		$request = $smcFunc['db_query']('', '
-			SELECT b.id_cat, c.name as cat_name, b.id_board, b.name, b.child_level, FIND_IN_SET({string:current_group}, b.member_groups) != 0 AS can_access
+			SELECT b.id_cat, c.name as cat_name, b.id_board, b.name, b.child_level,
+			FIND_IN_SET({string:current_group}, b.member_groups) != 0 AS can_access, FIND_IN_SET({string:current_group}, b.deny_member_groups) != 0 AS cannot_access
 			FROM {db_prefix}boards AS b
 				LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)
 			ORDER BY board_order',
@@ -1056,7 +1081,8 @@ function EditMembergroup()
 				'id' => $row['id_board'],
 				'name' => $row['name'],
 				'child_level' => $row['child_level'],
-				'selected' => !(empty($row['can_access']) || $row['can_access'] == 'f'),
+				'allow' => !(empty($row['can_access']) || $row['can_access'] == 'f'),
+				'deny' => !(empty($row['cannot_access']) || $row['cannot_access'] == 'f'),
 			);
 		}
 		$smcFunc['db_free_result']($request);

+ 15 - 15
Sources/ManagePermissions.php

@@ -1672,24 +1672,24 @@ function loadAllPermissions($loadType = 'classic')
 			}
 		}
 		ksort($context['permissions'][$permissionType]['columns']);
-	}
 
-	// Check we don't leave any empty groups - and mark hidden ones as such.
-	foreach ($context['permissions'][$permissionType]['columns'] as $column => $groups)
-		foreach ($groups as $id => $group)
-		{
-			if (empty($group['permissions']))
-				unset($context['permissions'][$permissionType]['columns'][$column][$id]);
-			else
+		// Check we don't leave any empty groups - and mark hidden ones as such.
+		foreach ($context['permissions'][$permissionType]['columns'] as $column => $groups)
+			foreach ($groups as $id => $group)
 			{
-				$foundNonHidden = false;
-				foreach ($group['permissions'] as $permission)
-					if (empty($permission['hidden']))
-						$foundNonHidden = true;
-				if (!$foundNonHidden)
-					$context['permissions'][$permissionType]['columns'][$column][$id]['hidden'] = true;
+				if (empty($group['permissions']))
+					unset($context['permissions'][$permissionType]['columns'][$column][$id]);
+				else
+				{
+					$foundNonHidden = false;
+					foreach ($group['permissions'] as $permission)
+						if (empty($permission['hidden']))
+							$foundNonHidden = true;
+					if (!$foundNonHidden)
+						$context['permissions'][$permissionType]['columns'][$column][$id]['hidden'] = true;
+				}
 			}
-		}
+	}
 }
 
 /**

+ 1 - 0
Sources/ManagePosts.php

@@ -357,6 +357,7 @@ function ModifyTopicSettings($return_config = false)
 			array('int', 'oldTopicDays', 'postinput' => $txt['manageposts_days'], 'subtext' => $txt['oldTopicDays_zero']),
 			array('int', 'defaultMaxTopics', 'postinput' => $txt['manageposts_topics']),
 			array('int', 'defaultMaxMessages', 'postinput' => $txt['manageposts_posts']),
+			array('check', 'disable_print_topic'),
 		'',
 			// Hot topics (etc)...
 			array('int', 'hotTopicPosts', 'postinput' => $txt['manageposts_posts']),

+ 1 - 0
Sources/ManageServer.php

@@ -465,6 +465,7 @@ function ModifyLoadBalancingSettings($return_config = false)
 		'loadavg_allunread' => '2.0',
 		'loadavg_unreadreplies' => '3.5',
 		'loadavg_show_posts' => '2.0',
+		'loadavg_userstats' => '10.0',
 		'loadavg_bbc' => '30.0',
 		'loadavg_forum' => '40.0',
 	);

+ 1 - 1
Sources/ManageSmileys.php

@@ -782,7 +782,7 @@ function EditSmileys()
 	$context[$context['admin_menu_name']]['current_subsection'] = 'editsmileys';
 
 	// Submitting a form?
-	if (isset($_POST['smiley_save']))
+	if (isset($_POST['smiley_save']) || isset($_POST['smiley_action']))
 	{
 		checkSession();
 

+ 6 - 6
Sources/MessageIndex.php

@@ -359,7 +359,7 @@ function MessageIndex()
 			SELECT
 				t.id_topic, t.num_replies, t.locked, t.num_views, t.is_sticky, t.id_poll, t.id_previous_board,
 				' . ($user_info['is_guest'] ? '0' : 'IFNULL(lt.id_msg, IFNULL(lmr.id_msg, -1)) + 1') . ' AS new_from,
-				t.id_last_msg, t.approved, t.unapproved_posts, ml.poster_time AS last_poster_time,
+				t.id_last_msg, t.approved, t.unapproved_posts, t.id_redirect_topic, ml.poster_time AS last_poster_time,
 				ml.id_msg_modified, ml.subject AS last_subject, ml.icon AS last_icon,
 				ml.poster_name AS last_member_name, ml.id_member AS last_id_member,
 				IFNULL(meml.real_name, ml.poster_name) AS last_display_name, t.id_first_msg,
@@ -490,8 +490,8 @@ function MessageIndex()
 					'preview' => $row['first_body'],
 					'icon' => $row['first_icon'],
 					'icon_url' => $settings[$context['icon_sources'][$row['first_icon']]] . '/post/' . $row['first_icon'] . '.png',
-					'href' => $scripturl . '?topic=' . $row['id_topic'] . '.0',
-					'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.0">' . $row['first_subject'] . '</a>'
+					'href' => $scripturl . '?topic=' . (empty($row['id_redirect_topic']) ? $row['id_topic'] : $row['id_redirect_topic']) . '.0',
+					'link' => '<a href="' . $scripturl . '?topic=' . (empty($row['id_redirect_topic']) ? $row['id_topic'] : $row['id_redirect_topic']). '.0">' . $row['first_subject'] . '</a>'
 				),
 				'last_post' => array(
 					'id' => $row['id_last_msg'],
@@ -508,8 +508,8 @@ function MessageIndex()
 					'preview' => $row['last_body'],
 					'icon' => $row['last_icon'],
 					'icon_url' => $settings[$context['icon_sources'][$row['last_icon']]] . '/post/' . $row['last_icon'] . '.png',
-					'href' => $scripturl . '?topic=' . $row['id_topic'] . ($user_info['is_guest'] ? ('.' . (!empty($options['view_newest_first']) ? 0 : ((int) (($row['num_replies']) / $context['pageindex_multiplier'])) * $context['pageindex_multiplier']) . '#msg' . $row['id_last_msg']) : (($row['num_replies'] == 0 ? '.0' : '.msg' . $row['id_last_msg']) . '#new')),
-					'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . ($user_info['is_guest'] ? ('.' . (!empty($options['view_newest_first']) ? 0 : ((int) (($row['num_replies']) / $context['pageindex_multiplier'])) * $context['pageindex_multiplier']) . '#msg' . $row['id_last_msg']) : (($row['num_replies'] == 0 ? '.0' : '.msg' . $row['id_last_msg']) . '#new')) . '" ' . ($row['num_replies'] == 0 ? '' : 'rel="nofollow"') . '>' . $row['last_subject'] . '</a>'
+					'href' => $scripturl . '?topic=' . (empty($row['id_redirect_topic']) ? $row['id_topic'] : $row['id_redirect_topic']) . ($user_info['is_guest'] ? ('.' . (!empty($options['view_newest_first']) ? 0 : ((int) (($row['num_replies']) / $context['pageindex_multiplier'])) * $context['pageindex_multiplier']) . '#msg' . $row['id_last_msg']) : (($row['num_replies'] == 0 ? '.0' : '.msg' . $row['id_last_msg']) . '#new')),
+					'link' => '<a href="' . $scripturl . '?topic=' . (empty($row['id_redirect_topic']) ? $row['id_topic'] : $row['id_redirect_topic']) . ($user_info['is_guest'] ? ('.' . (!empty($options['view_newest_first']) ? 0 : ((int) (($row['num_replies']) / $context['pageindex_multiplier'])) * $context['pageindex_multiplier']) . '#msg' . $row['id_last_msg']) : (($row['num_replies'] == 0 ? '.0' : '.msg' . $row['id_last_msg']) . '#new')) . '" ' . ($row['num_replies'] == 0 ? '' : 'rel="nofollow"') . '>' . $row['last_subject'] . '</a>'
 				),
 				'is_sticky' => !empty($modSettings['enableStickyTopics']) && !empty($row['is_sticky']),
 				'is_locked' => !empty($row['locked']),
@@ -523,7 +523,7 @@ function MessageIndex()
 				'new' => $row['new_from'] <= $row['id_msg_modified'],
 				'new_from' => $row['new_from'],
 				'newtime' => $row['new_from'],
-				'new_href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['new_from'] . '#new',
+				'new_href' => $scripturl . '?topic=' . (empty($row['id_redirect_topic']) ? $row['id_topic'] : $row['id_redirect_topic']) . '.msg' . $row['new_from'] . '#new',
 				'pages' => $pages,
 				'replies' => comma_format($row['num_replies']),
 				'views' => comma_format($row['num_views']),

+ 172 - 2
Sources/Printpage.php

@@ -29,20 +29,28 @@ if (!defined('SMF'))
 function PrintTopic()
 {
 	global $topic, $txt, $scripturl, $context, $user_info;
-	global $board_info, $smcFunc, $modSettings;
+	global $board_info, $smcFunc, $modSettings, $settings;
 
 	// Redirect to the boardindex if no valid topic id is provided.
 	if (empty($topic))
 		redirectexit();
 
+	if (!empty($modSettings['disable_print_topic']))
+	{
+		unset($_REQUEST['action']);
+		$context['theme_loaded'] = false;
+		fatal_lang_error('feature_disabled', false);
+	}
+
 	// Whatever happens don't index this.
 	$context['robot_no_index'] = true;
 
 	// Get the topic starter information.
 	$request = $smcFunc['db_query']('', '
-		SELECT m.poster_time, IFNULL(mem.real_name, m.poster_name) AS poster_name
+		SELECT mem.id_member, m.poster_time, IFNULL(mem.real_name, m.poster_name) AS poster_name, t.id_poll
 		FROM {db_prefix}messages AS m
 			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
+			LEFT JOIN {db_prefix}topics as t ON (t.id_first_msg = m.id_msg)
 		WHERE m.id_topic = {int:current_topic}
 		ORDER BY m.id_msg
 		LIMIT 1',
@@ -56,6 +64,168 @@ function PrintTopic()
 	$row = $smcFunc['db_fetch_assoc']($request);
 	$smcFunc['db_free_result']($request);
 
+	if (!empty($row['id_poll']))
+	{
+		loadLanguage('Post');
+		// Get the question and if it's locked.
+		$request = $smcFunc['db_query']('', '
+			SELECT
+				p.question, p.voting_locked, p.hide_results, p.expire_time, p.max_votes, p.change_vote,
+				p.guest_vote, p.id_member, IFNULL(mem.real_name, p.poster_name) AS poster_name, p.num_guest_voters, p.reset_poll
+			FROM {db_prefix}polls AS p
+				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = p.id_member)
+			WHERE p.id_poll = {int:id_poll}
+			LIMIT 1',
+			array(
+				'id_poll' => $row['id_poll'],
+			)
+		);
+		$pollinfo = $smcFunc['db_fetch_assoc']($request);
+		$smcFunc['db_free_result']($request);
+
+		$request = $smcFunc['db_query']('', '
+			SELECT COUNT(DISTINCT id_member) AS total
+			FROM {db_prefix}log_polls
+			WHERE id_poll = {int:id_poll}
+				AND id_member != {int:not_guest}',
+			array(
+				'id_poll' => $row['id_poll'],
+				'not_guest' => 0,
+			)
+		);
+		list ($pollinfo['total']) = $smcFunc['db_fetch_row']($request);
+		$smcFunc['db_free_result']($request);
+
+		// Total voters needs to include guest voters
+		$pollinfo['total'] += $pollinfo['num_guest_voters'];
+
+		// Get all the options, and calculate the total votes.
+		$request = $smcFunc['db_query']('', '
+			SELECT pc.id_choice, pc.label, pc.votes, IFNULL(lp.id_choice, -1) AS voted_this
+			FROM {db_prefix}poll_choices AS pc
+				LEFT JOIN {db_prefix}log_polls AS lp ON (lp.id_choice = pc.id_choice AND lp.id_poll = {int:id_poll} AND lp.id_member = {int:current_member} AND lp.id_member != {int:not_guest})
+			WHERE pc.id_poll = {int:id_poll}',
+			array(
+				'current_member' => $user_info['id'],
+				'id_poll' => $row['id_poll'],
+				'not_guest' => 0,
+			)
+		);
+		$pollOptions = array();
+		$realtotal = 0;
+		$pollinfo['has_voted'] = false;
+		while ($row = $smcFunc['db_fetch_assoc']($request))
+		{
+			censorText($row['label']);
+			$pollOptions[$row['id_choice']] = $row;
+			$realtotal += $row['votes'];
+			$pollinfo['has_voted'] |= $row['voted_this'] != -1;
+		}
+		$smcFunc['db_free_result']($request);
+
+		// If this is a guest we need to do our best to work out if they have voted, and what they voted for.
+		if ($user_info['is_guest'] && $pollinfo['guest_vote'] && allowedTo('poll_vote'))
+		{
+			if (!empty($_COOKIE['guest_poll_vote']) && preg_match('~^[0-9,;]+$~', $_COOKIE['guest_poll_vote']) && strpos($_COOKIE['guest_poll_vote'], ';' . $row['id_poll'] . ',') !== false)
+			{
+				// ;id,timestamp,[vote,vote...]; etc
+				$guestinfo = explode(';', $_COOKIE['guest_poll_vote']);
+				// Find the poll we're after.
+				foreach ($guestinfo as $i => $guestvoted)
+				{
+					$guestvoted = explode(',', $guestvoted);
+					if ($guestvoted[0] == $row['id_poll'])
+						break;
+				}
+				// Has the poll been reset since guest voted?
+				if ($pollinfo['reset_poll'] > $guestvoted[1])
+				{
+					// Remove the poll info from the cookie to allow guest to vote again
+					unset($guestinfo[$i]);
+					if (!empty($guestinfo))
+						$_COOKIE['guest_poll_vote'] = ';' . implode(';', $guestinfo);
+					else
+						unset($_COOKIE['guest_poll_vote']);
+				}
+				else
+				{
+					// What did they vote for?
+					unset($guestvoted[0], $guestvoted[1]);
+					foreach ($pollOptions as $choice => $details)
+					{
+						$pollOptions[$choice]['voted_this'] = in_array($choice, $guestvoted) ? 1 : -1;
+						$pollinfo['has_voted'] |= $pollOptions[$choice]['voted_this'] != -1;
+					}
+					unset($choice, $details, $guestvoted);
+				}
+				unset($guestinfo, $guestvoted, $i);
+			}
+		}
+
+		$context['user']['started'] = $user_info['id'] == $row['id_member'] && !$user_info['is_guest'];
+		// Set up the basic poll information.
+		$context['poll'] = array(
+			'id' => $row['id_poll'],
+			'image' => 'normal_' . (empty($pollinfo['voting_locked']) ? 'poll' : 'locked_poll'),
+			'question' => parse_bbc($pollinfo['question']),
+			'total_votes' => $pollinfo['total'],
+			'change_vote' => !empty($pollinfo['change_vote']),
+			'is_locked' => !empty($pollinfo['voting_locked']),
+			'options' => array(),
+			'lock' => allowedTo('poll_lock_any') || ($context['user']['started'] && allowedTo('poll_lock_own')),
+			'edit' => allowedTo('poll_edit_any') || ($context['user']['started'] && allowedTo('poll_edit_own')),
+			'allowed_warning' => $pollinfo['max_votes'] > 1 ? sprintf($txt['poll_options6'], min(count($pollOptions), $pollinfo['max_votes'])) : '',
+			'is_expired' => !empty($pollinfo['expire_time']) && $pollinfo['expire_time'] < time(),
+			'expire_time' => !empty($pollinfo['expire_time']) ? timeformat($pollinfo['expire_time']) : 0,
+			'has_voted' => !empty($pollinfo['has_voted']),
+			'starter' => array(
+				'id' => $pollinfo['id_member'],
+				'name' => $row['poster_name'],
+				'href' => $pollinfo['id_member'] == 0 ? '' : $scripturl . '?action=profile;u=' . $pollinfo['id_member'],
+				'link' => $pollinfo['id_member'] == 0 ? $row['poster_name'] : '<a href="' . $scripturl . '?action=profile;u=' . $pollinfo['id_member'] . '">' . $row['poster_name'] . '</a>'
+			)
+		);
+
+		// Make the lock and edit permissions defined above more directly accessible.
+		$context['allow_lock_poll'] = $context['poll']['lock'];
+		$context['allow_edit_poll'] = $context['poll']['edit'];
+
+		// You're allowed to view the results if:
+		// 1. you're just a super-nice-guy, or
+		// 2. anyone can see them (hide_results == 0), or
+		// 3. you can see them after you voted (hide_results == 1), or
+		// 4. you've waited long enough for the poll to expire. (whether hide_results is 1 or 2.)
+		$context['allow_poll_view'] = allowedTo('moderate_board') || $pollinfo['hide_results'] == 0 || ($pollinfo['hide_results'] == 1 && $context['poll']['has_voted']) || $context['poll']['is_expired'];
+
+		// Calculate the percentages and bar lengths...
+		$divisor = $realtotal == 0 ? 1 : $realtotal;
+
+		// Determine if a decimal point is needed in order for the options to add to 100%.
+		$precision = $realtotal == 100 ? 0 : 1;
+
+		// Now look through each option, and...
+		foreach ($pollOptions as $i => $option)
+		{
+			// First calculate the percentage, and then the width of the bar...
+			$bar = round(($option['votes'] * 100) / $divisor, $precision);
+			$barWide = $bar == 0 ? 1 : floor(($bar * 8) / 3);
+
+			// Now add it to the poll's contextual theme data.
+			$context['poll']['options'][$i] = array(
+				'id' => 'options-' . $i,
+				'percent' => $bar,
+				'votes' => $option['votes'],
+				'voted_this' => $option['voted_this'] != -1,
+				'bar' => '<span style="white-space: nowrap;"><img src="' . $settings['images_url'] . '/poll_' . ($context['right_to_left'] ? 'right' : 'left') . '.png" alt="" /><img src="' . $settings['images_url'] . '/poll_middle.png" width="' . $barWide . '" height="12" alt="-" /><img src="' . $settings['images_url'] . '/poll_' . ($context['right_to_left'] ? 'left' : 'right') . '.png" alt="" /></span>',
+				// Note: IE < 8 requires us to set a width on the container, too.
+				'bar_ndt' => $bar > 0 ? '<div class="bar" style="width: ' . ($bar * 3.5 + 4) . 'px;"><div style="width: ' . $bar * 3.5 . 'px;"></div></div>' : '',
+				'bar_width' => $barWide,
+				'option' => parse_bbc($option['label']),
+				'vote_button' => '<input type="' . ($pollinfo['max_votes'] > 1 ? 'checkbox' : 'radio') . '" name="options[]" id="options-' . $i . '" value="' . $i . '" class="input_' . ($pollinfo['max_votes'] > 1 ? 'check' : 'radio') . '" />'
+			);
+		}
+	}
+
 	// Lets "output" all that info.
 	loadTemplate('Printpage');
 	$context['template_layers'] = array('print');

+ 4 - 0
Sources/Profile-View.php

@@ -625,6 +625,10 @@ function statPanel($memID)
 
 	$context['page_title'] = $txt['statPanel_showStats'] . ' ' . $user_profile[$memID]['real_name'];
 
+	// Is the load average too high to allow searching just now?
+	if (!empty($context['load_average']) && !empty($modSettings['loadavg_userstats']) && $context['load_average'] >= $modSettings['loadavg_userstats'])
+		fatal_lang_error('loadavg_userstats_disabled', false);
+
 	// General user statistics.
 	$timeDays = floor($user_profile[$memID]['total_time_logged_in'] / 86400);
 	$timeHours = floor(($user_profile[$memID]['total_time_logged_in'] % 86400) / 3600);

+ 1 - 1
Sources/Subs.php

@@ -2571,7 +2571,7 @@ function redirectexit($setLocation = '', $refresh = false)
 	if (!empty($modSettings['queryless_urls']) && (empty($context['server']['is_cgi']) || ini_get('cgi.fix_pathinfo') == 1 || @get_cfg_var('cgi.fix_pathinfo') == 1) && (!empty($context['server']['is_apache']) || !empty($context['server']['is_lighttpd']) || !empty($context['server']['is_litespeed'])))
 	{
 		if (defined('SID') && SID != '')
-			$setLocation = preg_replace('/^' . preg_quote($scripturl, '/') . '\?(?:' . SID . '(?:;|&|&amp;))((?:board|topic)=[^#]+?)(#[^"]*?)?$/e', "\$scripturl . '/' . strtr('\$1', '&;=', '//,') . '.html\$2?' . SID", $setLocation);
+			$setLocation = preg_replace('/^' . preg_quote($scripturl, '/') . '\?(?:' . SID . '(?:;|&|&amp;))((?:board|topic)=[^#]+?)(#[^"]*?)?$/e', "\$scripturl . '/' . strtr('\$1', '&;=', '//,') . '.html?' . SID . '\$2'", $setLocation);
 		else
 			$setLocation = preg_replace('/^' . preg_quote($scripturl, '/') . '\?((?:board|topic)=[^#"]+?)(#[^"]*?)?$/e', "\$scripturl . '/' . strtr('\$1', '&;=', '//,') . '.html\$2'", $setLocation);
 	}

+ 5 - 3
Sources/Themes.php

@@ -61,7 +61,6 @@ function ThemesMain()
 		'admin' => 'ThemeAdmin',
 		'list' => 'ThemeList',
 		'reset' => 'SetThemeOptions',
-		'settings' => 'SetThemeSettings',
 		'options' => 'SetThemeOptions',
 		'install' => 'ThemeInstall',
 		'remove' => 'RemoveTheme',
@@ -198,6 +197,9 @@ function ThemeList()
 	loadLanguage('Admin');
 	isAllowedTo('admin_forum');
 
+	if (isset($_REQUEST['th']))
+		return SetThemeSettings();
+
 	if (isset($_POST['save']))
 	{
 		checkSession();
@@ -693,7 +695,7 @@ function SetThemeOptions()
  * - loads the Admin language file.
  * - calls ThemeAdmin() if no theme is specified. (the theme center.)
  * - requires admin_forum permission.
- * - accessed with ?action=admin;area=theme;sa=settings&th=xx.
+ * - accessed with ?action=admin;area=theme;sa=list&th=xx.
  */
 function SetThemeSettings()
 {
@@ -803,7 +805,7 @@ function SetThemeSettings()
 		// Invalidate the cache.
 		updateSettings(array('settings_updated' => time()));
 
-		redirectexit('action=admin;area=theme;sa=settings;th=' . $_GET['th'] . ';' . $context['session_var'] . '=' . $context['session_id']);
+		redirectexit('action=admin;area=theme;sa=list;th=' . $_GET['th'] . ';' . $context['session_var'] . '=' . $context['session_id']);
 	}
 
 	$context['sub_template'] = 'set_settings';

+ 57 - 15
Themes/default/Display.template.php

@@ -164,7 +164,7 @@ function template_main()
 		'notify' => array('test' => 'can_mark_notify', 'text' => $context['is_marked_notify'] ? 'unnotify' : 'notify', 'image' => ($context['is_marked_notify'] ? 'un' : '') . 'notify.png', 'lang' => true, 'custom' => 'onclick="return confirm(\'' . ($context['is_marked_notify'] ? $txt['notification_disable_topic'] : $txt['notification_enable_topic']) . '\');"', 'url' => $scripturl . '?action=notify;sa=' . ($context['is_marked_notify'] ? 'off' : 'on') . ';topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']),
 		'mark_unread' => array('test' => 'can_mark_unread', 'text' => 'mark_unread', 'image' => 'markunread.png', 'lang' => true, 'url' => $scripturl . '?action=markasread;sa=topic;t=' . $context['mark_unread_time'] . ';topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']),
 		'send' => array('test' => 'can_send_topic', 'text' => 'send_topic', 'image' => 'sendtopic.png', 'lang' => true, 'url' => $scripturl . '?action=emailuser;sa=sendtopic;topic=' . $context['current_topic'] . '.0'),
-		'print' => array('text' => 'print', 'image' => 'print.png', 'lang' => true, 'custom' => 'rel="new_win nofollow"', 'url' => $scripturl . '?action=printpage;topic=' . $context['current_topic'] . '.0'),
+		'print' => array('test' => 'can_print', 'text' => 'print', 'image' => 'print.png', 'lang' => true, 'custom' => 'rel="new_win nofollow"', 'url' => $scripturl . '?action=printpage;topic=' . $context['current_topic'] . '.0'),
 	);
 
 	// Allow adding new buttons easily.
@@ -703,14 +703,14 @@ function template_main()
 				<div class="cat_bar">
 					<h3 class="catbg">
 						<span class="ie6_header floatright">
-							<a href="javascript:oQuickReply.swap();"><img src="', $settings['images_url'], '/', $options['display_quick_reply'] == 2 ? 'collapse' : 'expand', '.png" alt="+" id="quickReplyExpand" class="icon" />		</a>
+							<a href="javascript:oQuickReply.swap();"><img src="', $settings['images_url'], '/', $options['display_quick_reply'] > 1 ? 'collapse' : 'expand', '.png" alt="+" id="quickReplyExpand" class="icon" /></a>
 						</span>
 						<span>
 							<a href="javascript:oQuickReply.swap();">', $txt['quick_reply'], '</a>
 						</span>
 					</h3>
 				</div>
-				<div id="quickReplyOptions"', $options['display_quick_reply'] == 2 ? '' : ' style="display: none"', '>
+				<div id="quickReplyOptions"', $options['display_quick_reply'] > 1 ? '' : ' style="display: none"', '>
 					<span class="upperframe"><span></span></span>
 					<div class="roundframe">
 						<p class="smalltext lefttext">', $txt['quick_reply_desc'], '</p>
@@ -730,31 +730,72 @@ function template_main()
 							<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
 							<input type="hidden" name="seqnum" value="', $context['form_sequence_number'], '" />';
 
-			// Guests just need more.
-			if ($context['user']['is_guest'])
-				echo '
+		// Guests just need more.
+		if ($context['user']['is_guest'])
+			echo '
 							<strong>', $txt['name'], ':</strong> <input type="text" name="guestname" value="', $context['name'], '" size="25" class="input_text" tabindex="', $context['tabindex']++, '" />
 							<strong>', $txt['email'], ':</strong> <input type="text" name="email" value="', $context['email'], '" size="25" class="input_text" tabindex="', $context['tabindex']++, '" /><br />';
 
-			// Is visual verification enabled?
-			if ($context['require_verification'])
-				echo '
+		// Is visual verification enabled?
+		if ($context['require_verification'])
+			echo '
 							<strong>', $txt['verification'], ':</strong>', template_control_verification($context['visual_verification_id'], 'quick_reply'), '<br />';
 
+		if ($options['display_quick_reply'] < 3)
+		{
 			echo '
 							<div class="quickReplyContent">
 								<textarea cols="600" rows="7" name="message" tabindex="', $context['tabindex']++, '"></textarea>
-							</div>
+							</div>';
+		}
+		else
+		{
+			// Show the actual posting area...
+			if ($context['show_bbc'])
+			{
+				echo '
+							<div id="bbcBox_message"></div>';
+			}
+
+			// What about smileys?
+			if (!empty($context['smileys']['postform']) || !empty($context['smileys']['popup']))
+				echo '
+							<div id="smileyBox_message"></div>';
+
+			echo '
+							', template_control_richedit($context['post_box_name'], 'smileyBox_message', 'bbcBox_message'), '
+							<script type="text/javascript"><!-- // --><![CDATA[
+								function insertQuoteFast(messageid)
+								{
+									if (window.XMLHttpRequest)
+										getXMLDocument(smf_prepareScriptUrl(smf_scripturl) + \'action=quotefast;quote=\' + messageid + \';xml;pb=', $context['post_box_name'], ';mode=\' + (oEditorHandle_', $context['post_box_name'], '.bRichTextEnabled ? 1 : 0), onDocReceived);
+									else
+										reqWin(smf_prepareScriptUrl(smf_scripturl) + \'action=quotefast;quote=\' + messageid + \';pb=', $context['post_box_name'], ';mode=\' + (oEditorHandle_', $context['post_box_name'], '.bRichTextEnabled ? 1 : 0), 240, 90);
+									return false;
+								}
+								function onDocReceived(XMLDoc)
+								{
+									var text = \'\';
+									for (var i = 0, n = XMLDoc.getElementsByTagName(\'quote\')[0].childNodes.length; i < n; i++)
+										text += XMLDoc.getElementsByTagName(\'quote\')[0].childNodes[i].nodeValue;
+									oEditorHandle_', $context['post_box_name'], '.insertText(text, false, true);
+
+									ajax_indicator(false);
+								}
+							// ]]></script>';
+
+		}
+		echo '
 							<div class="padding">
 								<hr class="hrcolor" />
 								<input type="submit" name="post" value="', $txt['post'], '" onclick="return submitThisOnce(this);" accesskey="s" tabindex="', $context['tabindex']++, '" class="button_submit" />
 								<input type="submit" name="preview" value="', $txt['preview'], '" onclick="return submitThisOnce(this);" accesskey="p" tabindex="', $context['tabindex']++, '" class="button_submit" />';
 
-			if ($context['show_spellchecking'])
-				echo '
+		if ($context['show_spellchecking'])
+			echo '
 								<input type="button" value="', $txt['spell_check'], '" onclick="spellCheck(\'postmodify\', \'message\');" tabindex="', $context['tabindex']++, '" class="button_submit" />';
 
-			echo '
+		echo '
 								<br class="clear_right" />
 							</div>
 						</form>
@@ -779,7 +820,7 @@ function template_main()
 	if (!empty($options['display_quick_reply']))
 		echo '
 					var oQuickReply = new QuickReply({
-						bDefaultCollapsed: ', !empty($options['display_quick_reply']) && $options['display_quick_reply'] == 2 ? 'false' : 'true', ',
+						bDefaultCollapsed: ', !empty($options['display_quick_reply']) && $options['display_quick_reply'] > 1 ? 'false' : 'true', ',
 						iTopicId: ', $context['current_topic'], ',
 						iStart: ', $context['start'], ',
 						sScriptUrl: smf_scripturl,
@@ -788,7 +829,8 @@ function template_main()
 						sImageId: "quickReplyExpand",
 						sImageCollapsed: "collapse.png",
 						sImageExpanded: "expand.png",
-						sJumpAnchor: "quickreply"
+						sJumpAnchor: "quickreply",
+						bIsFull: ', !empty($options['display_quick_reply']) && $options['display_quick_reply'] > 2 ? 'true' : 'false', '
 					});';
 
 	if (!empty($options['display_quick_mod']) && $options['display_quick_mod'] == 1 && $context['can_remove_post'])

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

@@ -405,12 +405,15 @@ function template_modify_board()
 
 	if (empty($modSettings['deny_boards_access']))
 		echo '
-							<em>', $txt['check_all'], '</em> <input type="checkbox" class="input_check" onclick="invertAll(this, this.form, \'groups[\');" /><br />
+							<span class="select_all_box">
+								<em>', $txt['check_all'], '</em> <input type="checkbox" class="input_check" onclick="invertAll(this, this.form, \'groups[\');" />
+							</span>
+							<br />
 							<br />
 						</dd>';
 	else
 		echo '
-								<tr>
+								<tr class="select_all_box">
 									<td>
 									</td>
 									<td>
@@ -440,6 +443,13 @@ function template_modify_board()
 							<div id="moderator_container"></div>
 						</dd>
 					</dl>
+					<script type="text/javascript"><!-- // --><![CDATA[
+						$(document).ready(function () {
+							$(".select_all_box").each(function () {
+								$(this).removeClass(\'select_all_box\');
+							});
+						});
+					// ]]></script>
 					<hr class="hrcolor" />';
 
 	if (empty($context['board']['is_recycle']) && empty($context['board']['topics']))

+ 95 - 67
Themes/default/ManageMembergroups.template.php

@@ -114,44 +114,17 @@ function template_new_group()
 							</fieldset>
 						</dd>';
 	}
+
 	echo '
 						<dt>
 							<strong>', $txt['membergroups_new_board'], ':</strong>', $context['post_group'] ? '<br />
 							<span class="smalltext" style="font-weight: normal">' . $txt['membergroups_new_board_post_groups'] . '</span>' : '', '
 						</dt>
-						<dd>
-							<fieldset id="visible_boards">
-								<legend>', $txt['membergroups_new_board_desc'], '</legend>
-								<ul class="ignoreboards floatleft">';
+						<dd>';
 
-	foreach ($context['categories'] as $category)
-	{
-		echo '
-									<li class="category">
-										<a href="javascript:void(0);" onclick="selectBoards([', implode(', ', $category['child_ids']), '], \'new_group\'); return false;">', $category['name'], '</a>
-									<ul>';
-
-		foreach ($category['boards'] as $board)
-		{
-			echo '
-										<li class="board" style="margin-', $context['right_to_left'] ? 'right' : 'left', ': ', $board['child_level'], 'em;">
-											<input type="checkbox" name="boardaccess[]" id="brd', $board['id'], '" value="', $board['id'], '" ', $board['selected'] ? ' checked="checked" disabled="disabled"' : '', ' class="input_check" /> <label for="brd', $board['id'], '">', $board['name'], '</label>
-										</li>';
-		}
-
-		echo '
-									</ul>
-								</li>';
-	}
-
-	echo '
-							</ul>
-							<br class="clear" />';
+	template_add_edit_group_boards_list(false);
 
 	echo '
-								<br />
-								<input type="checkbox" id="checkall_check" class="input_check" onclick="invertAll(this, this.form, \'boardaccess\');" /> <label for="checkall_check"><em>', $txt['check_all'], '</em></label>
-							</fieldset>
 						</dd>
 					</dl>
 					<hr class="hrcolor" />
@@ -327,44 +300,9 @@ function template_edit_group()
 							<strong>', $txt['membergroups_new_board'], ':</strong>', $context['group']['is_post_group'] ? '<br />
 							<span class="smalltext">' . $txt['membergroups_new_board_post_groups'] . '</span>' : '', '
 						</dt>
-						<dd>
-							<fieldset id="visible_boards" style="width: 95%;">
-								<legend><a href="javascript:void(0);" onclick="document.getElementById(\'visible_boards\').style.display = \'none\';document.getElementById(\'visible_boards_link\').style.display = \'block\'; return false;">', $txt['membergroups_new_board_desc'], '</a></legend>
-								<ul class="ignoreboards floatleft">';
-
-		foreach ($context['categories'] as $category)
-		{
-			echo '
-									<li class="category">
-										<a href="javascript:void(0);" onclick="selectBoards([', implode(', ', $category['child_ids']), '], \'groupForm\'); return false;">', $category['name'], '</a>
-										<ul>';
-
-			foreach ($category['boards'] as $board)
-			{
-				echo '
-											<li class="board" style="margin-', $context['right_to_left'] ? 'right' : 'left', ': ', $board['child_level'], 'em;">
-												<input type="checkbox" name="boardaccess[]" id="brd', $board['id'], '" value="', $board['id'], '" ', $board['selected'] ? ' checked="checked"' : '', ' class="input_check" /> <label for="brd', $board['id'], '">', $board['name'], '</label>
-											</li>';
-			}
-
-			echo '
-										</ul>
-									</li>';
-		}
-
-		echo '
-								</ul>
-								<br class="clear" />';
-
+						<dd>';
+		template_add_edit_group_boards_list();
 		echo '
-								<br />
-								<input type="checkbox" id="checkall_check" class="input_check" onclick="invertAll(this, this.form, \'boardaccess\');" /> <label for="checkall_check"><em>', $txt['check_all'], '</em></label>
-							</fieldset>
-							<a href="javascript:void(0);" onclick="document.getElementById(\'visible_boards\').style.display = \'block\'; document.getElementById(\'visible_boards_link\').style.display = \'none\'; return false;" id="visible_boards_link" style="display: none;">[ ', $txt['membergroups_select_visible_boards'], ' ]</a>
-							<script type="text/javascript"><!-- // --><![CDATA[
-								document.getElementById("visible_boards_link").style.display = "";
-								document.getElementById("visible_boards").style.display = "none";
-							// ]]></script>
 						</dd>';
 	}
 	echo '
@@ -431,6 +369,96 @@ function template_edit_group()
 		// ]]></script>';
 }
 
+function template_add_edit_group_boards_list($collapse = true)
+{
+	global $context, $txt, $modSettings;
+	echo '
+							<fieldset id="visible_boards">
+								<legend>', $txt['membergroups_new_board_desc'], '</legend>
+								<ul class="ignoreboards floatleft">';
+
+	foreach ($context['categories'] as $category)
+	{
+		if (empty($modSettings['deny_boards_access']))
+			echo '
+									<li class="category">
+										<a href="javascript:void(0);" onclick="selectBoards([', implode(', ', $category['child_ids']), '], \'new_group\'); return false;"><strong>', $category['name'], '</strong></a>
+									<ul style="width:100%">';
+		else
+			echo '
+									<li class="category">
+										<strong>', $category['name'], '</strong>
+										<span class="select_all_box">
+											<em style="margin-left:5em;">', $txt['all_boards_in_cat'], ': </em>
+											<select onchange="select_in_category(', $category['id'], ', this, [', implode(',', array_keys($category['boards'])), ']);">
+												<option>---</option>
+												<option value="allow">', $txt['board_perms_allow'], '</option>
+												<option value="ignore">', $txt['board_perms_ignore'], '</option>
+												<option value="deny">', $txt['board_perms_deny'], '</option>
+											</select>
+										</span>
+										<ul style="width:100%" id="boards_list_', $category['id'], '">';
+
+		foreach ($category['boards'] as $board)
+		{
+			if (empty($modSettings['deny_boards_access']))
+				echo '
+										<li class="board" style="margin-', $context['right_to_left'] ? 'right' : 'left', ': ', $board['child_level'], 'em;">
+											<input type="checkbox" name="boardaccess[', $board['id'], ']" id="brd', $board['id'], '" value="\'allow\'" ', $board['allow'] ? ' checked="checked"' : '', ' class="input_check" /> <label for="brd', $board['id'], '">', $board['name'], '</label>
+										</li>';
+			else
+				echo '
+											<li class="board" style="width:100%">
+												<span style="margin-', $context['right_to_left'] ? 'right' : 'left', ': ', $board['child_level'], 'em;">', $board['name'], ': </span>
+												<span style="width:50%;float:right">
+													<input type="radio" name="boardaccess[', $board['id'], ']" id="allow_brd', $board['id'], '" value="allow" ', $board['allow'] ? ' checked="checked"' : '', ' class="input_check" /> <label for="allow_brd', $board['id'], '">', $txt['permissions_option_on'], '</label>
+													<input type="radio" name="boardaccess[', $board['id'], ']" id="ignore_brd', $board['id'], '" value="ignore" ', !$board['allow'] && !$board['deny'] ? ' checked="checked"' : '', ' class="input_check" /> <label for="ignore_brd', $board['id'], '">', $txt['permissions_option_off'], '</label>
+													<input type="radio" name="boardaccess[', $board['id'], ']" id="deny_brd', $board['id'], '" value="deny" ', $board['deny'] ? ' checked="checked"' : '', ' class="input_check" /> <label for="deny_brd', $board['id'], '">', $txt['permissions_option_deny'], '</label>
+												</span>
+											</li>';
+		}
+
+		echo '
+									</ul>
+								</li>';
+	}
+
+	echo '
+							</ul>
+							<br class="clear" />';
+
+	if (empty($modSettings['deny_boards_access']))
+		echo '
+								<br />
+								<input type="checkbox" id="checkall_check" class="input_check" onclick="invertAll(this, this.form, \'boardaccess\');" /> <label for="checkall_check"><em>', $txt['check_all'], '</em></label>
+							</fieldset>';
+	else
+		echo '
+								<br />
+								<span class="select_all_box">
+									<em>', $txt['all'], ': </em>
+									<input type="radio" name="select_all" id="allow_all" class="input_radio" onclick="selectAllRadio(this, this.form, \'boardaccess\', \'allow\');" /> <label for="allow_all">', $txt['board_perms_allow'], '</label>
+									<input type="radio" name="select_all" id="ignore_all" class="input_radio" onclick="selectAllRadio(this, this.form, \'boardaccess\', \'ignore\');" /> <label for="ignore_all">', $txt['board_perms_ignore'], '</label>
+									<input type="radio" name="select_all" id="deny_all" class="input_radio" onclick="selectAllRadio(this, this.form, \'boardaccess\', \'deny\');" /> <label for="deny_all">', $txt['board_perms_deny'], '</label>
+								</span>
+							</fieldset>
+							<script type="text/javascript"><!-- // --><![CDATA[
+								$(document).ready(function () {
+									$(".select_all_box").each(function () {
+										$(this).removeClass(\'select_all_box\');
+									});
+								});
+							// ]]></script>';
+
+	if ($collapse)
+		echo '
+							<a href="javascript:void(0);" onclick="document.getElementById(\'visible_boards\').style.display = \'block\'; document.getElementById(\'visible_boards_link\').style.display = \'none\'; return false;" id="visible_boards_link" style="display: none;">[ ', $txt['membergroups_select_visible_boards'], ' ]</a>
+							<script type="text/javascript"><!-- // --><![CDATA[
+								document.getElementById("visible_boards_link").style.display = "";
+								document.getElementById("visible_boards").style.display = "none";
+							// ]]></script>';
+}
+
 // Templating for viewing the members of a group.
 function template_group_members()
 {

+ 29 - 8
Themes/default/Printpage.template.php

@@ -50,13 +50,13 @@ function template_print_above()
 				padding: 0;
 				list-style: none;
 			}
-			dt.postheader
+			div.postheader, #poll_data
 			{
 				border: solid #000;
 				border-width: 1px 0;
 				padding: 4px 0;
 			}
-			dd.postbody
+			div.postbody
 			{
 				margin: 1em 0 2em 2em;
 			}
@@ -98,27 +98,48 @@ function template_print_above()
 				color: black;
 				background-color: black;
 			}
+			.voted
+			{
+				font-weight: bold;
+			}
 		</style>
 	</head>
 	<body>
 		<h1 id="title">', $context['forum_name_html_safe'], '</h1>
 		<h2 id="linktree">', $context['category_name'], ' => ', (!empty($context['parent_boards']) ? implode(' => ', $context['parent_boards']) . ' => ' : ''), $context['board_name'], ' => ', $txt['topic_started'], ': ', $context['poster_name'], ' ', $txt['search_on'], ' ', $context['post_time'], '</h2>
-		<dl id="posts">';
+		<div id="posts">';
 }
 
 function template_main()
 {
 	global $context, $settings, $options, $txt;
 
+	if (!empty($context['poll']))
+	{
+		echo '
+			<div id="poll_data">', $txt['poll'], '
+				<div class="question">', $txt['poll_question'], ': <strong>', $context['poll']['question'], '</strong>';
+
+		$options = 1;
+		foreach ($context['poll']['options'] as $option)
+			echo '
+					<div class="', $option['voted_this'] ? 'voted' : '', '">', $txt['option'], ' ', $options++, ': <strong>', $option['option'], '</strong>
+						', $context['allow_poll_view'] ? $txt['votes'] . ': ' . $option['votes'] . '' : '', '
+					</div>';
+
+		echo '
+			</div>';
+	}
+
 	foreach ($context['posts'] as $post)
 		echo '
-			<dt class="postheader">
+			<div class="postheader">
 				', $txt['title'], ': <strong>', $post['subject'], '</strong><br />
 				', $txt['post_by'], ': <strong>', $post['member'], '</strong> ', $txt['search_on'], ' <strong>', $post['time'], '</strong>
-			</dt>
-			<dd class="postbody">
+			</div>
+			<div class="postbody">
 				', $post['body'], '
-			</dd>';
+			</div>';
 }
 
 function template_print_below()
@@ -126,7 +147,7 @@ function template_print_below()
 	global $context, $settings, $options;
 
 	echo '
-		</dl>
+		</div>
 		<div id="footer" class="smalltext">
 			', theme_copyright(), '
 		</div>

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

@@ -1668,6 +1668,7 @@ function template_profile_theme_settings()
 									<option value="0"', empty($context['member']['options']['display_quick_reply']) ? ' selected="selected"' : '', '>', $txt['display_quick_reply1'], '</option>
 									<option value="1"', !empty($context['member']['options']['display_quick_reply']) && $context['member']['options']['display_quick_reply'] == 1 ? ' selected="selected"' : '', '>', $txt['display_quick_reply2'], '</option>
 									<option value="2"', !empty($context['member']['options']['display_quick_reply']) && $context['member']['options']['display_quick_reply'] == 2 ? ' selected="selected"' : '', '>', $txt['display_quick_reply3'], '</option>
+									<option value="3"', !empty($context['member']['options']['display_quick_reply']) && $context['member']['options']['display_quick_reply'] == 3 ? ' selected="selected"' : '', '>', $txt['display_quick_reply4'], '</option>
 								</select>
 							</dd>
 							<dt>

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

@@ -130,7 +130,8 @@ function template_options()
 			'options' => array(
 				0 => $txt['display_quick_reply1'],
 				1 => $txt['display_quick_reply2'],
-				2 => $txt['display_quick_reply3']
+				2 => $txt['display_quick_reply3'],
+				3 => $txt['display_quick_reply4']
 			),
 			'default' => true,
 		),

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

@@ -214,7 +214,7 @@ function template_list_themes()
 		echo '
 			<div class="title_bar">
 				<h3 class="titlebg">
-					<span class="floatleft"><strong><a href="', $scripturl, '?action=admin;area=theme;th=', $theme['id'], ';', $context['session_var'], '=', $context['session_id'], ';sa=settings">', $theme['name'], '</a></strong>', !empty($theme['version']) ? ' <em>(' . $theme['version'] . ')</em>' : '', '</span>';
+					<span class="floatleft"><strong><a href="', $scripturl, '?action=admin;area=theme;th=', $theme['id'], ';', $context['session_var'], '=', $context['session_id'], ';sa=list">', $theme['name'], '</a></strong>', !empty($theme['version']) ? ' <em>(' . $theme['version'] . ')</em>' : '', '</span>';
 
 			// You *cannot* delete the default theme. It's important!
 			if ($theme['id'] != 1)
@@ -434,7 +434,7 @@ function template_set_settings()
 
 	echo '
 	<div id="admincenter">
-		<form action="', $scripturl, '?action=admin;area=theme;sa=settings;th=', $context['theme_settings']['theme_id'], '" method="post" accept-charset="', $context['character_set'], '">
+		<form action="', $scripturl, '?action=admin;area=theme;sa=list;th=', $context['theme_settings']['theme_id'], '" method="post" accept-charset="', $context['character_set'], '">
 			<div class="title_bar">
 				<h3 class="titlebg">
 					<span class="ie6_header floatleft"><a href="', $scripturl, '?action=helpadmin;help=theme_settings" onclick="return reqWin(this.href);" class="help"><img src="', $settings['images_url'], '/helptopics.png" alt="', $txt['help'], '" class="icon" /></a> ', $txt['theme_settings'], ' - ', $context['theme_settings']['name'], '</span>
@@ -772,7 +772,7 @@ function template_installed()
 			<span class="topslice"><span></span></span>
 			<div class="content">
 				<p>
-					<a href="', $scripturl, '?action=admin;area=theme;sa=settings;th=', $context['installed_theme']['id'], ';', $context['session_var'], '=', $context['session_id'], '">', $context['installed_theme']['name'], '</a> ', $txt['theme_installed_message'], '
+					<a href="', $scripturl, '?action=admin;area=theme;sa=list;th=', $context['installed_theme']['id'], ';', $context['session_var'], '=', $context['session_id'], '">', $context['installed_theme']['name'], '</a> ', $txt['theme_installed_message'], '
 				</p>
 				<p>
 					<a href="', $scripturl, '?action=admin;area=theme;sa=admin;', $context['session_var'], '=', $context['session_id'], '">', $txt['back'], '</a>

+ 3 - 0
Themes/default/css/admin.css

@@ -288,6 +288,9 @@ pre.file_content {
 	border-bottom: 1px dotted #000;
 	cursor: help;
 }
+.select_all_box {
+	display:none;
+}
 
 /* Styles for the manage members section.
 ------------------------------------------------- */

+ 1 - 2
Themes/default/css/index.css

@@ -1947,7 +1947,6 @@ img.smiley {
 	width: 635px;
 	max-width: 100%;
 	min-width: 100%;
-	margin: 0.25em 0 1em 0;
 }
 /* The jump to box */
 #display_jump_to {
@@ -2771,7 +2770,7 @@ img.centericon {
 .ignoreboards {
 	margin: 0 2%;
 	padding: 0;
-	width: 45%;
+	width: 90%;
 }
 .ignoreboards a {
 	font-weight: bold;

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

@@ -636,4 +636,4 @@ function template_css()
 	<link rel="stylesheet" type="text/css" href="', $filename, '" />';
 }
 
-?>
+?>

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

@@ -526,6 +526,7 @@ $txt['oldTopicDays'] = 'Time before topic is warned as old on reply';
 $txt['oldTopicDays_zero'] = '0 to disable';
 $txt['defaultMaxTopics'] = 'Number of topics per page in the message index';
 $txt['defaultMaxMessages'] = 'Number of posts per page in a topic page';
+$txt['disable_print_topic'] = 'Disable print topic feature';
 $txt['hotTopicPosts'] = 'Number of posts for a hot topic';
 $txt['hotTopicVeryPosts'] = 'Number of posts for a very hot topic';
 $txt['enableAllMessages'] = 'Max topic size to show &quot;All&quot; posts';
@@ -659,4 +660,9 @@ $txt['hooks_disable_legend_disabled'] = 'the hook exists but has been disabled';
 $txt['hooks_disable_legend_missing'] = 'the hook has not been found';
 $txt['hooks_reset_filter'] = 'Reset filter';
 
+$txt['board_perms_allow'] = 'Allow';
+$txt['board_perms_ignore'] = 'Ignore';
+$txt['board_perms_deny'] = 'Deny';
+$txt['all_boards_in_cat'] = 'All boards in this category';
+
 ?>

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

@@ -346,6 +346,7 @@ $txt['loadavg_allunread_disabled'] = 'The server\'s resources are temporarily un
 $txt['loadavg_unreadreplies_disabled'] = 'The server is currently under high stress.  Please try again shortly.';
 $txt['loadavg_show_posts_disabled'] = 'Please try again later.  This member\'s posts are not currently available due to high load on the server.';
 $txt['loadavg_unread_disabled'] = 'The server\'s resources are temporarily under too high a demand to list out the topics you have not read.';
+$txt['loadavg_userstats_disabled'] = 'Please try again later.  This member\'s statistics are not currently available due to high load on the server.';
 
 $txt['cannot_edit_permissions_inherited'] = 'You cannot edit inherited permissions directly, you must either edit the parent group or edit the membergroup inheritance.';
 

+ 11 - 11
Themes/default/languages/Help.english.php

@@ -17,21 +17,21 @@ $helptxt['manage_boards'] = '
 		<li>
 			<strong>Sports</strong>
 			&nbsp;- A &quot;category&quot;
-		</li>
-		<ul class="normallist">
-			<li>
-				<strong>Baseball</strong>
-				&nbsp;- A board under the category of &quot;Sports&quot;
-			</li>
 			<ul class="normallist">
 				<li>
-					<strong>Stats</strong>
-					&nbsp;- A child board under the board of &quot;Baseball&quot;
+					<strong>Baseball</strong>
+					&nbsp;- A board under the category of &quot;Sports&quot;
+					<ul class="normallist">
+						<li>
+							<strong>Stats</strong>
+							&nbsp;- A child board under the board of &quot;Baseball&quot;
+						</li>
+					</ul>
 				</li>
+				<li><strong>Football</strong>
+				&nbsp;- A board under the category of &quot;Sports&quot;</li>
 			</ul>
-			<li><strong>Football</strong>
-			&nbsp;- A board under the category of &quot;Sports&quot;</li>
-		</ul>
+		</li>
 	</ul>
 	Categories allow you to break down the board into broad topics (&quot;Cars,
 	Sports&quot;), and the &quot;Boards&quot; under them are the actual topics under which

+ 2 - 1
Themes/default/languages/ManageSettings.english.php

@@ -3,7 +3,7 @@
 
 global $scripturl;
 
-$txt['modSettings_desc'] = 'This page allows you to change the settings of features and basic options in your forum.  Please see the <a href="' . $scripturl . '?action=admin;area=theme;sa=settings;th=%1$s;%3$s=%2$s">theme settings</a> for more options.  Click the help icons for more information about a setting.';
+$txt['modSettings_desc'] = 'This page allows you to change the settings of features and basic options in your forum.  Please see the <a href="' . $scripturl . '?action=admin;area=theme;sa=list;th=%1$s;%3$s=%2$s">theme settings</a> for more options.  Click the help icons for more information about a setting.';
 $txt['security_settings_desc'] = 'This page allows you to set options specifically related to the security and moderation of your forum, including anti-spam options.';
 $txt['modification_settings_desc'] = 'This page contains settings added by any modifications to your forum';
 
@@ -147,6 +147,7 @@ $txt['loadavg_search'] = 'Threshold to disabling search';
 $txt['loadavg_allunread'] = 'Threshold to disabling all unread topics';
 $txt['loadavg_unreadreplies'] = 'Threshold to disabling unread replies';
 $txt['loadavg_show_posts'] = 'Threshold to disabling showing user posts';
+$txt['loadavg_userstats'] = 'Threshold to disabling showing user statistics';
 $txt['loadavg_bbc'] = 'Threshold to disabling BBC formating when showing posts';
 $txt['loadavg_forum'] = 'Threshold to disabling the forum <strong>completely</strong>';
 $txt['loadavg_disabled_windows'] = '<span class="error">Load balancing support is not available on Windows.</span>';

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

@@ -290,6 +290,7 @@ $txt['display_quick_reply'] = 'Use quick reply on topic display: ';
 $txt['display_quick_reply1'] = 'don\'t show at all';
 $txt['display_quick_reply2'] = 'show, off by default';
 $txt['display_quick_reply3'] = 'show, on by default';
+$txt['display_quick_reply4'] = 'show full editor, on by default';
 $txt['display_quick_mod'] = 'Show quick-moderation as ';
 $txt['display_quick_mod_none'] = 'don\'t show.';
 $txt['display_quick_mod_check'] = 'checkboxes.';

+ 0 - 2
Themes/default/languages/Reports.english.php

@@ -21,8 +21,6 @@ $txt['results'] = 'Results';
 
 // Board permissions
 $txt['board_perms_permission'] = 'Permission';
-$txt['board_perms_allow'] = 'Allow';
-$txt['board_perms_deny'] = 'Deny';
 $txt['board_perms_name_announce_topic'] = 'Announce topic';
 $txt['board_perms_name_approve_posts'] = 'Approve posts';
 $txt['board_perms_name_delete_any'] = 'Delete any posts';

+ 8 - 0
Themes/default/scripts/admin.js

@@ -599,4 +599,12 @@ function repeatString(sString, iTime)
 		return '';
 	else
 		return sString + repeatString(sString, iTime - 1);
+}
+
+function select_in_category(cat_id, elem, brd_list)
+{
+	for (var brd in brd_list)
+		document.getElementById(elem.value + '_brd' + brd_list[brd]).checked = true;
+
+	elem.selectedIndex = 0;
 }

+ 1 - 1
Themes/default/scripts/script.js

@@ -533,7 +533,7 @@ function selectRadioByName(oRadioGroup, sName)
 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)
+		if (oForm[i].name != undefined && oForm[i].name.substr(0, sMask.length) == sMask && oForm[i].value == sValue)
 			oForm[i].checked = true;
 }
 

+ 6 - 2
Themes/default/scripts/topic.js

@@ -123,6 +123,7 @@ function QuickReply(oOptions)
 {
 	this.opt = oOptions;
 	this.bCollapsed = this.opt.bDefaultCollapsed;
+	this.bIsFull = this.opt.bIsFull;
 }
 
 // When a user presses quote, put it in the quick reply box (if expanded).
@@ -143,7 +144,10 @@ QuickReply.prototype.quote = function (iMessageId, xDeprecated)
 		if (window.XMLHttpRequest)
 		{
 			ajax_indicator(true);
-			getXMLDocument(smf_prepareScriptUrl(this.opt.sScriptUrl) + 'action=quotefast;quote=' + iMessageId + ';xml', this.onQuoteReceived);
+			if (this.bIsFull)
+				insertQuoteFast(iMessageId);
+			else
+				getXMLDocument(smf_prepareScriptUrl(this.opt.sScriptUrl) + 'action=quotefast;quote=' + iMessageId + ';xml', this.onQuoteReceived);
 		}
 		// Or with a smart popup!
 		else
@@ -176,7 +180,7 @@ QuickReply.prototype.onQuoteReceived = function (oXMLDoc)
 QuickReply.prototype.swap = function ()
 {
 	document.getElementById(this.opt.sImageId).src = this.opt.sImagesUrl + "/" + (this.bCollapsed ? this.opt.sImageCollapsed : this.opt.sImageExpanded);
-	document.getElementById(this.opt.sContainerId).style.display = this.bCollapsed ? '' : 'none';
+	$('#' + this.opt.sContainerId).slideToggle();
 
 	this.bCollapsed = !this.bCollapsed;
 }

+ 60 - 26
Themes/penguin/Display.template.php

@@ -159,7 +159,7 @@ function template_main()
 
 	// Build the normal button array.
 	$normal_buttons = array(
-		'print' => array('text' => 'print', 'image' => 'print.png', 'lang' => true, 'custom' => 'rel="new_win nofollow"', 'url' => $scripturl . '?action=printpage;topic=' . $context['current_topic'] . '.0'),
+		'print' => array('test' => 'can_print', 'text' => 'print', 'image' => 'print.png', 'lang' => true, 'custom' => 'rel="new_win nofollow"', 'url' => $scripturl . '?action=printpage;topic=' . $context['current_topic'] . '.0'),
 		'send' => array('test' => 'can_send_topic', 'text' => 'send_topic', 'image' => 'sendtopic.png', 'lang' => true, 'url' => $scripturl . '?action=emailuser;sa=sendtopic;topic=' . $context['current_topic'] . '.0'),
 		'mark_unread' => array('test' => 'can_mark_unread', 'text' => 'mark_unread', 'image' => 'markunread.png', 'lang' => true, 'url' => $scripturl . '?action=markasread;sa=topic;t=' . $context['mark_unread_time'] . ';topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']),
 		'notify' => array('test' => 'can_mark_notify', 'text' => $context['is_marked_notify'] ? 'unnotify' : 'notify', 'image' => ($context['is_marked_notify'] ? 'un' : '') . 'notify.png', 'lang' => true, 'custom' => 'onclick="return confirm(\'' . ($context['is_marked_notify'] ? $txt['notification_disable_topic'] : $txt['notification_enable_topic']) . '\');"', 'url' => $scripturl . '?action=notify;sa=' . ($context['is_marked_notify'] ? 'off' : 'on') . ';topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']),
@@ -174,8 +174,6 @@ function template_main()
 	// Allow adding new buttons easily.
 	call_integration_hook('integrate_display_buttons', array(&$normal_buttons));
 
-	// Show the page index... "Pages: [1]".
-
 	// Show the topic information - icon, subject, etc.
 	echo '
 			<div id="forumposts">
@@ -519,7 +517,7 @@ function template_main()
 									// Show a checkbox for quick moderation?
 									if (!empty($options['display_quick_mod']) && $options['display_quick_mod'] == 1 && $message['can_remove'])
 										echo '
-											<li class="inline_mod_check" style="display: none;" id="in_topic_mod_check_', $message['id'], '"><label for="fukn_pita_bastard_', $message['id'], '">Select post&nbsp;</label></li>';
+											<li class="inline_mod_check" style="display: none;" id="in_topic_mod_check_', $message['id'], '"><label for="in_topic_mod_check_', $message['id'], '">Select post&nbsp;</label></li>';
 										echo '
 											<li><a href="', $scripturl, '?action=', !empty($message['member']['is_guest']) ? 'trackip' : 'profile;area=tracking;sa=ip;u=' . $message['member']['id'], ';searchip=', $message['member']['ip'], '" class="ip_link">', $message['member']['ip'], '</a></li>
 										</ul>
@@ -603,12 +601,12 @@ function template_main()
 				<div class="cat_bar">
 					<h3 class="catbg">
 						<a href="javascript:oQuickReply.swap();" id="QuickReply_swap">
-							<img src="', $settings['images_url'], '/', $options['display_quick_reply'] == 2 ? 'upshrink' : 'upshrink2', '.png" alt="+" id="quickReplyExpand" class="icon floatright" />
+							<img src="', $settings['images_url'], '/', $options['display_quick_reply'] > 1 ? 'upshrink' : 'upshrink2', '.png" alt="+" id="quickReplyExpand" class="icon floatright" />
 						</a>
 						<a href="javascript:oQuickReply.swap();">', $txt['quick_reply'], '</a>
 					</h3>
 				</div>
-				<div id="quickReplyOptions"', $options['display_quick_reply'] == 2 ? '' : ' style="display: none"', '>
+				<div id="quickReplyOptions"', $options['display_quick_reply'] > 1 ? '' : ' style="display: none"', '>
 					<div class="roundframe">
 						<p class="smalltext lefttext">', $txt['quick_reply_desc'], '</p>
 						', $context['is_locked'] ? '<p class="alert smalltext">' . $txt['quick_reply_warning'] . '</p>' : '',
@@ -627,23 +625,66 @@ function template_main()
 							<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
 							<input type="hidden" name="seqnum" value="', $context['form_sequence_number'], '" />';
 
-			// Guests just need more.
-			if ($context['user']['is_guest'])
-				echo '
+		// Guests just need more.
+		if ($context['user']['is_guest'])
+			echo '
 							<strong>', $txt['name'], ':</strong> <input type="text" name="guestname" value="', $context['name'], '" size="25" class="input_text" tabindex="', $context['tabindex']++, '" />
 							<strong>', $txt['email'], ':</strong> <input type="text" name="email" value="', $context['email'], '" size="25" class="input_text" tabindex="', $context['tabindex']++, '" /><br />';
 
-			// Is visual verification enabled?
-			if ($context['require_verification'])
-				echo '
+		// Is visual verification enabled?
+		if ($context['require_verification'])
+			echo '
 							<strong>', $txt['verification'], ':</strong>', template_control_verification($context['visual_verification_id'], 'quick_reply'), '<br />';
 
+		if ($options['display_quick_reply'] < 3)
+		{
 			echo '
 							<div class="quickReplyContent">
 								<textarea class ="expand_test" cols="" rows="" name="message" tabindex="', $context['tabindex']++, '"></textarea>
-							</div>
+							</div>';
+		}
+		else
+		{
+			// Show the actual posting area...
+			if ($context['show_bbc'])
+			{
+				echo '
+								<div id="bbcBox_message"></div>';
+			}
+
+			// What about smileys?
+			if (!empty($context['smileys']['postform']) || !empty($context['smileys']['popup']))
+				echo '
+								<div id="smileyBox_message"></div>';
+
+			echo '
+							', template_control_richedit($context['post_box_name'], 'smileyBox_message', 'bbcBox_message'), '
+								<script type="text/javascript"><!-- // --><![CDATA[
+									function insertQuoteFast(messageid)
+									{
+										if (window.XMLHttpRequest)
+											getXMLDocument(smf_prepareScriptUrl(smf_scripturl) + \'action=quotefast;quote=\' + messageid + \';xml;pb=', $context['post_box_name'], ';mode=\' + (oEditorHandle_', $context['post_box_name'], '.bRichTextEnabled ? 1 : 0), onDocReceived);
+										else
+											reqWin(smf_prepareScriptUrl(smf_scripturl) + \'action=quotefast;quote=\' + messageid + \';pb=', $context['post_box_name'], ';mode=\' + (oEditorHandle_', $context['post_box_name'], '.bRichTextEnabled ? 1 : 0), 240, 90);
+										return false;
+									}
+									function onDocReceived(XMLDoc)
+									{
+										var text = \'\';
+										for (var i = 0, n = XMLDoc.getElementsByTagName(\'quote\')[0].childNodes.length; i < n; i++)
+											text += XMLDoc.getElementsByTagName(\'quote\')[0].childNodes[i].nodeValue;
+										oEditorHandle_', $context['post_box_name'], '.insertText(text, false, true);
+
+										ajax_indicator(false);
+									}
+								// ]]></script>';
+
+		}
+		echo '
+							<div class="padding">
 								<input type="submit" name="post" value="', $txt['post'], '" onclick="return submitThisOnce(this);" accesskey="s" tabindex="', $context['tabindex']++, '" class="button_submit" />
-								<input type="submit" name="preview" value="', $txt['preview'], '" onclick="return submitThisOnce(this);" accesskey="p" tabindex="', $context['tabindex']++, '" class="button_submit" />';
+								<input type="submit" name="preview" value="', $txt['preview'], '" onclick="return submitThisOnce(this);" accesskey="p" tabindex="', $context['tabindex']++, '" class="button_submit" />
+							</div>';
 
 			if ($context['show_spellchecking'])
 				echo '
@@ -668,10 +709,10 @@ function template_main()
 				<script type="text/javascript" src="' . $settings['default_theme_url'] . '/scripts/topic.js"></script>
 				<script type="text/javascript"><!-- // --><![CDATA[';
 
-/*	if (!empty($options['display_quick_reply']))
+	if (!empty($options['display_quick_reply']))
 		echo '
 					var oQuickReply = new QuickReply({
-						bDefaultCollapsed: ', !empty($options['display_quick_reply']) && $options['display_quick_reply'] == 2 ? 'false' : 'true', ',
+						bDefaultCollapsed: ', !empty($options['display_quick_reply']) && $options['display_quick_reply'] > 1 ? 'false' : 'true', ',
 						iTopicId: ', $context['current_topic'], ',
 						iStart: ', $context['start'], ',
 						sScriptUrl: smf_scripturl,
@@ -680,9 +721,10 @@ function template_main()
 						sImageId: "quickReplyExpand",
 						sImageCollapsed: "upshrink.png",
 						sImageExpanded: "upshrink2.png",
-						sJumpAnchor: "quickreply"
+						sJumpAnchor: "quickreply",
+						bIsFull: ', !empty($options['display_quick_reply']) && $options['display_quick_reply'] > 2 ? 'true' : 'false', '
 					});';
-*/
+
 	if (!empty($options['display_quick_mod']) && $options['display_quick_mod'] == 1 && $context['can_remove_post'])
 		echo '
 					var oInTopicModeration = new InTopicModeration({
@@ -801,15 +843,7 @@ function template_main()
 	}
 
 	echo '
-
 		$(document).ready(function(){
-			$("#quickReplyOptions").hide();
-			$("#QuickReply_swap").show();
-
-			$("#QuickReply_swap").click(function(){
-				$("#quickReplyOptions").slideToggle();
-			});
-
 			$("li a.quote_button, li a.modify_button, li a.modify_inline, a.topic_reply_title").bt(jQuery.bt.options = {positions: "top, bottom"});
 		});
 

+ 1 - 0
Themes/penguin/Profile.template.php

@@ -1628,6 +1628,7 @@ function template_profile_theme_settings()
 									<option value="0"', empty($context['member']['options']['display_quick_reply']) ? ' selected="selected"' : '', '>', $txt['display_quick_reply1'], '</option>
 									<option value="1"', !empty($context['member']['options']['display_quick_reply']) && $context['member']['options']['display_quick_reply'] == 1 ? ' selected="selected"' : '', '>', $txt['display_quick_reply2'], '</option>
 									<option value="2"', !empty($context['member']['options']['display_quick_reply']) && $context['member']['options']['display_quick_reply'] == 2 ? ' selected="selected"' : '', '>', $txt['display_quick_reply3'], '</option>
+									<option value="3"', !empty($context['member']['options']['display_quick_reply']) && $context['member']['options']['display_quick_reply'] == 3 ? ' selected="selected"' : '', '>', $txt['display_quick_reply4'], '</option>
 								</select>
 							</dd>
 							<dt>

+ 1 - 0
Themes/penguin/Settings.template.php

@@ -131,6 +131,7 @@ function template_options()
 				0 => $txt['display_quick_reply1'],
 				1 => $txt['display_quick_reply2'],
 				2 => $txt['display_quick_reply3']
+				3 => $txt['display_quick_reply4']
 			),
 			'default' => true,
 		),

+ 3 - 0
Themes/penguin/css/admin.css

@@ -316,6 +316,9 @@ pre.file_content {
 	border-bottom: 1px dotted #000;
 	cursor: help;
 }
+.select_all_box {
+	display:none;
+}
 
 /* Styles for the manage members section.
 ------------------------------------------------- */

+ 1 - 2
Themes/penguin/css/index.css

@@ -1848,7 +1848,6 @@ img.smiley {
 	width: 635px;
 	max-width: 100%;
 	min-width: 100%;
-	margin: 10px 0;
 }
 /* The jump to box */
 #display_jump_to {
@@ -2672,7 +2671,7 @@ img.centericon {
 .ignoreboards {
 	margin: 0 2%;
 	padding: 0;
-	width: 45%;
+	width: 90%;
 }
 .ignoreboards a {
 	font-weight: bold;

+ 8 - 0
Themes/penguin/scripts/admin.js

@@ -599,4 +599,12 @@ function repeatString(sString, iTime)
 		return '';
 	else
 		return sString + repeatString(sString, iTime - 1);
+}
+
+function select_in_category(cat_id, elem, brd_list)
+{
+	for (var brd in brd_list)
+	{
+		document.getElementById(elem.value + '_brd' + brd_list[brd]).checked = true;
+	}
 }

+ 2 - 8
other/install.php

@@ -912,7 +912,6 @@ function ForumSettings()
 
 	// Check if the database sessions will even work.
 	$incontext['test_dbsession'] = ini_get('session.auto_start') != 1;
-	$incontext['utf8_should_work'] = stripos(PHP_OS, 'win') === false;
 	$incontext['utf8_default'] = $databases[$db_type]['utf8_default'];
 	$incontext['utf8_required'] = $databases[$db_type]['utf8_required'];
 
@@ -2437,19 +2436,14 @@ function template_forum_settings()
 					<input type="checkbox" name="dbsession" id="dbsession_check" checked="checked" class="input_check" /> <label for="dbsession_check">', $txt['install_settings_dbsession_title'], '</label><br />
 					<div style="font-size: smaller; margin-bottom: 2ex;">', $incontext['test_dbsession'] ? $txt['install_settings_dbsession_info1'] : $txt['install_settings_dbsession_info2'], '</div>
 				</td>
-			</tr>';
-
-	if ($incontext['utf8_should_work'])
-		echo '
+			</tr>
 			<tr>
 				<td valign="top" class="textbox">', $txt['install_settings_utf8'], ':</td>
 				<td>
 					<input type="checkbox" name="utf8" id="utf8_check"', $incontext['utf8_default'] ? ' checked="checked"' : '', ' class="input_check"', $incontext['utf8_required'] ? ' disabled="disabled"' : '', ' /> <label for="utf8_check">', $txt['install_settings_utf8_title'], '</label><br />
 					<div style="font-size: smaller; margin-bottom: 2ex;">', $txt['install_settings_utf8_info'], '</div>
 				</td>
-			</tr>';
-
-	echo '
+			</tr>
 			<tr>
 				<td valign="top" class="textbox">', $txt['install_settings_stats'], ':</td>
 				<td>

+ 1 - 1
other/install_2-1_mysql.sql

@@ -989,7 +989,7 @@ CREATE TABLE {$db_prefix}log_reported (
   id_member mediumint(8) unsigned NOT NULL default '0',
   membername varchar(255) NOT NULL default '',
   subject varchar(255) NOT NULL default '',
-  body text NOT NULL,
+  body mediumtext NOT NULL,
   time_started int(10) NOT NULL default '0',
   time_updated int(10) NOT NULL default '0',
   num_reports mediumint(6) NOT NULL default '0',