2
0
Эх сурвалжийг харах

Merge branch 'release-2.1' of git://github.com/SimpleMachines/SMF2.1.git into minor-stuff

Conflicts:
	Sources/ModerationCenter.php
	Sources/ReportToMod.php
	Sources/Subs.php
	Themes/default/ModerationCenter.template.php
	Themes/default/SendTopic.template.php

Signed-off-by: Suki <[email protected]>
Suki 11 жил өмнө
parent
commit
6a1a9c9b2a
82 өөрчлөгдсөн 2635 нэмэгдсэн , 1333 устгасан
  1. 26 25
      Sources/Calendar.php
  2. 15 6
      Sources/Display.php
  3. 3 2
      Sources/Errors.php
  4. 24 49
      Sources/Load.php
  5. 2 0
      Sources/ManageAttachments.php
  6. 1 14
      Sources/ManageMembers.php
  7. 11 3
      Sources/ManageNews.php
  8. 2 0
      Sources/ManagePermissions.php
  9. 4 4
      Sources/ManageSettings.php
  10. 1 0
      Sources/ManageSmileys.php
  11. 1 32
      Sources/Memberlist.php
  12. 627 11
      Sources/ModerationCenter.php
  13. 13 5
      Sources/Modlog.php
  14. 0 11
      Sources/News.php
  15. 6 0
      Sources/PackageGet.php
  16. 11 18
      Sources/Post.php
  17. 1 1
      Sources/Profile-Actions.php
  18. 4 63
      Sources/Profile-Modify.php
  19. 2 0
      Sources/Profile-View.php
  20. 9 0
      Sources/Profile.php
  21. 46 7
      Sources/Recent.php
  22. 0 10
      Sources/Register.php
  23. 9 2
      Sources/RemoveTopic.php
  24. 210 198
      Sources/ReportToMod.php
  25. 11 36
      Sources/Security.php
  26. 1 1
      Sources/Subs-Calendar.php
  27. 3 0
      Sources/Subs-Db-mysql.php
  28. 4 1
      Sources/Subs-Db-mysqli.php
  29. 2 2
      Sources/Subs-Db-postgresql.php
  30. 2 11
      Sources/Subs-Members.php
  31. 63 17
      Sources/Subs.php
  32. 1 1
      Sources/Themes.php
  33. 5 1
      Sources/tasks/EventNew-Notify.php
  34. 135 0
      Sources/tasks/MemberReport-Notify.php
  35. 161 0
      Sources/tasks/MemberReportReply-Notify.php
  36. 11 5
      Themes/default/Admin.template.php
  37. 4 4
      Themes/default/BoardIndex.template.php
  38. 3 3
      Themes/default/Calendar.template.php
  39. 8 34
      Themes/default/Display.template.php
  40. 1 1
      Themes/default/GenericControls.template.php
  41. 1 1
      Themes/default/GenericMenu.template.php
  42. 0 20
      Themes/default/ManageMembers.template.php
  43. 5 0
      Themes/default/ManageNews.template.php
  44. 0 20
      Themes/default/Memberlist.template.php
  45. 327 0
      Themes/default/ModerationCenter.template.php
  46. 101 99
      Themes/default/Packages.template.php
  47. 2 19
      Themes/default/PersonalMessage.template.php
  48. 3 3
      Themes/default/Post.template.php
  49. 18 56
      Themes/default/Profile.template.php
  50. 6 0
      Themes/default/Recent.template.php
  51. 105 0
      Themes/default/ReportToMod.template.php
  52. 0 197
      Themes/default/SendTopic.template.php
  53. 37 4
      Themes/default/Themes.template.php
  54. 1 2
      Themes/default/Who.template.php
  55. 199 0
      Themes/default/css/calendar.css
  56. 24 0
      Themes/default/css/calendar.rtl.css
  57. 5 207
      Themes/default/css/index.css
  58. 0 25
      Themes/default/css/rtl.css
  59. 4 2
      Themes/default/languages/Admin.english.php
  60. 2 0
      Themes/default/languages/Alerts.english.php
  61. 36 0
      Themes/default/languages/EmailTemplates.english.php
  62. 1 2
      Themes/default/languages/Errors.english.php
  63. 1 1
      Themes/default/languages/Help.english.php
  64. 2 0
      Themes/default/languages/Install.english.php
  65. 5 2
      Themes/default/languages/ManagePermissions.english.php
  66. 1 0
      Themes/default/languages/ManageSmileys.english.php
  67. 11 1
      Themes/default/languages/ModerationCenter.english.php
  68. 6 0
      Themes/default/languages/Modlog.english.php
  69. 1 0
      Themes/default/languages/PersonalMessage.english.php
  70. 5 0
      Themes/default/languages/Post.english.php
  71. 6 4
      Themes/default/languages/Profile.english.php
  72. 5 22
      Themes/default/languages/index.english.php
  73. 1 2
      index.php
  74. 49 12
      other/install.php
  75. 0 7
      other/install_2-1_mysql.sql
  76. 0 7
      other/install_2-1_postgresql.sql
  77. 0 7
      other/install_2-1_sqlite.sql
  78. 0 7
      other/install_2-1_sqlite3.sql
  79. 30 2
      other/upgrade.php
  80. 64 8
      other/upgrade_2-1_mysql.sql
  81. 64 8
      other/upgrade_2-1_postgresql.sql
  82. 64 8
      other/upgrade_2-1_sqlite.sql

+ 26 - 25
Sources/Calendar.php

@@ -49,13 +49,14 @@ function CalendarMain()
 	if (isset($_GET['sa']) && isset($subActions[$_GET['sa']]) && !WIRELESS)
 		return $subActions[$_GET['sa']]();
 
-	// This is gonna be needed...
-	loadTemplate('Calendar');
-
 	// You can't do anything if the calendar is off.
 	if (empty($modSettings['cal_enabled']))
 		fatal_lang_error('calendar_off', false);
 
+	// This is gonna be needed...
+	loadTemplate('Calendar');
+	loadCSSFile('calendar.css', array('force_current' => false, 'validate' => true, 'rtl' => 'calendar.rtl.css'));
+
 	// Did the specify an individual event ID? If so, let's splice the year/month in to what we would otherwise be doing.
 	if (isset($_GET['event']))
 	{
@@ -160,7 +161,7 @@ function CalendarMain()
 
 	// Basic template stuff.
 	$context['allow_calendar_event'] = allowedTo('calendar_post');
-	
+
 	// If you don't allow events not linked to posts and you're not an admin, we have more work to do...
 	if ($context['allow_calendar_event'] && empty($modSettings['cal_allow_unlinked']) && !$user_info['is_admin'])
 	{
@@ -243,7 +244,7 @@ function CalendarPost()
 			isAllowedTo('calendar_edit_' . (!empty($user_info['id']) && getEventPoster($_REQUEST['eventid']) == $user_info['id'] ? 'own' : 'any'));
 
 		// New - and directing?
-		if ($_REQUEST['eventid'] == -1 && (isset($_POST['link_to_board']) || empty($modSettings['cal_allow_unlinked'])))
+		if (isset($_POST['link_to_board']) || empty($modSettings['cal_allow_unlinked']))
 		{
 			$_REQUEST['calendar'] = 1;
 			require_once($sourcedir . '/Post.php');
@@ -327,26 +328,6 @@ function CalendarPost()
 			'span' => 1,
 		);
 		$context['event']['last_day'] = (int) strftime('%d', mktime(0, 0, 0, $context['event']['month'] == 12 ? 1 : $context['event']['month'] + 1, 0, $context['event']['month'] == 12 ? $context['event']['year'] + 1 : $context['event']['year']));
-
-		// Get list of boards that can be posted in.
-		$boards = boardsAllowedTo('post_new');
-		if (empty($boards))
-		{
-			// You can post new events but can't link them to anything...
-			$context['event']['categories'] = array();
-		}
-		else
-		{
-			// Load the list of boards and categories in the context.
-			require_once($sourcedir . '/Subs-MessageIndex.php');
-			$boardListOptions = array(
-				'included_boards' => in_array(0, $boards) ? null : $boards,
-				'not_redirection' => true,
-				'use_permissions' => true,
-				'selected_board' => $modSettings['cal_defaultboard'],
-			);
-			$context['event']['categories'] = getBoardList($boardListOptions);
-		}
 	}
 	else
 	{
@@ -370,6 +351,26 @@ function CalendarPost()
 			isAllowedTo('calendar_edit_own');
 	}
 
+	// Get list of boards that can be posted in.
+	$boards = boardsAllowedTo('post_new');
+	if (empty($boards))
+	{
+		// You can post new events but can't link them to anything...
+		$context['event']['categories'] = array();
+	}
+	else
+	{
+		// Load the list of boards and categories in the context.
+		require_once($sourcedir . '/Subs-MessageIndex.php');
+		$boardListOptions = array(
+			'included_boards' => in_array(0, $boards) ? null : $boards,
+			'not_redirection' => true,
+			'use_permissions' => true,
+			'selected_board' => $modSettings['cal_defaultboard'],
+		);
+		$context['event']['categories'] = getBoardList($boardListOptions);
+	}
+
 	// Template, sub template, etc.
 	loadTemplate('Calendar');
 	$context['sub_template'] = 'event_post';

+ 15 - 6
Sources/Display.php

@@ -378,9 +378,6 @@ function Display()
 	// Did we report a post to a moderator just now?
 	$context['report_sent'] = isset($_GET['reportsent']);
 
-	// Did we send this topic to a friend?
-	$context['topic_sent'] = isset($_GET['topicsent']);
-
 	// Let's get nosey, who is viewing this topic?
 	if (!empty($settings['display_who_viewing']))
 	{
@@ -543,7 +540,7 @@ function Display()
 	$context['mark_unread_time'] = !empty($virtual_msg) ? $virtual_msg : $topicinfo['new_from'];
 
 	// Set a canonical URL for this page.
-	$context['canonical_url'] = $scripturl . '?topic=' . $topic . '.' . $context['start'];
+	$context['canonical_url'] = $scripturl . '?topic=' . $topic . '.' . ($can_show_all ? '0;all' : $context['start']);
 
 	// For quick reply we need a response prefix in the default forum language.
 	if (!isset($context['response_prefix']) && !($context['response_prefix'] = cache_get_data('response_prefix', 600)))
@@ -1097,6 +1094,12 @@ function Display()
 		$context['can_move'] &= count($boards_allowed) > 1;
 	}
 
+	// If a topic is locked, you can't remove it unless it's yours and you locked it or you can lock_any
+	if ($topicinfo['locked'])
+	{
+		$context['can_delete'] &= (($topicinfo['locked'] == 1 && $context['user']['started']) || allowedTo('lock_any'));
+	}
+
 	// Cleanup all the permissions with extra stuff...
 	$context['can_mark_notify'] = !$context['user']['is_guest'];
 	$context['calendar_post'] &= !empty($modSettings['cal_enabled']);
@@ -1268,6 +1271,12 @@ function prepareDisplayContext($reset = false)
 	// Are you allowed to remove at least a single reply?
 	$context['can_remove_post'] |= allowedTo('delete_own') && (empty($modSettings['edit_disable_time']) || $message['poster_time'] + $modSettings['edit_disable_time'] * 60 >= time()) && $message['id_member'] == $user_info['id'];
 
+	// If the topic is locked, you might not be able to delete the post...
+	if ($context['is_locked'])
+	{
+		$context['can_remove_post'] &= ($context['user']['started'] && $context['is_locked'] == 1) || allowedTo('lock_any');
+	}
+
 	// If it couldn't load, or the user was a guest.... someday may be done with a guest table.
 	if (!loadMemberContext($message['id_member'], true))
 	{
@@ -1277,7 +1286,7 @@ function prepareDisplayContext($reset = false)
 		$memberContext[$message['id_member']]['group'] = $txt['guest_title'];
 		$memberContext[$message['id_member']]['link'] = $message['poster_name'];
 		$memberContext[$message['id_member']]['email'] = $message['poster_email'];
-		$memberContext[$message['id_member']]['show_email'] = showEmailAddress(true, 0);
+		$memberContext[$message['id_member']]['show_email'] = allowedTo('admin_forum');
 		$memberContext[$message['id_member']]['is_guest'] = true;
 	}
 	else
@@ -1342,7 +1351,7 @@ function prepareDisplayContext($reset = false)
 	$output['is_message_author'] = $message['id_member'] == $user_info['id'];
 	if (!empty($output['modified']['name']))
 		$output['modified']['last_edit_text'] = sprintf($txt['last_edit_by'], $output['modified']['time'], $output['modified']['name']);
-	
+
 	// Did they give a reason for editing?
 	if (!empty($output['modified']['name']) && !empty($output['modified']['reason']))
 		$output['modified']['last_edit_text'] .= '&nbsp;' . sprintf($txt['last_edit_reason'], $output['modified']['reason']);

+ 3 - 2
Sources/Errors.php

@@ -374,8 +374,9 @@ function display_maintenance_message()
 function display_db_error()
 {
 	global $mbname, $modSettings, $maintenance;
-	global $db_connection, $webmaster_email, $db_last_error, $db_error_send, $smcFunc;
+	global $db_connection, $webmaster_email, $db_last_error, $db_error_send, $smcFunc, $sourcedir;
 
+	require_once($sourcedir . '/Logging.php');
 	set_fatal_error_headers();
 
 	// For our purposes, we're gonna want this on if at all possible.
@@ -457,4 +458,4 @@ function set_fatal_error_headers()
 	header('Retry-After: 3600');
 }
 
-?>
+?>

+ 24 - 49
Sources/Load.php

@@ -946,9 +946,9 @@ function loadMemberData($users, $is_name = false, $set = 'normal')
 	// Used by default
 	$select_columns = '
 			IFNULL(lo.log_time, 0) AS is_online, IFNULL(a.id_attach, 0) AS id_attach, a.filename, a.attachment_type,
-			mem.signature, mem.personal_text, mem.location, mem.gender, mem.avatar, mem.id_member, mem.member_name,
+			mem.signature, mem.personal_text, mem.avatar, mem.id_member, mem.member_name,
 			mem.real_name, mem.email_address, mem.hide_email, mem.date_registered, mem.website_title, mem.website_url,
-			mem.birthdate, mem.member_ip, mem.member_ip2, mem.icq, mem.aim, mem.yim, mem.skype, mem.posts, mem.last_login,
+			mem.birthdate, mem.member_ip, mem.member_ip2, mem.posts, mem.last_login,
 			mem.karma_good, mem.id_post_group, mem.karma_bad, mem.lngfile, mem.id_group, mem.time_offset, mem.show_online,
 			mg.online_color AS member_group_color, IFNULL(mg.group_name, {string:blank_string}) AS member_group,
 			pg.online_color AS post_group_color, IFNULL(pg.group_name, {string:blank_string}) AS post_group,
@@ -1121,10 +1121,8 @@ function loadMemberContext($user, $display_custom_fields = false)
 	// Censor everything.
 	censorText($profile['signature']);
 	censorText($profile['personal_text']);
-	censorText($profile['location']);
 
 	// Set things up to be used before hand.
-	$gendertxt = $profile['gender'] == 2 ? $txt['female'] : ($profile['gender'] == 1 ? $txt['male'] : '');
 	$profile['signature'] = str_replace(array("\n", "\r"), array('<br>', ''), $profile['signature']);
 	$profile['signature'] = parse_bbc($profile['signature'], true, 'sig' . $profile['id_member']);
 
@@ -1142,7 +1140,7 @@ function loadMemberContext($user, $display_custom_fields = false)
 		'href' => $scripturl . '?action=profile;u=' . $profile['id_member'],
 		'link' => '<a href="' . $scripturl . '?action=profile;u=' . $profile['id_member'] . '" title="' . $txt['profile_of'] . ' ' . $profile['real_name'] . '">' . $profile['real_name'] . '</a>',
 		'email' => $profile['email_address'],
-		'show_email' => showEmailAddress(!empty($profile['hide_email']), $profile['id_member']),
+		'show_email' => !$user_info['is_guest'] && ($user_info['id'] == $profile['id_member'] || allowedTo('moderate_forum')),
 		'registered' => empty($profile['date_registered']) ? $txt['not_applicable'] : timeformat($profile['date_registered']),
 		'registered_timestamp' => empty($profile['date_registered']) ? 0 : forum_time(true, $profile['date_registered']),
 	);
@@ -1158,41 +1156,12 @@ function loadMemberContext($user, $display_custom_fields = false)
 			'buddies' => $buddy_list,
 			'title' => !empty($modSettings['titlesEnable']) ? $profile['usertitle'] : '',
 			'blurb' => $profile['personal_text'],
-			'gender' => array(
-				'name' => $gendertxt,
-				'image' => !empty($profile['gender']) ? '<span class="generic_icons ' . ($profile['gender'] == 1 ? 'gender_male' : 'gender_female') . '" title="' . $gendertxt . '"></span>' : ''
-			),
 			'website' => array(
 				'title' => $profile['website_title'],
 				'url' => $profile['website_url'],
 			),
 			'birth_date' => empty($profile['birthdate']) || $profile['birthdate'] === '0001-01-01' ? '0000-00-00' : (substr($profile['birthdate'], 0, 4) === '0004' ? '0000' . substr($profile['birthdate'], 4) : $profile['birthdate']),
 			'signature' => $profile['signature'],
-			'location' => $profile['location'],
-			'icq' => $profile['icq'] != '' && !$user_info['is_guest'] ? array(
-				'name' => $profile['icq'],
-				'href' => 'http://www.icq.com/whitepages/about_me.php?uin=' . $profile['icq'],
-				'link' => '<a class="icq new_win" href="http://www.icq.com/whitepages/about_me.php?uin=' . $profile['icq'] . '" target="_blank" title="' . $txt['icq_title'] . ' - ' . $profile['icq'] . '"><img src="' . $settings['images_url'] . '/icq.png" alt="' . $txt['icq'] . ' - ' . $profile['icq'] . '"></a>',
-				'link_text' => '<a class="icq extern" href="http://www.icq.com/whitepages/about_me.php?uin=' . $profile['icq'] . '" title="' . $txt['icq_title'] . ' - ' . $profile['icq'] . '">' . $profile['icq'] . '</a>',
-			) : array('name' => '', 'add' => '', 'href' => '', 'link' => '', 'link_text' => ''),
-			'aim' => $profile['aim'] != '' && !$user_info['is_guest'] ? array(
-				'name' => $profile['aim'],
-				'href' => 'aim:goim?screenname=' . urlencode(strtr($profile['aim'], array(' ' => '%20'))) . '&amp;message=' . $txt['aim_default_message'],
-				'link' => '<a class="aim" href="aim:goim?screenname=' . urlencode(strtr($profile['aim'], array(' ' => '%20'))) . '&amp;message=' . $txt['aim_default_message'] . '" title="' . $txt['aim_title'] . ' - ' . $profile['aim'] . '"><img src="' . $settings['images_url'] . '/aim.png" alt="' . $txt['aim_title'] . ' - ' . $profile['aim'] . '"></a>',
-				'link_text' => '<a class="aim" href="aim:goim?screenname=' . urlencode(strtr($profile['aim'], array(' ' => '%20'))) . '&amp;message=' . $txt['aim_default_message'] . '" title="' . $txt['aim_title'] . ' - ' . $profile['aim'] . '">' . $profile['aim'] . '</a>'
-			) : array('name' => '', 'href' => '', 'link' => '', 'link_text' => ''),
-			'yim' => $profile['yim'] != '' && !$user_info['is_guest'] ? array(
-				'name' => $profile['yim'],
-				'href' => 'http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($profile['yim']),
-				'link' => '<a class="yim" href="http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($profile['yim']) . '" title="' . $txt['yim_title'] . ' - ' . $profile['yim'] . '"><img src="' . $settings['images_url'] . '/yahoo.png" alt="' . $txt['yim_title'] . ' - ' . $profile['yim'] . '"></a>',
-				'link_text' => '<a class="yim" href="http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($profile['yim']) . '" title="' . $txt['yim_title'] . ' - ' . $profile['yim'] . '">' . $profile['yim'] . '</a>'
-			) : array('name' => '', 'href' => '', 'link' => '', 'link_text' => ''),
-			'skype' => !empty($profile['skype']) && !$user_info['is_guest'] ? array(
-				'name' => $profile['skype'],
-				'href' => 'skype:' . $profile['skype'] . '?chat',
-				'link' => '<a class="skype new_win" href="skype:' . $profile['skype'] . '?chat" title="' . $txt['skype'] . ' - ' . $profile['skype'] . '"><img src="' . $settings['images_url'] . '/skype.png" alt="' . $txt['skype'] . ' - ' . $profile['skype'] . '"></a>',
-				'link_text' => '<a class="skype new_win" href="skype:' . $profile['skype'] . '?chat" title="' . $txt['skype'] . ' - ' . $profile['skype'] . '">' . $profile['skype'] . '</a>',
-			) : array('name' => '', 'href' => '', 'link' => '', 'link_text' => '',),
 			'real_posts' => $profile['posts'],
 			'posts' => $profile['posts'] > 500000 ? $txt['geek'] : comma_format($profile['posts']),
 			'avatar' => array(
@@ -1236,17 +1205,6 @@ function loadMemberContext($user, $display_custom_fields = false)
 			'local_time' => timeformat(time() + ($profile['time_offset'] - $user_info['time_offset']) * 3600, false),
 		);
 
-	// First do a quick run through to make sure there is something to be shown.
-	$memberContext[$user]['has_messenger'] = false;
-	foreach (array('icq', 'skype', 'aim', 'yim') as $messenger)
-	{
-		if (!isset($context['disabled_fields'][$messenger]) && !empty($memberContext[$user][$messenger]['link']))
-		{
-			$memberContext[$user]['has_messenger'] = true;
-			break;
-		}
-	}
-
 	// Are we also loading the members custom fields into context?
 	if ($display_custom_fields && !empty($modSettings['displayFields']))
 	{
@@ -1982,7 +1940,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=list;th=1;' . $context['session_var'] . '=' . $context['session_id'], '" class="alert">', $txt['theme_dir_wrong'], '</a>
+	<a href="', $scripturl . '?action=admin;area=theme;sa=list;' . $context['session_var'] . '=' . $context['session_id'], '" class="alert">', $txt['theme_dir_wrong'], '</a>
 </div>';
 		}
 
@@ -2078,6 +2036,9 @@ function loadCSSFile($filename, $params = array(), $id = '')
 	// Add it to the array for use in the template
 	if (!empty($filename))
 		$context['css_files'][$id] = array('filename' => $filename, 'options' => $params);
+
+	if (!empty($context['right_to_left']) && !empty($params['rtl']))
+		loadCSSFile($params['rtl'], array_diff_key($params, array('rtl' => 0)));
 }
 
 /**
@@ -2703,7 +2664,7 @@ function template_include($filename, $once = false)
 function loadDatabase()
 {
 	global $db_persist, $db_connection, $db_server, $db_user, $db_passwd;
-	global $db_type, $db_name, $ssi_db_user, $ssi_db_passwd, $sourcedir, $db_prefix;
+	global $db_type, $db_name, $ssi_db_user, $ssi_db_passwd, $sourcedir, $db_prefix, $db_port;
 
 	// Figure out what type of database we are using.
 	if (empty($db_type) || !file_exists($sourcedir . '/Subs-Db-' . $db_type . '.php'))
@@ -2712,13 +2673,27 @@ function loadDatabase()
 	// Load the file for the database.
 	require_once($sourcedir . '/Subs-Db-' . $db_type . '.php');
 
+	$db_options = array();
+
+	// Add in the port if needed
+	if (!empty($db_port))
+		$db_options['port'] = $db_port;
+
 	// If we are in SSI try them first, but don't worry if it doesn't work, we have the normal username and password we can use.
 	if (SMF == 'SSI' && !empty($ssi_db_user) && !empty($ssi_db_passwd))
-		$db_connection = smf_db_initiate($db_server, $db_name, $ssi_db_user, $ssi_db_passwd, $db_prefix, array('persist' => $db_persist, 'non_fatal' => true, 'dont_select_db' => true));
+	{
+		$options = array_merge($db_options, array('persist' => $db_persist, 'non_fatal' => true, 'dont_select_db' => true));
+
+		$db_connection = smf_db_initiate($db_server, $db_name, $ssi_db_user, $ssi_db_passwd, $db_prefix, $options);
+	}
 
 	// Either we aren't in SSI mode, or it failed.
 	if (empty($db_connection))
-		$db_connection = smf_db_initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, array('persist' => $db_persist, 'dont_select_db' => SMF == 'SSI'));
+	{
+		$options = array_merge($db_options, array('persist' => $db_persist, 'dont_select_db' => SMF == 'SSI'));
+
+		$db_connection = smf_db_initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, $options);
+	}
 
 	// Safe guard here, if there isn't a valid connection lets put a stop to it.
 	if (!$db_connection)

+ 2 - 0
Sources/ManageAttachments.php

@@ -284,6 +284,7 @@ function ManageAvatarSettings($return_config = false)
 		array('title', 'avatar_server_stored'),
 			array('warning', empty($testImg) ? 'avatar_img_enc_warning' : ''),
 			array('permissions', 'profile_server_avatar', 0, $txt['avatar_server_stored_groups']),
+			array('warning', !$context['valid_avatar_dir'] ? 'avatar_directory_wrong' : ''),
 			array('text', 'avatar_directory', 40, 'invalid' => !$context['valid_avatar_dir']),
 			array('text', 'avatar_url', 40),
 		// External avatars?
@@ -311,6 +312,7 @@ function ManageAvatarSettings($return_config = false)
 			array('warning', 'avatar_paranoid_warning'),
 			array('check', 'avatar_paranoid'),
 		'',
+			array('warning', !$context['valid_custom_avatar_dir'] ? 'custom_avatar_dir_wrong' : ''),
 			array('text', 'custom_avatar_dir', 40, 'subtext' => $txt['custom_avatar_dir_desc'], 'invalid' => !$context['valid_custom_avatar_dir']),
 			array('text', 'custom_avatar_url', 40),
 	);

+ 1 - 14
Sources/ManageMembers.php

@@ -235,11 +235,6 @@ function ViewMemberlist()
 				'type' => 'date',
 				'range' => true
 			),
-			'gender' => array(
-				'db_fields' => array('gender'),
-				'type' => 'checkbox',
-				'values' => array('0', '1', '2'),
-			),
 			'activated' => array(
 				'db_fields' => array('CASE WHEN is_activated IN (1, 11) THEN 1 ELSE 0 END'),
 				'type' => 'checkbox',
@@ -257,17 +252,9 @@ function ViewMemberlist()
 				'db_fields' => array('website_title', 'website_url'),
 				'type' => 'string'
 			),
-			'location' => array(
-				'db_fields' => array('location'),
-				'type' => 'string'
-			),
 			'ip' => array(
 				'db_fields' => array('member_ip'),
 				'type' => 'string'
-			),
-			'messenger' => array(
-				'db_fields' => array('icq', 'aim', 'yim', 'skype'),
-				'type' => 'string'
 			)
 		);
 		$range_trans = array(
@@ -1257,7 +1244,7 @@ function AdminApprove()
 	}
 
 	// Although updateStats *may* catch this, best to do it manually just in case (Doesn't always sort out unapprovedMembers).
-	if (in_array($current_filter, array(3, 4)))
+	if (in_array($current_filter, array(3, 4, 5)))
 		updateSettings(array('unapprovedMembers' => ($modSettings['unapprovedMembers'] > $member_count ? $modSettings['unapprovedMembers'] - $member_count : 0)));
 
 	// Update the member's stats. (but, we know the member didn't change their name.)

+ 11 - 3
Sources/ManageNews.php

@@ -311,6 +311,9 @@ function SelectMailingMembers()
 {
 	global $txt, $context, $modSettings, $smcFunc;
 
+	// Is there any confirm message?
+	$context['newsletter_sent'] = isset($_SESSION['newsletter_sent']) ? $_SESSION['newsletter_sent'] : '';
+
 	$context['page_title'] = $txt['admin_newsletters'];
 
 	$context['sub_template'] = 'email_members';
@@ -682,7 +685,7 @@ function ComposeMailing()
  * Called by ?action=admin;area=news;sa=mailingsend
  * Requires the send_mail permission.
  * Redirects to itself when more batches need to be sent.
- * Redirects to ?action=admin after everything has been sent.
+ * Redirects to ?action=admin;area=news;sa=mailingmembers after everything has been sent.
  *
  * @param bool $clean_only = false; if set, it will only clean the variables, put them in context, then return.
  * @uses the ManageNews template and email_members_send sub template.
@@ -937,7 +940,11 @@ function SendMailing($clean_only = false)
 
 		// If we've not got a query then we must be done!
 		if ($sendQuery == '()')
-			redirectexit('action=admin');
+		{
+			// Set a confirmation message.
+			$_SESSION['newsletter_sent'] = 'queue_done';
+			redirectexit('action=admin;area=news;sa=mailingmembers');
+		}
 
 		// Anything to exclude?
 		if (!empty($context['recipients']['exclude_groups']) && in_array(0, $context['recipients']['exclude_groups']))
@@ -1019,7 +1026,8 @@ function SendMailing($clean_only = false)
 	{
 		// Log this into the admin log.
 		logAction('newsletter', array(), 'admin');
-		redirectexit('action=admin');
+		$_SESSION['newsletter_sent'] = 'queue_done';
+		redirectexit('action=admin;area=news;sa=mailingmembers');
 	}
 
 	// Working out progress is a black art of sorts.

+ 2 - 0
Sources/ManagePermissions.php

@@ -1113,6 +1113,7 @@ function setPermissionLevel($level, $group, $profile = 'null')
 		'profile_upload_avatar',
 		'profile_remote_avatar',
 		'profile_remove_own',
+		'report_user',
 	));
 	$groupLevels['board']['standard'] = array_merge($groupLevels['board']['restrict'], array(
 		'poll_vote',
@@ -2205,6 +2206,7 @@ function loadIllegalGuestPermissions()
 		'profile_upload_avatar',
 		'remove',
 		'report_any',
+		'report_user',
 		'send_email_to_members',
 		'send_mail',
 		'split_any',

+ 4 - 4
Sources/ManageSettings.php

@@ -163,7 +163,7 @@ function ModifyBasicSettings($return_config = false)
 		'',
 			// Number formatting, timezones.
 			array('text', 'time_format'),
-			array('float', 'time_offset', 'subtext' => $txt['setting_time_offset_note'], 6, 'postinput' => $txt['hours']),
+			array('float', 'time_offset', 'subtext' => $txt['setting_time_offset_note'], 6, 'postinput' => $txt['hours'], 'step' => 0.25, 'min' => -23.5, 'max' => 23.5),
 			'default_timezone' => array('select', 'default_timezone', array()),
 		'',
 			// Who's online?
@@ -1127,7 +1127,7 @@ function ShowCustomProfiles()
 	$context['sub_template'] = 'show_custom_profile';
 
 	// What about standard fields they can tweak?
-	$standard_fields = array('icq', 'aim', 'yim', 'skype', 'location', 'gender', 'website', 'personal_text', 'posts', 'warning_status');
+	$standard_fields = array('website', 'personal_text', 'posts', 'warning_status');
 	// What fields can't you put on the registration page?
 	$context['fields_no_registration'] = array('posts', 'warning_status');
 
@@ -1196,7 +1196,7 @@ function ShowCustomProfiles()
 				'data' => array(
 					'function' => create_function('$rowData', '
 						$isChecked = $rowData[\'disabled\'] ? \'\' : \' checked\';
-						$onClickHandler = $rowData[\'can_show_register\'] ? sprintf(\'onclick="document.getElementById(\\\'reg_%1$s\\\').disabled = !this.checked;"\', $rowData[\'id\']) : \'\';
+						$onClickHandler = $rowData[\'can_show_register\'] ? sprintf(\' onclick="document.getElementById(\\\'reg_%1$s\\\').disabled = !this.checked;"\', $rowData[\'id\']) : \'\';
 						return sprintf(\'<input type="checkbox" name="active[]" id="active_%1$s" value="%1$s" class="input_check"%2$s%3$s>\', $rowData[\'id\'], $isChecked, $onClickHandler);
 					'),
 					'style' => 'width: 20%;',
@@ -1369,7 +1369,7 @@ function list_getProfileFields($start, $items_per_page, $sort, $standardFields)
 
 	if ($standardFields)
 	{
-		$standard_fields = array('icq', 'aim', 'yim', 'skype', 'location', 'gender', 'website', 'personal_text', 'posts', 'warning_status');
+		$standard_fields = array('website', 'personal_text', 'posts', 'warning_status');
 		$fields_no_registration = array('posts', 'warning_status');
 		$disabled_fields = isset($modSettings['disabled_profile_fields']) ? explode(',', $modSettings['disabled_profile_fields']) : array();
 		$registration_fields = isset($modSettings['registration_fields']) ? explode(',', $modSettings['registration_fields']) : array();

+ 1 - 0
Sources/ManageSmileys.php

@@ -137,6 +137,7 @@ function EditSmileySettings($return_config = false)
 			array('check', 'smiley_sets_enable'),
 			array('check', 'smiley_enable', 'subtext' => $txt['smileys_enable_note']),
 			array('text', 'smileys_url', 40),
+			array('warning', !is_dir($context['smileys_dir']) ? 'setting_smileys_dir_wrong' : ''),
 			array('text', 'smileys_dir', 'invalid' => !$context['smileys_dir_found'], 40),
 		'',
 			// Message icons.

+ 1 - 32
Sources/Memberlist.php

@@ -83,34 +83,6 @@ function Memberlist()
 				'up' => 'LENGTH(mem.website_url) > 0 DESC, IFNULL(mem.website_url, 1=1) ASC, mem.website_url ASC'
 			),
 		),
-		'icq' => array(
-			'label' => $txt['icq'],
-			'sort' => array(
-				'down' => 'LENGTH(mem.icq) > 0 ASC, mem.icq = 0 DESC, mem.icq DESC',
-				'up' => 'LENGTH(mem.icq) > 0 DESC, mem.icq = 0 ASC, mem.icq ASC'
-			),
-		),
-		'aim' => array(
-			'label' => $txt['aim'],
-			'sort' => array(
-				'down' => 'LENGTH(mem.aim) > 0 ASC, IFNULL(mem.aim, 1=1) DESC, mem.aim DESC',
-				'up' => 'LENGTH(mem.aim) > 0 DESC, IFNULL(mem.aim, 1=1) ASC, mem.aim ASC'
-			),
-		),
-		'yim' => array(
-			'label' => $txt['yim'],
-			'sort' => array(
-				'down' => 'LENGTH(mem.yim) > 0 ASC, IFNULL(mem.yim, 1=1) DESC, mem.yim DESC',
-				'up' => 'LENGTH(mem.yim) > 0 DESC, IFNULL(mem.yim, 1=1) ASC, mem.yim ASC'
-			),
-		),
-		'skype' => array(
-			'label' => $txt['skype'],
-			'sort' => array(
-				'down' => 'LENGTH(mem.skype) > 0 ASC, IFNULL(mem.skype, 1=1) DESC, mem.skype DESC',
-				'up' => 'LENGTH(mem.skype) > 0 DESC, IFNULL(mem.skype, 1=1) ASC, mem.skype ASC',
-			),
-		),
 		'id_group' => array(
 			'label' => $txt['position'],
 			'sort' => array(
@@ -468,9 +440,7 @@ function MLSearch()
 			$fields = allowedTo('moderate_forum') ? array('member_name', 'real_name') : array('real_name');
 		else
 			$fields = array();
-		// Search for messengers...
-		if (in_array('messenger', $_POST['fields']) && !$user_info['is_guest'])
-			$fields += array(3 => 'aim', 'icq', 'yim', 'skype');
+
 		// Search for websites.
 		if (in_array('website', $_POST['fields']))
 			$fields += array(7 => 'website_title', 'website_url');
@@ -545,7 +515,6 @@ function MLSearch()
 		$context['search_fields'] = array(
 			'name' => $txt['mlist_search_name'],
 			'email' => $txt['mlist_search_email'],
-			'messenger' => $txt['mlist_search_messenger'],
 			'website' => $txt['mlist_search_website'],
 			'group' => $txt['mlist_search_group'],
 		);

+ 627 - 11
Sources/ModerationCenter.php

@@ -32,9 +32,10 @@ function ModerationMain($dont_call = false)
 	$context['can_moderate_boards'] = $user_info['mod_cache']['bq'] != '0=1';
 	$context['can_moderate_groups'] = $user_info['mod_cache']['gq'] != '0=1';
 	$context['can_moderate_approvals'] = $modSettings['postmod_active'] && !empty($user_info['mod_cache']['ap']);
+	$context['can_moderate_users'] = allowedTo('moderate_forum');	
 
 	// Everyone using this area must be allowed here!
-	if (!$context['can_moderate_boards'] && !$context['can_moderate_groups'] && !$context['can_moderate_approvals'])
+	if (!$context['can_moderate_boards'] && !$context['can_moderate_groups'] && !$context['can_moderate_approvals'] && !$context['can_moderate_users'])
 		isAllowedTo('access_mod_center');
 
 	// We're gonna want a menu of some kind.
@@ -138,16 +139,6 @@ function ModerationMain($dont_call = false)
 			'title' => $txt['mc_groups'],
 			'enabled' => $context['can_moderate_groups'],
 			'areas' => array(
-				'userwatch' => array(
-					'label' => $txt['mc_watched_users_title'],
-					'enabled' => $modSettings['warning_settings'][0] == 1 && $context['can_moderate_boards'],
-					'function' => 'ViewWatchedUsers',
-					'icon' => 'members_watched.png',
-					'subsections' => array(
-						'member' => array($txt['mc_watched_users_member']),
-						'post' => array($txt['mc_watched_users_post']),
-					),
-				),
 				'groups' => array(
 					'label' => $txt['mc_group_requests'],
 					'file' => 'Groups.php',
@@ -163,6 +154,32 @@ function ModerationMain($dont_call = false)
 				),
 			),
 		),
+		'members' => array(
+			'title' => $txt['mc_members'],
+			'enabled' => $context['can_moderate_users'] || ($modSettings['warning_settings'][0] == 1 && $context['can_moderate_boards']),
+			'areas' => array(
+				'userwatch' => array(
+					'label' => $txt['mc_watched_users_title'],
+					'enabled' => $modSettings['warning_settings'][0] == 1 && $context['can_moderate_boards'],
+					'function' => 'ViewWatchedUsers',
+					'icon' => 'members_watched.png',
+					'subsections' => array(
+						'member' => array($txt['mc_watched_users_member']),
+						'post' => array($txt['mc_watched_users_post']),
+					),
+				),
+				'memberreports' => array(
+					'label' => $txt['mc_reported_members_title'],
+					'enabled' => $context['can_moderate_users'],
+					'function' => 'ReportedMembers',
+					'icon' => 'members_watched.png',
+					'subsections' => array(
+						'open' => array($txt['mc_reportedp_active']),
+						'closed' => array($txt['mc_reportedp_closed']),	
+					),
+				),
+			),
+		)
 	);
 
 	// Make sure the administrator has a valid session...
@@ -248,6 +265,14 @@ function ModerationHome()
 		$valid_blocks['r'] = 'ReportedPosts';
 		$valid_blocks['w'] = 'WatchedUsers';
 	}
+	if ($context['can_moderate_users'])
+	{
+		// This falls under the category of moderating users as well...
+		if (!$context['can_moderate_boards'])
+			$valid_blocks['w'] = 'WatchedUsers';
+
+		$valid_blocks['rm'] = 'ReportedMembers';
+	}
 
 	call_integration_hook('integrate_mod_centre_blocks', array(&$valid_blocks));
 
@@ -473,11 +498,13 @@ function ModBlockReportedPosts()
 			FROM {db_prefix}log_reported AS lr
 				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lr.id_member)
 			WHERE ' . ($user_info['mod_cache']['bq'] == '1=1' || $user_info['mod_cache']['bq'] == '0=1' ? $user_info['mod_cache']['bq'] : 'lr.' . $user_info['mod_cache']['bq']) . '
+				AND lr.id_board != {int:not_a_reported_post}
 				AND lr.closed = {int:not_closed}
 				AND lr.ignore_all = {int:not_ignored}
 			ORDER BY lr.time_updated DESC
 			LIMIT 10',
 			array(
+				'not_a_reported_post' => 0,
 				'not_closed' => 0,
 				'not_ignored' => 0,
 			)
@@ -564,6 +591,292 @@ function ModBlockGroupRequests()
 	return 'group_requests_block';
 }
 
+/**
+ * Show a list of the most recent reported posts.
+ */
+function ModBlockReportedMembers()
+{
+	global $context, $user_info, $scripturl, $smcFunc;
+
+	// Got the info already?
+	$cachekey = md5(serialize((int) allowedTo('moderate_forum')));
+	$context['reported_users'] = array();
+	if (!allowedTo('moderate_forum'))
+		return 'reported_users_block';
+
+	if (($reported_posts = cache_get_data('reported_users_' . $cachekey, 90)) === null)
+	{
+		// By George, that means we in a position to get the reports, jolly good.
+		$request = $smcFunc['db_query']('', '
+			SELECT lr.id_report, lr.id_member,
+				lr.num_reports, IFNULL(mem.real_name, lr.membername) AS user_name,
+				IFNULL(mem.id_member, 0) AS id_user
+			FROM {db_prefix}log_reported AS lr
+				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lr.id_member)
+			WHERE lr.id_board = {int:not_a_reported_post}
+				AND lr.closed = {int:not_closed}
+				AND lr.ignore_all = {int:not_ignored}
+			ORDER BY lr.time_updated DESC
+			LIMIT 10',
+			array(
+				'not_a_reported_post' => 0,
+				'not_closed' => 0,
+				'not_ignored' => 0,
+			)
+		);
+		$reported_users = array();
+		while ($row = $smcFunc['db_fetch_assoc']($request))
+			$reported_users[] = $row;
+		$smcFunc['db_free_result']($request);
+
+		// Cache it.
+		cache_put_data('reported_users_' . $cachekey, $reported_posts, 90);
+	}
+
+	$context['reported_users'] = array();
+	foreach ($reported_users as $i => $row)
+	{
+		$context['reported_users'][] = array(
+			'id' => $row['id_report'],
+			'alternate' => $i % 2,
+			'report_href' => $scripturl . '?action=moderate;area=memberreports;report=' . $row['id_report'],
+			'user' => array(
+				'id' => $row['id_user'],
+				'name' => $row['user_name'],
+				'link' => $row['id_user'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_user'] . '">' . $row['user_name'] . '</a>' : $row['user_name'],
+				'href' => $scripturl . '?action=profile;u=' . $row['id_author'],
+			),
+			'comments' => array(),
+			'num_reports' => $row['num_reports'],
+		);
+	}
+
+	return 'reported_users_block';
+}
+
+/**
+ * Browse all the reported users...
+ */
+function ReportedMembers()
+{
+	global $txt, $context, $scripturl, $user_info, $smcFunc;
+
+	loadTemplate('ModerationCenter');
+
+	// Set an empty var for the server response.
+	$context['report_member_action'] = '';
+
+	// Put the open and closed options into tabs, because we can...
+	$context[$context['moderation_menu_name']]['tab_data'] = array(
+		'title' => $txt['mc_reported_members'],
+		'help' => '',
+		'description' => $txt['mc_reported_members_desc'],
+	);
+
+	isAllowedTo('moderate_forum');
+
+	// Are they wanting to view a particular report?
+	if (!empty($_REQUEST['report']))
+		return MemberReport();
+
+	// Set up the comforting bits...
+	$context['page_title'] = $txt['mc_reported_members'];
+	$context['sub_template'] = 'reported_members';
+
+	// Are we viewing open or closed reports?
+	$context['view_closed'] = isset($_GET['sa']) && $_GET['sa'] == 'closed' ? 1 : 0;
+
+	// Are we doing any work?
+	if ((isset($_GET['ignore']) || isset($_GET['close'])) && isset($_GET['rid']))
+	{
+		checkSession('get');
+		$_GET['rid'] = (int) $_GET['rid'];
+
+		// Update the report...
+		$smcFunc['db_query']('', '
+			UPDATE {db_prefix}log_reported
+			SET ' . (isset($_GET['ignore']) ? 'ignore_all = {int:ignore_all}' : 'closed = {int:closed}') . '
+			WHERE id_report = {int:id_report}',
+			array(
+				'ignore_all' => isset($_GET['ignore']) ? (int) $_GET['ignore'] : 0,
+				'closed' => isset($_GET['close']) ? (int) $_GET['close'] : 0,
+				'id_report' => $_GET['rid'],
+			)
+		);
+
+		// Get the board, topic and message for this report
+		$request = $smcFunc['db_query']('', '
+			SELECT id_member, membername
+			FROM {db_prefix}log_reported
+			WHERE id_report = {int:id_report}',
+			array(
+				'id_report' => $_GET['rid'],
+			)
+		);
+
+		// Set up the data for the log...
+		$extra = array('report' => $_GET['rid']);
+		list($extra['member'], $extra['membername']) = $smcFunc['db_fetch_row']($request);
+		$smcFunc['db_free_result']($request);
+
+		// Stick this in string format for consistency
+		$extra['member'] = (string)$extra['member'];
+
+		// Tell the user about it.
+		$context['report_member_action'] = isset($_GET['ignore']) ? (!empty($_GET['ignore']) ? 'ignore' : 'unignore') : (!empty($_GET['close']) ? 'close' : 'open');
+
+		// Log this action
+		logAction($context['report_member_action'] . '_user_report', $extra);
+
+		// Time to update.
+		updateSettings(array('last_mod_report_action' => time()));
+		recountOpenMemberReports();
+	}
+	elseif (isset($_POST['close']) && isset($_POST['close_selected']))
+	{
+		checkSession();
+
+		// All the ones to update...
+		$toClose = array();
+		foreach ($_POST['close'] as $rid)
+			$toClose[] = (int) $rid;
+
+		if (!empty($toClose))
+		{
+			// Get the data for each of these reports
+			$request = $smcFunc['db_query']('', '
+				SELECT id_report, id_member, membername
+				FROM {db_prefix}log_reported
+				WHERE id_report IN ({array_int:report_list})',
+				array(
+					'report_list' => $toClose,
+				)
+			);
+
+			while ($reports = $smcFunc['db_fetch_assoc']($request))
+			{
+				$report_data = array(
+					'report' => $reports['id_report'],
+					'membername' => $reports['membername'],
+					'member' => (string)$reports['id_member'],
+				);
+
+				// Log that this report was closed
+				logAction('close_user_report', $report_data);
+			}
+
+			$smcFunc['db_free_result']($request);
+
+			$smcFunc['db_query']('', '
+				UPDATE {db_prefix}log_reported
+				SET closed = {int:is_closed}
+				WHERE id_report IN ({array_int:report_list})',
+				array(
+					'report_list' => $toClose,
+					'is_closed' => 1,
+				)
+			);
+
+			// Time to update.
+			updateSettings(array('last_mod_report_action' => time()));
+			recountOpenMemberReports();
+		}
+
+		// Go on and tell the result.
+		$context['report_member_action'] = 'close_all';
+	}
+
+	// How many entries are we viewing?
+	$request = $smcFunc['db_query']('', '
+		SELECT COUNT(*)
+		FROM {db_prefix}log_reported AS lr
+		WHERE lr.closed = {int:view_closed}
+			AND lr.id_board = {int:not_a_reported_post}',
+		array(
+			'view_closed' => $context['view_closed'],
+			'not_a_reported_post' => 0,
+		)
+	);
+	list ($context['total_reports']) = $smcFunc['db_fetch_row']($request);
+	$smcFunc['db_free_result']($request);
+
+	// So, that means we can page index, yes?
+	$context['page_index'] = constructPageIndex($scripturl . '?action=moderate;area=memberreports' . ($context['view_closed'] ? ';sa=closed' : ''), $_GET['start'], $context['total_reports'], 10);
+	$context['start'] = $_GET['start'];
+
+	// By George, that means we in a position to get the reports, golly good.
+	$request = $smcFunc['db_query']('', '
+		SELECT lr.id_report, lr.id_member, lr.time_started, lr.time_updated, lr.num_reports, lr.closed, lr.ignore_all,
+			IFNULL(mem.real_name, lr.membername) AS user_name, IFNULL(mem.id_member, 0) AS id_user
+		FROM {db_prefix}log_reported AS lr
+			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lr.id_member)
+		WHERE lr.closed = {int:view_closed}
+			AND lr.id_board = {int:not_a_reported_post}
+		ORDER BY lr.time_updated DESC
+		LIMIT ' . $context['start'] . ', 10',
+		array(
+			'view_closed' => $context['view_closed'],
+			'not_a_reported_post' => 0,
+		)
+	);
+	$context['reports'] = array();
+	$report_ids = array();
+	for ($i = 0; $row = $smcFunc['db_fetch_assoc']($request); $i++)
+	{
+		$report_ids[] = $row['id_report'];
+		$context['reports'][$row['id_report']] = array(
+			'id' => $row['id_report'],
+			'alternate' => $i % 2,
+			'report_href' => $scripturl . '?action=moderate;area=memberreports;report=' . $row['id_report'],
+			'user' => array(
+				'id' => $row['id_user'],
+				'name' => $row['user_name'],
+				'link' => $row['id_user'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_user'] . '">' . $row['user_name'] . '</a>' : $row['user_name'],
+				'href' => $scripturl . '?action=profile;u=' . $row['id_user'],
+			),
+			'comments' => array(),
+			'time_started' => timeformat($row['time_started']),
+			'last_updated' => timeformat($row['time_updated']),
+			'num_reports' => $row['num_reports'],
+			'closed' => $row['closed'],
+			'ignore' => $row['ignore_all']
+		);
+	}
+	$smcFunc['db_free_result']($request);
+
+	// Now get all the people who reported it.
+	if (!empty($report_ids))
+	{
+		$request = $smcFunc['db_query']('', '
+			SELECT lrc.id_comment, lrc.id_report, lrc.time_sent, lrc.comment,
+				IFNULL(mem.id_member, 0) AS id_member, IFNULL(mem.real_name, lrc.membername) AS reporter
+			FROM {db_prefix}log_reported_comments AS lrc
+				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lrc.id_member)
+			WHERE lrc.id_report IN ({array_int:report_list})',
+			array(
+				'report_list' => $report_ids,
+			)
+		);
+		while ($row = $smcFunc['db_fetch_assoc']($request))
+		{
+			$context['reports'][$row['id_report']]['comments'][] = array(
+				'id' => $row['id_comment'],
+				'message' => $row['comment'],
+				'time' => timeformat($row['time_sent']),
+				'member' => array(
+					'id' => $row['id_member'],
+					'name' => empty($row['reporter']) ? $txt['guest'] : $row['reporter'],
+					'link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['reporter'] . '</a>' : (empty($row['reporter']) ? $txt['guest'] : $row['reporter']),
+					'href' => $row['id_member'] ? $scripturl . '?action=profile;u=' . $row['id_member'] : '',
+				),
+			);
+		}
+		$smcFunc['db_free_result']($request);
+	}
+
+	$context['report_manage_bans'] = allowedTo('manage_bans');
+}
+
 /**
  * Act as an entrace for all group related activity.
  * @todo As for most things in this file, this needs to be moved somewhere appropriate?
@@ -593,6 +906,309 @@ function ModerateGroups()
 	$subactions[$context['sub_action']]();
 }
 
+/**
+ * How many open reports do we have?
+ */
+function recountOpenMemberReports()
+{
+	global $user_info, $context, $smcFunc;
+
+	$request = $smcFunc['db_query']('', '
+		SELECT COUNT(*)
+		FROM {db_prefix}log_reported
+		WHERE closed = {int:not_closed}
+			AND ignore_all = {int:not_ignored}
+			AND id_board = {int:not_a_reported_post}',
+		array(
+			'not_closed' => 0,
+			'not_ignored' => 0,
+			'not_a_reported_post' => 0,
+		)
+	);
+	list ($open_reports) = $smcFunc['db_fetch_row']($request);
+	$smcFunc['db_free_result']($request);
+
+	$_SESSION['rmc'] = array(
+		'id' => $user_info['id'],
+		'time' => time(),
+		'reports' => $open_reports,
+	);
+
+	$context['open_member_reports'] = $open_reports;
+}
+
+function MemberReport()
+{
+	global $user_info, $context, $sourcedir, $scripturl, $txt, $smcFunc;
+
+	// Have to at least give us something
+	if (empty($_REQUEST['report']))
+		fatal_lang_error('mc_no_modreport_specified');
+
+	// Integers only please
+	$_REQUEST['report'] = (int) $_REQUEST['report'];
+
+	// Get the report details, need this so we can limit access to a particular board
+	$request = $smcFunc['db_query']('', '
+		SELECT lr.id_report, lr.id_member,
+			lr.time_started, lr.time_updated, lr.num_reports, lr.closed, lr.ignore_all,
+			IFNULL(mem.real_name, lr.membername) AS user_name, IFNULL(mem.id_member, 0) AS id_user
+		FROM {db_prefix}log_reported AS lr
+			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lr.id_member)
+		WHERE lr.id_report = {int:id_report}
+			AND lr.id_board = {int:not_a_reported_post}
+		LIMIT 1',
+		array(
+			'id_report' => $_REQUEST['report'],
+			'not_a_reported_post' => 0,
+		)
+	);
+
+	// So did we find anything?
+	if (!$smcFunc['db_num_rows']($request))
+		fatal_lang_error('mc_no_modreport_found');
+
+	// Woohoo we found a report and they can see it!  Bad news is we have more work to do
+	$row = $smcFunc['db_fetch_assoc']($request);
+	$smcFunc['db_free_result']($request);
+
+	// If they are adding a comment then... add a comment.
+	if (isset($_POST['add_comment']) && !empty($_POST['mod_comment']))
+	{
+		checkSession();
+
+		$newComment = trim($smcFunc['htmlspecialchars']($_POST['mod_comment']));
+
+		// In it goes.
+		if (!empty($newComment))
+		{
+			$smcFunc['db_insert']('',
+				'{db_prefix}log_comments',
+				array(
+					'id_member' => 'int', 'member_name' => 'string', 'comment_type' => 'string', 'recipient_name' => 'string',
+					'id_notice' => 'int', 'body' => 'string', 'log_time' => 'int',
+				),
+				array(
+					$user_info['id'], $user_info['name'], 'reportc', '',
+					$_REQUEST['report'], $newComment, time(),
+				),
+				array('id_comment')
+			);
+			$last_comment = $smcFunc['db_insert_id']('{db_prefix}log_comments', 'id_comment');
+
+			// And get ready to notify people.
+			$smcFunc['db_insert']('insert',
+				'{db_prefix}background_tasks',
+				array('task_file' => 'string', 'task_class' => 'string', 'task_data' => 'string', 'claimed_time' => 'int'),
+				array('$sourcedir/tasks/MemberReportReply-Notify.php', 'MemberReportReply_Notify_Background', serialize(array(
+					'report_id' => $_REQUEST['report'],
+					'comment_id' => $last_comment,
+					'sender_name' => $user_info['name'],
+					'time' => time(),
+				)), 0),
+				array('id_task')
+			);
+
+			// Redirect to prevent double submittion.
+			redirectexit($scripturl . '?action=moderate;area=memberreports;report=' . $_REQUEST['report']);
+		}
+	}
+
+	$context['report'] = array(
+		'id' => $row['id_report'],
+		'report_href' => $scripturl . '?action=moderate;area=memberreports;report=' . $row['id_report'],
+		'user' => array(
+			'id' => $row['id_user'],
+			'name' => $row['user_name'],
+			'link' => $row['id_user'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_user'] . '">' . $row['user_name'] . '</a>' : $row['user_name'],
+			'href' => $scripturl . '?action=profile;u=' . $row['id_user'],
+		),
+		'comments' => array(),
+		'mod_comments' => array(),
+		'time_started' => timeformat($row['time_started']),
+		'last_updated' => timeformat($row['time_updated']),
+		'num_reports' => $row['num_reports'],
+		'closed' => $row['closed'],
+		'ignore' => $row['ignore_all']
+	);
+
+	// So what bad things do the reporters have to say about it?
+	$request = $smcFunc['db_query']('', '
+		SELECT lrc.id_comment, lrc.id_report, lrc.time_sent, lrc.comment, lrc.member_ip,
+			IFNULL(mem.id_member, 0) AS id_member, IFNULL(mem.real_name, lrc.membername) AS reporter
+		FROM {db_prefix}log_reported_comments AS lrc
+			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lrc.id_member)
+		WHERE lrc.id_report = {int:id_report}',
+		array(
+			'id_report' => $context['report']['id'],
+		)
+	);
+	while ($row = $smcFunc['db_fetch_assoc']($request))
+	{
+		$context['report']['comments'][] = array(
+			'id' => $row['id_comment'],
+			'message' => strtr($row['comment'], array("\n" => '<br>')),
+			'time' => timeformat($row['time_sent']),
+			'member' => array(
+				'id' => $row['id_member'],
+				'name' => empty($row['reporter']) ? $txt['guest'] : $row['reporter'],
+				'link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['reporter'] . '</a>' : (empty($row['reporter']) ? $txt['guest'] : $row['reporter']),
+				'href' => $row['id_member'] ? $scripturl . '?action=profile;u=' . $row['id_member'] : '',
+				'ip' => !empty($row['member_ip']) && allowedTo('moderate_forum') ? '<a href="' . $scripturl . '?action=trackip;searchip=' . $row['member_ip'] . '">' . $row['member_ip'] . '</a>' : '',
+			),
+		);
+	}
+	$smcFunc['db_free_result']($request);
+
+	// Hang about old chap, any comments from moderators on this one?
+	$request = $smcFunc['db_query']('', '
+		SELECT lc.id_comment, lc.id_notice, lc.log_time, lc.body,
+			IFNULL(mem.id_member, 0) AS id_member, IFNULL(mem.real_name, lc.member_name) AS moderator
+		FROM {db_prefix}log_comments AS lc
+			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lc.id_member)
+		WHERE lc.id_notice = {int:id_report}
+			AND lc.comment_type = {literal:reportc}',
+		array(
+			'id_report' => $context['report']['id'],
+		)
+	);
+	while ($row = $smcFunc['db_fetch_assoc']($request))
+	{
+		$context['report']['mod_comments'][] = array(
+			'id' => $row['id_comment'],
+			'message' => parse_bbc($row['body']),
+			'time' => timeformat($row['log_time']),
+			'member' => array(
+				'id' => $row['id_member'],
+				'name' => $row['moderator'],
+				'link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['moderator'] . '</a>' : $row['moderator'],
+				'href' => $scripturl . '?action=profile;u=' . $row['id_member'],
+			),
+		);
+	}
+	$smcFunc['db_free_result']($request);
+
+	// What have the other moderators done to this message?
+	require_once($sourcedir . '/Modlog.php');
+	require_once($sourcedir . '/Subs-List.php');
+	loadLanguage('Modlog');
+
+	// Find their ID in the serialized action string...
+	$user_id_length = strlen((string)$context['report']['user']['id']);
+	$member = 's:6:"member";s:' . $user_id_length . ':"' . $context['report']['user']['id'] . '";}';
+
+	// This is all the information from the moderation log.
+	// Note that we use "raw" here to prevent SMF from escaping things we don't want escaped
+	$listOptions = array(
+		'id' => 'memreport_actions_list',
+		'title' => $txt['mc_modreport_modactions'],
+		'items_per_page' => 15,
+		'no_items_label' => $txt['modlog_no_entries_found'],
+		'base_href' => $scripturl . '?action=moderate;area=memberreports;report=' . $context['report']['id'],
+		'default_sort_col' => 'time',
+		'get_items' => array(
+			'function' => 'list_getModLogEntries',
+			'params' => array(
+				'lm.extra LIKE {raw:member}
+					AND lm.action LIKE {raw:report}',
+				array('member' => '\'%' . $member . '\'', 'report' => '\'%_user_report\''),
+				1,
+				true,
+			),
+		),
+		'get_count' => array(
+			'function' => 'list_getModLogEntryCount',
+			'params' => array(
+				'lm.extra LIKE {string:member}
+				AND lm.action LIKE {string:report}',
+				array('member' => '%' . $member . '%', 'report' => '%_user_report'),
+				1,
+				true,
+			),
+		),
+		// This assumes we are viewing by user.
+		'columns' => array(
+			'action' => array(
+				'header' => array(
+					'value' => $txt['modlog_action'],
+				),
+				'data' => array(
+					'db' => 'action_text',
+					'class' => 'smalltext',
+				),
+				'sort' => array(
+					'default' => 'lm.action',
+					'reverse' => 'lm.action DESC',
+				),
+			),
+			'time' => array(
+				'header' => array(
+					'value' => $txt['modlog_date'],
+				),
+				'data' => array(
+					'db' => 'time',
+					'class' => 'smalltext',
+				),
+				'sort' => array(
+					'default' => 'lm.log_time',
+					'reverse' => 'lm.log_time DESC',
+				),
+			),
+			'moderator' => array(
+				'header' => array(
+					'value' => $txt['modlog_member'],
+				),
+				'data' => array(
+					'db' => 'moderator_link',
+					'class' => 'smalltext',
+				),
+				'sort' => array(
+					'default' => 'mem.real_name',
+					'reverse' => 'mem.real_name DESC',
+				),
+			),
+			'position' => array(
+				'header' => array(
+					'value' => $txt['modlog_position'],
+				),
+				'data' => array(
+					'db' => 'position',
+					'class' => 'smalltext',
+				),
+				'sort' => array(
+					'default' => 'mg.group_name',
+					'reverse' => 'mg.group_name DESC',
+				),
+			),
+			'ip' => array(
+				'header' => array(
+					'value' => $txt['modlog_ip'],
+				),
+				'data' => array(
+					'db' => 'ip',
+					'class' => 'smalltext',
+				),
+				'sort' => array(
+					'default' => 'lm.ip',
+					'reverse' => 'lm.ip DESC',
+				),
+			),
+		),
+	);
+
+	// Create the watched user list.
+	createList($listOptions);
+
+	// Make sure to get the correct tab selected.
+	if ($context['report']['closed'])
+		$context[$context['moderation_menu_name']]['current_subsection'] = 'closed';
+
+	// Finally we are done :P
+	loadTemplate('ModerationCenter');
+	$context['page_title'] = sprintf($txt['mc_viewmemberreport'], $context['report']['user']['name']);
+	$context['sub_template'] = 'viewmemberreport';
+}
+
 /**
  * Show a notice sent to a user.
  */

+ 13 - 5
Sources/Modlog.php

@@ -311,12 +311,13 @@ function ViewModlog()
  * @param $query_string
  * @param $query_params
  * @param $log_type
+ * @param $ignore_boards
  */
-function list_getModLogEntryCount($query_string = '', $query_params = array(), $log_type = 1)
+function list_getModLogEntryCount($query_string = '', $query_params = array(), $log_type = 1, $ignore_boards = false)
 {
 	global $smcFunc, $user_info;
 
-	$modlog_query = allowedTo('admin_forum') || $user_info['mod_cache']['bq'] == '1=1' ? '1=1' : ($user_info['mod_cache']['bq'] == '0=1' ? 'lm.id_board = 0 AND lm.id_topic = 0' : (strtr($user_info['mod_cache']['bq'], array('id_board' => 'b.id_board')) . ' AND ' . strtr($user_info['mod_cache']['bq'], array('id_board' => 't.id_board'))));
+	$modlog_query = allowedTo('admin_forum') || $user_info['mod_cache']['bq'] == '1=1' ? '1=1' : (($user_info['mod_cache']['bq'] == '0=1' || $ignore_boards) ? 'lm.id_board = 0 AND lm.id_topic = 0' : (strtr($user_info['mod_cache']['bq'], array('id_board' => 'b.id_board')) . ' AND ' . strtr($user_info['mod_cache']['bq'], array('id_board' => 't.id_board'))));
 
 	$result = $smcFunc['db_query']('', '
 		SELECT COUNT(*)
@@ -351,12 +352,13 @@ function list_getModLogEntryCount($query_string = '', $query_params = array(), $
  * @param $query_string
  * @param $query_params
  * @param $log_type
+ * @param $ignore_boards 
  */
-function list_getModLogEntries($start, $items_per_page, $sort, $query_string = '', $query_params = array(), $log_type = 1)
+function list_getModLogEntries($start, $items_per_page, $sort, $query_string = '', $query_params = array(), $log_type = 1, $ignore_boards = false)
 {
 	global $scripturl, $txt, $smcFunc, $user_info;
 
-	$modlog_query = allowedTo('admin_forum') || $user_info['mod_cache']['bq'] == '1=1' ? '1=1' : ($user_info['mod_cache']['bq'] == '0=1' ? 'lm.id_board = 0 AND lm.id_topic = 0' : (strtr($user_info['mod_cache']['bq'], array('id_board' => 'b.id_board')) . ' AND ' . strtr($user_info['mod_cache']['bq'], array('id_board' => 't.id_board'))));
+	$modlog_query = allowedTo('admin_forum') || $user_info['mod_cache']['bq'] == '1=1' ? '1=1' : (($user_info['mod_cache']['bq'] == '0=1' || $ignore_boards) ? 'lm.id_board = 0 AND lm.id_topic = 0' : (strtr($user_info['mod_cache']['bq'], array('id_board' => 'b.id_board')) . ' AND ' . strtr($user_info['mod_cache']['bq'], array('id_board' => 't.id_board'))));
 
 	// Can they see the IP address?
 	$seeIP = allowedTo('moderate_forum');
@@ -617,7 +619,13 @@ function list_getModLogEntries($start, $items_per_page, $sort, $query_string = '
 				$entries[$k]['extra'][$type] = sprintf($txt['modlog_id'], $entry['extra'][$type]);
 
 		if (isset($entry['extra']['report']))
-			$entries[$k]['extra']['report'] = '<a href="' . $scripturl . '?action=moderate;area=reports;report=' . $entry['extra']['report'] . '">' . $txt['modlog_report'] . '</a>';
+		{
+			// Member profile reports go in a different area
+			if (stristr($entry['action'], 'user_report'))
+				$entries[$k]['extra']['report'] = '<a href="' . $scripturl . '?action=moderate;area=memberreports;report=' . $entry['extra']['report'] . '">' . $txt['modlog_report'] . '</a>';
+			else
+				$entries[$k]['extra']['report'] = '<a href="' . $scripturl . '?action=moderate;area=reports;report=' . $entry['extra']['report'] . '">' . $txt['modlog_report'] . '</a>';
+		}
 
 		if (empty($entries[$k]['action_text']))
 			$entries[$k]['action_text'] = isset($txt['modlog_ac_' . $entry['action']]) ? $txt['modlog_ac_' . $entry['action']] : $entry['action'];

+ 0 - 11
Sources/News.php

@@ -924,20 +924,9 @@ function getXmlProfile($xml_format)
 			$data['signature'] = cdata_parse($profile['signature']);
 		if ($profile['blurb'] != '')
 			$data['blurb'] = cdata_parse($profile['blurb']);
-		if ($profile['location'] != '')
-			$data['location'] = cdata_parse($profile['location']);
 		if ($profile['title'] != '')
 			$data['title'] = cdata_parse($profile['title']);
 
-		if (!empty($profile['icq']['name']) && !$user_info['is_guest'])
-			$data['icq'] = $profile['icq']['name'];
-		if ($profile['aim']['name'] != '' && !$user_info['is_guest'])
-			$data['aim'] = $profile['aim']['name'];
-		if ($profile['yim']['name'] != '' && !$user_info['is_guest'])
-			$data['yim'] = $profile['yim']['name'];
-		if (!empty($profile['skype']['name']) && !$user_info['is_guest'])
-			$data['skype'] = $profile['skype']['name'];
-
 		if ($profile['website']['title'] != '')
 			$data['website'] = array(
 				'title' => cdata_parse($profile['website']['title']),

+ 6 - 0
Sources/PackageGet.php

@@ -170,6 +170,12 @@ function PackageServers()
 			$ftp->close();
 		}
 	}
+
+	addInlineJavascript('
+	$(\'.new_package_content\').hide();
+	$(\'.download_new_package\').on(\'click\', function() {
+		$(\'.new_package_content\').css(\'display\') == \'none\' ? $(\'.new_package_content\').show(\'slow\') : $(\'.new_package_content\').hide(\'slow\'); 
+	});', true);
 }
 
 /**

+ 11 - 18
Sources/Post.php

@@ -309,6 +309,7 @@ function Post($post_errors = array())
 		$context['event']['last_day'] = (int) strftime('%d', mktime(0, 0, 0, $context['event']['month'] == 12 ? 1 : $context['event']['month'] + 1, 0, $context['event']['month'] == 12 ? $context['event']['year'] + 1 : $context['event']['year']));
 
 		$context['event']['board'] = !empty($board) ? $board : $modSettings['cal_defaultboard'];
+		$context['event']['topic'] = !empty($topic) ? $topic : 0;
 	}
 
 	// See if any new replies have come along.
@@ -1902,26 +1903,18 @@ function Post2()
 		// ... or just update it?
 		else
 		{
-			$span = !empty($modSettings['cal_allowspan']) && !empty($_REQUEST['span']) ? min((int) $modSettings['cal_maxspan'], (int) $_REQUEST['span'] - 1) : 0;
-			$start_time = mktime(0, 0, 0, (int) $_REQUEST['month'], (int) $_REQUEST['day'], (int) $_REQUEST['year']);
-
-			$smcFunc['db_query']('', '
-				UPDATE {db_prefix}calendar
-				SET end_date = {date:end_date},
-					start_date = {date:start_date},
-					title = {string:title}
-				WHERE id_event = {int:id_event}',
-				array(
-					'end_date' => strftime('%Y-%m-%d', $start_time + $span * 86400),
-					'start_date' => strftime('%Y-%m-%d', $start_time),
-					'id_event' => $_REQUEST['eventid'],
-					'title' => $smcFunc['htmlspecialchars']($_REQUEST['evtitle'], ENT_QUOTES),
-				)
+			// Set up our options
+			$eventOptions = array(
+				'board' => $board,
+				'topic' => $topic,
+				'title' => $_POST['evtitle'],
+				'member' => $user_info['id'],
+				'start_date' => sprintf('%04d-%02d-%02d', $_POST['year'], $_POST['month'], $_POST['day']),
+				'span' => isset($_POST['span']) && $_POST['span'] > 0 ? min((int) $modSettings['cal_maxspan'], (int) $_POST['span'] - 1) : 0,
 			);
+
+			modifyEvent($_REQUEST['eventid'], $eventOptions);
 		}
-		updateSettings(array(
-			'calendar_updated' => time(),
-		));
 	}
 
 	// Marking read should be done even for editing messages....

+ 1 - 1
Sources/Profile-Actions.php

@@ -48,7 +48,7 @@ function activateAccount($memID)
 		logAction('approve_member', array('member' => $memID), 'admin');
 
 		// If we are doing approval, update the stats for the member just in case.
-		if (in_array($user_profile[$memID]['is_activated'], array(3, 4, 13, 14)))
+		if (in_array($user_profile[$memID]['is_activated'], array(3, 4, 5, 13, 14, 15)))
 			updateSettings(array('unapprovedMembers' => ($modSettings['unapprovedMembers'] > 1 ? $modSettings['unapprovedMembers'] - 1 : 0)));
 
 		// Make sure we update the stats too.

+ 4 - 63
Sources/Profile-Modify.php

@@ -73,21 +73,6 @@ function loadProfileFields($force_reload = false)
 	*/
 
 	$profile_fields = array(
-		'aim' => array(
-			'type' => 'text',
-			'label' => $txt['aim'],
-			'subtext' => $txt['your_aim'],
-			'size' => 24,
-			'value' => strtr(empty($cur_profile['aim']) ? '' : $cur_profile['aim'], '+', ' '),
-			'permission' => 'profile_extra',
-			'input_validate' => create_function('&$value', '
-				$value = strtr($value, \' \', \'+\');
-				if (strlen($value) > 32)
-					return \'aim_too_long\';
-
-				return true;
-			'),
-		),
 		'avatar_choice' => array(
 			'type' => 'callback',
 			'callback_func' => 'avatar_select',
@@ -152,7 +137,7 @@ function loadProfileFields($force_reload = false)
 			'),
 		),
 		'date_registered' => array(
-			'type' => 'text',
+			'type' => 'date',
 			'value' => empty($cur_profile['date_registered']) ? $txt['not_applicable'] : strftime('%Y-%m-%d', $cur_profile['date_registered'] + ($user_info['time_offset'] + $modSettings['time_offset']) * 3600),
 			'label' => $txt['date_registered'],
 			'log_change' => true,
@@ -211,13 +196,6 @@ function loadProfileFields($force_reload = false)
 				return $isValid;
 			'),
 		),
-		'gender' => array(
-			'type' => 'select',
-			'cast_type' => 'int',
-			'options' => 'return array(0 => \'\', 1 => $txt[\'male\'], 2 => $txt[\'female\']);',
-			'label' => $txt['gender'],
-			'permission' => 'profile_extra',
-		),
 		'hide_email' => array(
 			'type' => 'check',
 			'value' => empty($cur_profile['hide_email']) ? true : false,
@@ -229,21 +207,6 @@ function loadProfileFields($force_reload = false)
 				return true;
 			'),
 		),
-		'icq' => array(
-			'type' => 'text',
-			'label' => $txt['icq'],
-			'subtext' => $txt['your_icq'],
-			'size' => 24,
-			'permission' => 'profile_extra',
-			// Need to make sure ICQ doesn't equal 0.
-			'input_validate' => create_function('&$value', '
-				if (empty($value))
-					$value = \'\';
-				else
-					$value = (int) $value;
-				return true;
-			'),
-		),
 		// Selecting group membership is a complicated one so we treat it separate!
 		'id_group' => array(
 			'type' => 'callback',
@@ -338,13 +301,6 @@ function loadProfileFields($force_reload = false)
 				}
 			'),
 		),
-		'location' => array(
-			'type' => 'text',
-			'label' => $txt['location'],
-			'log_change' => true,
-			'size' => 50,
-			'permission' => 'profile_other',
-		),
 		// The username is not always editable - so adjust it as such.
 		'member_name' => array(
 			'type' => allowedTo('admin_forum') && isset($_GET['changeusername']) ? 'text' : 'label',
@@ -378,13 +334,6 @@ function loadProfileFields($force_reload = false)
 				return false;
 			'),
 		),
-		'skype' => array(
-			'type' => 'text',
-			'label' => $txt['skype'],
-			'subtext' => $txt['skype_username'],
-			'size' => 24,
-			'permission' => 'profile_extra',
-		),
 		'passwrd1' => array(
 			'type' => 'password',
 			'label' => ucwords($txt['choose_pass']),
@@ -679,14 +628,6 @@ function loadProfileFields($force_reload = false)
 			'),
 			'link_with' => 'website',
 		),
-		'yim' => array(
-			'type' => 'text',
-			'label' => $txt['yim'],
-			'subtext' => $txt['your_yim'],
-			'size' => 24,
-			'input_attr' => array('maxlength="32"'),
-			'permission' => 'profile_extra',
-		),
 	);
 
 	call_integration_hook('integrate_load_profile_fields', array(&$profile_fields));
@@ -1680,9 +1621,7 @@ function forumProfile($memID)
 	setupProfileContext(
 		array(
 			'avatar_choice', 'hr', 'personal_text', 'hr',
-			'bday1', 'location', 'gender', 'hr',
-			'icq', 'aim', 'yim', 'skype', 'hr',
-			'usertitle', 'signature', 'hr',
+			'bday1', 'usertitle', 'signature', 'hr',
 			'karma_good', 'hr',
 			'website_title', 'website_url',
 		)
@@ -1961,6 +1900,8 @@ function alert_configuration($memID)
 		'moderation' => array(
 			'msg_report' => array('alert' => 'yes', 'email' => 'yes', 'permission' => array('name' => 'moderate_board', 'is_board' => true)),
 			'msg_report_reply' => array('alert' => 'yes', 'email' => 'yes', 'permission' => array('name' => 'moderate_board', 'is_board' => true)),
+			'member_report' => array('alert' => 'yes', 'email' => 'yes', 'permission' => array('name' => 'moderate_forum', 'is_board' => false)),
+			'member_report_reply' => array('alert' => 'yes', 'email' => 'yes', 'permission' => array('name' => 'moderate_forum', 'is_board' => false)),
 		),
 		'members' => array(
 			'member_register' => array('alert' => 'yes', 'email' => 'yes', 'permission' => array('name' => 'moderate_forum', 'is_board' => false)),

+ 2 - 0
Sources/Profile-View.php

@@ -317,6 +317,8 @@ function fetch_alerts($memID, $all = false)
 			$alerts[$id_alert]['extra']['topic_msg'] = $topics[$alert['extra']['topic']];
 		if ($alert['content_type'] == 'msg')
 			$alerts[$id_alert]['extra']['msg_msg'] = $msgs[$alert['content_id']];
+		if ($alert['content_type'] == 'profile')
+			$alerts[$id_alert]['extra']['profile_msg'] = '<a href="' . $scripturl . '?action=profile;u=' . $alerts[$id_alert]['content_id'] . '">' . $alerts[$id_alert]['extra']['user_name'] . '</a>';
 
 		if (!empty($memberContext[$alert['sender_id']]))
 			$alerts[$id_alert]['sender'] = &$memberContext[$alert['sender_id']];

+ 9 - 0
Sources/Profile.php

@@ -326,6 +326,15 @@ function ModifyProfile($post_errors = array())
 						'any' => array('pm_send'),
 					),
 				),
+				'report' => array(
+					'label' => $txt['report_profile'],
+					'custom_url' => $scripturl . '?action=reporttm;' . $context['session_var'] . '=' . $context['session_id'],
+					'icon' => 'warning.png',
+					'permission' => array(
+						'own' => array(),
+						'any' => array('moderate_forum', 'report_user'),
+					),
+				),
 				'issuewarning' => array(
 					'label' => $txt['profile_issue_warning'],
 					'enabled' => $modSettings['warning_settings'][0] == 1,

+ 46 - 7
Sources/Recent.php

@@ -81,6 +81,8 @@ function RecentPosts()
 	$context['page_title'] = $txt['recent_posts'];
 	$context['sub_template'] = 'recent';
 
+	$context['is_redirect'] = false;
+
 	if (isset($_REQUEST['start']) && $_REQUEST['start'] > 95)
 		$_REQUEST['start'] = 95;
 
@@ -114,13 +116,19 @@ function RecentPosts()
 			);
 		}
 
+		$recycling = empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0;
+
 		$request = $smcFunc['db_query']('', '
 			SELECT b.id_board, b.num_posts
 			FROM {db_prefix}boards AS b
 			WHERE b.id_cat IN ({array_int:category_list})
-				AND {query_see_board}',
+				AND b.redirect = {string:empty}' . $recycle ? '
+				AND b.id_board != {int:recycle_board}' : '' . '
+				AND {query_wanna_see_board}',
 			array(
 				'category_list' => $_REQUEST['c'],
+				'empty' => '',
+				'recycle_board' => $modSettings['recycle_board'],
 			)
 		);
 		$total_cat_posts = 0;
@@ -158,11 +166,13 @@ function RecentPosts()
 			SELECT b.id_board, b.num_posts
 			FROM {db_prefix}boards AS b
 			WHERE b.id_board IN ({array_int:board_list})
+				AND b.redirect = {string:empty}
 				AND {query_see_board}
 			LIMIT {int:limit}',
 			array(
 				'board_list' => $_REQUEST['boards'],
 				'limit' => count($_REQUEST['boards']),
+				'empty' => '',
 			)
 		);
 		$total_posts = 0;
@@ -193,7 +203,7 @@ function RecentPosts()
 	elseif (!empty($board))
 	{
 		$request = $smcFunc['db_query']('', '
-			SELECT num_posts
+			SELECT num_posts, redirect
 			FROM {db_prefix}boards
 			WHERE id_board = {int:current_board}
 			LIMIT 1',
@@ -201,9 +211,16 @@ function RecentPosts()
 				'current_board' => $board,
 			)
 		);
-		list ($total_posts) = $smcFunc['db_fetch_row']($request);
+		list ($total_posts, $redirect) = $smcFunc['db_fetch_row']($request);
 		$smcFunc['db_free_result']($request);
 
+		// If this is a redirection board, don't bother counting topics here...
+		if ($redirect != '')
+		{
+			$total_posts = 0;
+			$context['is_redirect'] = true;
+		}
+
 		$query_this_board = 'b.id_board = {int:board}';
 		$query_parameters['board'] = $board;
 
@@ -225,8 +242,24 @@ function RecentPosts()
 		$query_parameters['max_id_msg'] = max(0, $modSettings['maxMsgID'] - 100 - $_REQUEST['start'] * 6);
 		$query_parameters['recycle_board'] = $modSettings['recycle_board'];
 
-		// @todo This isn't accurate because we ignore the recycle bin.
-		$context['page_index'] = constructPageIndex($scripturl . '?action=recent', $_REQUEST['start'], min(100, $modSettings['totalMessages']), 10, false);
+		// "Borrow" some data from above...
+		$query_these_boards = str_replace('AND m.id_msg >= {int:max_id_msg}', '', $query_this_board);
+		$query_these_boards_params = $query_parameters;
+		unset($query_these_boards_params['max_id_msg']);
+		
+		$get_num_posts = $smcFunc['db_query']('', '
+			SELECT IFNULL(SUM(num_posts), 0)
+			FROM {db_prefix}boards
+			WHERE ' . $query_these_boards . '
+				AND b.redirect = {string:empty}',
+			array_merge($query_these_boards_params, array('empty' => ''))
+		);
+
+		$num_posts = min(100, $smcFunc['db_fetch_row']($get_num_posts));
+
+		$smcFunc['db_free_result']($get_num_posts);
+
+		$context['page_index'] = constructPageIndex($scripturl . '?action=recent', $_REQUEST['start'], $num_posts, 10, false);
 	}
 
 	$context['linktree'][] = array(
@@ -234,8 +267,12 @@ function RecentPosts()
 		'name' => $context['page_title']
 	);
 
+	// If you selected a redirection board, don't try getting posts for it...
+	if ($context['is_redirect'])
+		$messages = 0;
+
 	$key = 'recent-' . $user_info['id'] . '-' . md5(serialize(array_diff_key($query_parameters, array('max_id_msg' => 0)))) . '-' . (int) $_REQUEST['start'];
-	if (empty($modSettings['cache_enable']) || ($messages = cache_get_data($key, 120)) == null)
+	if (!$context['is_redirect'] && (empty($modSettings['cache_enable']) || ($messages = cache_get_data($key, 120)) == null))
 	{
 		$done = false;
 		while (!$done)
@@ -334,9 +371,10 @@ function RecentPosts()
 			),
 			'topic' => $row['id_topic'],
 			'href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'],
-			'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'] . '" rel="nofollow">' . $row['subject'] . '</a>',
+			'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'] . '" rel="nofollow" title="' . $row['subject'] . '">' . $row['shorten_subject'] . '</a>',
 			'start' => $row['num_replies'],
 			'subject' => $row['subject'],
+			'shorten_subject' => shorten_subject($row['subject'], 30),
 			'time' => timeformat($row['poster_time']),
 			'timestamp' => forum_time(true, $row['poster_time']),
 			'first_poster' => array(
@@ -978,6 +1016,7 @@ function UnreadTopics()
 				SELECT t.id_topic, t.id_board, t.id_last_msg, IFNULL(lmr.id_msg, 0) AS id_msg' . (!in_array($_REQUEST['sort'], array('t.id_last_msg', 't.id_topic')) ? ', ' . $_REQUEST['sort'] . ' AS sort_key' : '') . '
 				FROM {db_prefix}messages AS m
 					INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic)
+					LEFT JOIN {db_prefix}log_topics_unread AS lt ON (lt.id_topic = t.id_topic)
 					LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member})' . (isset($sortKey_joins[$_REQUEST['sort']]) ? $sortKey_joins[$_REQUEST['sort']] : '') . '
 				WHERE m.id_member = {int:current_member}' . (!empty($board) ? '
 					AND t.id_board = {int:current_board}' : '') . ($modSettings['postmod_active'] ? '

+ 0 - 10
Sources/Register.php

@@ -325,16 +325,6 @@ function Register2($verifiedOpenID = false)
 	{
 		$reg_fields = explode(',', $modSettings['registration_fields']);
 
-		// Easy string fields first.
-		foreach (array('skype', 'aim', 'yim', 'location') as $field)
-			if (in_array($field, $reg_fields))
-				$possible_strings[] = $field;
-
-		// Then the easy numeric fields.
-		foreach (array('icq', 'gender') as $field)
-			if (in_array($field, $reg_fields))
-				$possible_ints[] = $field;
-
 		// Website is a little different
 		if (in_array('website', $reg_fields))
 			$possible_strings += array('website_url', 'website_title');

+ 9 - 2
Sources/RemoveTopic.php

@@ -43,7 +43,7 @@ function RemoveTopic2()
 	removeDeleteConcurrence();
 
 	$request = $smcFunc['db_query']('', '
-		SELECT t.id_member_started, ms.subject, t.approved
+		SELECT t.id_member_started, ms.subject, t.approved, t.locked
 		FROM {db_prefix}topics AS t
 			INNER JOIN {db_prefix}messages AS ms ON (ms.id_msg = t.id_first_msg)
 		WHERE t.id_topic = {int:current_topic}
@@ -52,7 +52,7 @@ function RemoveTopic2()
 			'current_topic' => $topic,
 		)
 	);
-	list ($starter, $subject, $approved) = $smcFunc['db_fetch_row']($request);
+	list ($starter, $subject, $approved, $locked) = $smcFunc['db_fetch_row']($request);
 	$smcFunc['db_free_result']($request);
 
 	if ($starter == $user_info['id'] && !allowedTo('remove_any'))
@@ -64,6 +64,13 @@ function RemoveTopic2()
 	if ($modSettings['postmod_active'] && !$approved && $starter != $user_info['id'])
 		isAllowedTo('approve_posts');
 
+	// Ok, we got that far, but is it locked?
+	if ($locked)
+	{
+		if (!($locked == 1 && $starter == $user_info['id'] || allowedTo('lock_any')))
+			fatal_lang_error('cannot_remove_locked', 'user');
+	}
+
 	// Notify people that this topic has been removed.
 	sendNotifications($topic, 'remove');
 

+ 210 - 198
Sources/SendTopic.php → Sources/ReportToMod.php

@@ -1,7 +1,7 @@
 <?php
 
 /**
- * The functions in this file deal with sending topics to a friend or moderator
+ * The functions in this file deal with reporting posts or profiles to mods and admins
  * Simple Machines Forum (SMF)
  *
  * @package SMF
@@ -16,144 +16,7 @@ if (!defined('SMF'))
 	die('No direct access...');
 
 /**
- * Allow a user to send an email.
- * Send an email to the user - allow the sender to write the message.
- * Can either be passed a user ID as uid or a message id as msg.
- * Does not check permissions for a message ID as there is no information disclosed.
- */
-function EmailUser()
-{
-	global $context, $user_info, $smcFunc, $txt, $scripturl, $sourcedir;
-
-	// Can the user even see this information?
-	if ($user_info['is_guest'])
-		fatal_lang_error('no_access', false);
-
-	isAllowedTo('send_email_to_members');
-
-	// Don't index anything here.
-	$context['robot_no_index'] = true;
-
-	// Load the template.
-	loadTemplate('SendTopic');
-
-	// Are we sending to a user?
-	$context['form_hidden_vars'] = array();
-	if (isset($_REQUEST['uid']))
-	{
-		$request = $smcFunc['db_query']('', '
-			SELECT email_address AS email, real_name AS name, id_member, hide_email
-			FROM {db_prefix}members
-			WHERE id_member = {int:id_member}',
-			array(
-				'id_member' => (int) $_REQUEST['uid'],
-			)
-		);
-
-		$context['form_hidden_vars']['uid'] = (int) $_REQUEST['uid'];
-	}
-	elseif (isset($_REQUEST['msg']))
-	{
-		$request = $smcFunc['db_query']('', '
-			SELECT IFNULL(mem.email_address, m.poster_email) AS email, IFNULL(mem.real_name, m.poster_name) AS name, IFNULL(mem.id_member, 0) AS id_member, hide_email
-			FROM {db_prefix}messages AS m
-				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
-			WHERE m.id_msg = {int:id_msg}',
-			array(
-				'id_msg' => (int) $_REQUEST['msg'],
-			)
-		);
-
-		$context['form_hidden_vars']['msg'] = (int) $_REQUEST['msg'];
-	}
-
-	if (empty($request) || $smcFunc['db_num_rows']($request) == 0)
-		fatal_lang_error('cant_find_user_email');
-
-	$row = $smcFunc['db_fetch_assoc']($request);
-	$smcFunc['db_free_result']($request);
-
-	// Are you sure you got the address?
-	if (empty($row['email']))
-		fatal_lang_error('cant_find_user_email');
-
-	// Can they actually do this?
-	$context['show_email_address'] = showEmailAddress(!empty($row['hide_email']), $row['id_member']);
-	if ($context['show_email_address'] === 'no')
-		fatal_lang_error('no_access', false);
-
-	// Setup the context!
-	$context['recipient'] = array(
-		'id' => $row['id_member'],
-		'name' => $row['name'],
-		'email' => $row['email'],
-		'email_link' => ($context['show_email_address'] == 'yes_permission_override' ? '<em>' : '') . '<a href="mailto:' . $row['email'] . '">' . $row['email'] . '</a>' . ($context['show_email_address'] == 'yes_permission_override' ? '</em>' : ''),
-		'link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['name'] . '</a>' : $row['name'],
-	);
-
-	// Can we see this person's email address?
-	$context['can_view_receipient_email'] = $context['show_email_address'] == 'yes' || $context['show_email_address'] == 'yes_permission_override';
-
-	// Are we actually sending it?
-	if (isset($_POST['send']) && isset($_POST['email_body']))
-	{
-		require_once($sourcedir . '/Subs-Post.php');
-
-		checkSession();
-
-		// If it's a guest sort out their names.
-		if ($user_info['is_guest'])
-		{
-			if (empty($_POST['y_name']) || $_POST['y_name'] == '_' || trim($_POST['y_name']) == '')
-				fatal_lang_error('no_name', false);
-			if (empty($_POST['y_email']))
-				fatal_lang_error('no_email', false);
-			if (preg_match('~^[0-9A-Za-z=_+\-/][0-9A-Za-z=_\'+\-/\.]*@[\w\-]+(\.[\w\-]+)*(\.[\w]{2,6})$~', $_POST['y_email']) == 0)
-				fatal_lang_error('email_invalid_character', false);
-
-			$from_name = trim($_POST['y_name']);
-			$from_email = trim($_POST['y_email']);
-		}
-		else
-		{
-			$from_name = $user_info['name'];
-			$from_email = $user_info['email'];
-		}
-
-		// Check we have a body (etc).
-		if (trim($_POST['email_body']) == '' || trim($_POST['email_subject']) == '')
-			fatal_lang_error('email_missing_data');
-
-		// We use a template in case they want to customise!
-		$replacements = array(
-			'EMAILSUBJECT' => $_POST['email_subject'],
-			'EMAILBODY' => $_POST['email_body'],
-			'SENDERNAME' => $from_name,
-			'RECPNAME' => $context['recipient']['name'],
-		);
-
-		// Don't let them send too many!
-		spamProtection('sendmail');
-
-		// Get the template and get out!
-		$emaildata = loadEmailTemplate('send_email', $replacements);
-		sendmail($context['recipient']['email'], $emaildata['subject'], $emaildata['body'], $from_email, 'custemail', false, 1, null, true);
-
-		// Now work out where to go!
-		if (isset($_REQUEST['uid']))
-			redirectexit('action=profile;u=' . (int) $_REQUEST['uid']);
-		elseif (isset($_REQUEST['msg']))
-			redirectexit('msg=' . (int) $_REQUEST['msg']);
-		else
-			redirectexit();
-	}
-
-	$context['sub_template'] = 'custom_email';
-	$context['page_title'] = $txt['send_email'];
-}
-
-/**
- * Report a post to the moderator... ask for a comment.
+ * Report a post or profile to the moderator... ask for a comment.
  * Gathers data from the user to report abuse to the moderator(s).
  * Uses the ReportToModerator template, main sub template.
  * Requires the report_any permission.
@@ -162,7 +25,8 @@ function EmailUser()
  */
 function ReportToModerator()
 {
-	global $txt, $topic, $context, $smcFunc, $sourcedir;
+	global $txt, $topic, $context, $smcFunc, $scripturl, $sourcedir;
+
 
 	$context['robot_no_index'] = true;
 	$context['comment_body'] = '';
@@ -171,7 +35,11 @@ function ReportToModerator()
 	is_not_guest();
 
 	// You can't use this if it's off or you are not allowed to do it.
-	isAllowedTo('report_any');
+	// If we don't have the ID of something to report, we'll die with a no_access error below
+	if (isset($_REQUEST['msg']))
+		isAllowedTo('report_msg');
+	elseif (isset($_REQUEST['u']))
+		isAllowedTo('report_user');
 
 	// Previewing or modifying?
 	if (isset($_POST['preview']) && !isset($_POST['save']))
@@ -192,34 +60,77 @@ function ReportToModerator()
 	if ((isset($_POST[$context['session_var']]) || isset($_POST['save'])) && empty($context['post_errors']) && !isset($_POST['preview']))
 		ReportToModerator2();
 
-	// We need a message ID to check!
-	if (empty($_REQUEST['msg']) && empty($_REQUEST['mid']))
+	// We need a message ID or user ID to check!
+	if (empty($_REQUEST['msg']) && empty($_REQUEST['mid']) && empty($_REQUEST['u']))
 		fatal_lang_error('no_access', false);
 
 	// For compatibility, accept mid, but we should be using msg. (not the flavor kind!)
-	$_REQUEST['msg'] = empty($_REQUEST['msg']) ? (int) $_REQUEST['mid'] : (int) $_REQUEST['msg'];
+	if (!empty($_REQUEST['msg']) || !empty($_REQUEST['mid']))
+		$_REQUEST['msg'] = empty($_REQUEST['msg']) ? (int) $_REQUEST['mid'] : (int) $_REQUEST['msg'];
+	// msg and mid empty - assume we're reporting a user
+	elseif (!empty($_REQUEST['u']))
+		$_REQUEST['u'] = (int) $_REQUEST['u'];
 
-	// Check the message's ID - don't want anyone reporting a post they can't even see!
-	$result = $smcFunc['db_query']('', '
-		SELECT m.id_msg, m.id_member, t.id_member_started
-		FROM {db_prefix}messages AS m
-			INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic})
-		WHERE m.id_msg = {int:id_msg}
-			AND m.id_topic = {int:current_topic}
-		LIMIT 1',
-		array(
-			'current_topic' => $topic,
-			'id_msg' => $_REQUEST['msg'],
-		)
-	);
-	if ($smcFunc['db_num_rows']($result) == 0)
-		fatal_lang_error('no_board', false);
-	list ($_REQUEST['msg'], $member, $starter) = $smcFunc['db_fetch_row']($result);
-	$smcFunc['db_free_result']($result);
+	// Set up some form values
+	$context['report_type'] = isset($_REQUEST['msg']) ? 'msg' : 'u';
+	$context['reported_item'] = isset($_REQUEST['msg']) ? $_REQUEST['msg'] : $_REQUEST['u'];
+
+	if (isset($_REQUEST['msg']))
+	{
+		// Check the message's ID - don't want anyone reporting a post they can't even see!
+		$result = $smcFunc['db_query']('', '
+			SELECT m.id_msg, m.id_member, t.id_member_started
+			FROM {db_prefix}messages AS m
+				INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic})
+			WHERE m.id_msg = {int:id_msg}
+				AND m.id_topic = {int:current_topic}
+			LIMIT 1',
+			array(
+				'current_topic' => $topic,
+				'id_msg' => $_REQUEST['msg'],
+			)
+		);
+		if ($smcFunc['db_num_rows']($result) == 0)
+			fatal_lang_error('no_board', false);
+		list ($_REQUEST['msg'], $member, $starter) = $smcFunc['db_fetch_row']($result);
+		$smcFunc['db_free_result']($result);
+
+
+		// This is here so that the user could, in theory, be redirected back to the topic.
+		$context['start'] = $_REQUEST['start'];
+		$context['message_id'] = $_REQUEST['msg'];
+
+		// The submit URL is different for users than it is for posts
+		$context['submit_url'] = $scripturl . '?action=reporttm;msg=' . $_REQUEST['msg'] . ';topic=' . $topic;
+	}
+	else
+	{
+		// Check the user's ID
+		$result = $smcFunc['db_query']('', '
+			SELECT id_member, real_name, member_name
+			FROM {db_prefix}members
+			WHERE id_member = {int:current_user}',
+			array(
+				'current_user' => $_REQUEST['u'],
+			)
+		);
+
+		if ($smcFunc['db_num_rows']($result) == 0)
+			fatal_lang_error('no_user', false);
+		list($_REQUEST['u'], $display_name, $username) = $smcFunc['db_fetch_row']($result);
+
+		$context['current_user'] = $_REQUEST['u'];
+		$context['submit_url'] = $scripturl . '?action=reporttm;u=' . $_REQUEST['u'];
+	}
+
+	$context['comment_body'] = !isset($_POST['comment']) ? '' : trim($_POST['comment']);
+
+	$context['page_title'] = $context['report_type'] == 'msg' ? $txt['report_to_mod'] : sprintf($txt['report_profile'], $display_name);
+	$context['notice'] = $context['report_type'] == 'msg' ? $txt['report_to_mod_func'] : $txt['report_profile_func'];
 
 	// Show the inputs for the comment, etc.
 	loadLanguage('Post');
-	loadTemplate('SendTopic');
+	loadTemplate('ReportToMod');
 
 	addInlineJavascript('
 	var error_box = $("#error_box");
@@ -243,13 +154,6 @@ function ReportToModerator()
 				error_box.hide();
 		}
 	});', true);
-
-	// This is here so that the user could, in theory, be redirected back to the topic.
-	$context['start'] = $_REQUEST['start'];
-	$context['message_id'] = $_REQUEST['msg'];
-
-	$context['page_title'] = $txt['report_to_mod'];
-	$context['sub_template'] = 'report';
 }
 
 /**
@@ -267,7 +171,10 @@ function ReportToModerator2()
 	is_not_guest();
 
 	// You must have the proper permissions!
-	isAllowedTo('report_any');
+	if (isset($_REQUEST['msg']))
+		isAllowedTo('report_any');
+	else
+		isAllowedTo('report_user');
 
 	// Make sure they aren't spamming.
 	spamProtection('reporttm');
@@ -293,32 +200,6 @@ function ReportToModerator2()
 	if ($smcFunc['strlen']($poster_comment) > 254)
 		$post_errors[] = 'post_too_long';
 
-	// Guests need to provide their address!
-	if ($user_info['is_guest'])
-	{
-		$_POST['email'] = !isset($_POST['email']) ? '' : trim($_POST['email']);
-		if ($_POST['email'] === '')
-			$post_errors[] = 'no_email';
-		elseif (preg_match('~^[0-9A-Za-z=_+\-/][0-9A-Za-z=_\'+\-/\.]*@[\w\-]+(\.[\w\-]+)*(\.[\w]{2,6})$~', $_POST['email']) == 0)
-			$post_errors[] = 'bad_email';
-
-		isBannedEmail($_POST['email'], 'cannot_post', sprintf($txt['you_are_post_banned'], $txt['guest_title']));
-
-		$user_info['email'] = $smcFunc['htmlspecialchars']($_POST['email']);
-	}
-
-	// Could they get the right verification code?
-	if ($user_info['is_guest'] && !empty($modSettings['guests_report_require_captcha']))
-	{
-		require_once($sourcedir . '/Subs-Editor.php');
-		$verificationOptions = array(
-			'id' => 'report',
-		);
-		$context['require_verification'] = create_control_verification($verificationOptions, true);
-		if (is_array($context['require_verification']))
-			$post_errors = array_merge($post_errors, $context['require_verification']);
-	}
-
 	// Any errors?
 	if (!empty($post_errors))
 	{
@@ -331,8 +212,23 @@ function ReportToModerator2()
 		return ReportToModerator();
 	}
 
+	if (isset($_POST['msg']))
+	{
+		// Handle this elsewhere to keep things from getting too long
+		reportPost($_POST['msg'], $poster_comment);
+	}
+	else
+	{
+		reportUser($_POST['u'], $poster_comment);
+	}
+}
+
+function reportPost($msg, $reason)
+{
+	global $context, $smcFunc, $user_info;
+
 	// Get the basic topic information, and make sure they can see it.
-	$_POST['msg'] = (int) $_POST['msg'];
+	$_POST['msg'] = (int) $msg;
 
 	$request = $smcFunc['db_query']('', '
 		SELECT m.id_topic, m.id_board, m.subject, m.body, m.id_member AS id_poster, m.poster_name, mem.real_name
@@ -420,7 +316,7 @@ function ReportToModerator2()
 			),
 			array(
 				$id_report, $user_info['id'], $user_info['name'],
-				$user_info['ip'], $poster_comment, time(),
+				$user_info['ip'], $reason, time(),
 			),
 			array('id_comment')
 		);
@@ -449,4 +345,120 @@ function ReportToModerator2()
 	redirectexit('reportsent;topic=' . $topic . '.msg' . $_POST['msg'] . '#msg' . $_POST['msg']);
 }
 
+function reportUser($id_member, $reason)
+{
+	global $context, $smcFunc, $user_info;
+
+	// Get the basic topic information, and make sure they can see it.
+	$_POST['u'] = (int) $id_member;
+
+	$request = $smcFunc['db_query']('', '
+		SELECT id_member, real_name, member_name
+		FROM {db_prefix}members
+		WHERE id_member = {int:id_member}',
+		array(
+			'id_member' => $_POST['u']
+		)
+	);
+	if ($smcFunc['db_num_rows']($request) == 0)
+		fatal_lang_error('no_user', false);
+	$user = $smcFunc['db_fetch_assoc']($request);
+	$smcFunc['db_free_result']($request);
+
+	$user_name = un_htmlspecialchars($user['real_name']) . ($user['real_name'] != $user['member_name'] ? ' (' . $user['member_name'] . ')' : '');
+	$reporterName = un_htmlspecialchars($user_info['name']) . ($user_info['name'] != $user_info['username'] && $user_info['username'] != '' ? ' (' . $user_info['username'] . ')' : '');
+
+	$request = $smcFunc['db_query']('', '
+		SELECT id_report, ignore_all
+		FROM {db_prefix}log_reported
+		WHERE id_member = {int:id_member}
+			AND id_msg = {int:not_a_reported_post}
+			AND (closed = {int:not_closed} OR ignore_all = {int:ignored})
+		ORDER BY ignore_all DESC',
+		array(
+			'id_member' => $_POST['u'],
+			'not_a_reported_post' => 0,
+			'not_closed' => 0,
+			'ignored' => 1,
+		)
+	);
+	if ($smcFunc['db_num_rows']($request) != 0)
+		list ($id_report, $ignore) = $smcFunc['db_fetch_row']($request);
+
+	$smcFunc['db_free_result']($request);
+
+	// If we're just going to ignore these, then who gives a monkeys...
+	if (!empty($ignore))
+		redirectexit('action=profile;u=' . $_POST['u']);
+
+	// Already reported? My god, we could be dealing with a real rogue here...
+	if (!empty($id_report))
+		$smcFunc['db_query']('', '
+			UPDATE {db_prefix}log_reported
+			SET num_reports = num_reports + 1, time_updated = {int:current_time}
+			WHERE id_report = {int:id_report}',
+			array(
+				'current_time' => time(),
+				'id_report' => $id_report,
+			)
+		);
+	// Otherwise, we shall make one!
+	else
+	{
+		$smcFunc['db_insert']('',
+			'{db_prefix}log_reported',
+			array(
+				'id_msg' => 'int', 'id_topic' => 'int', 'id_board' => 'int', 'id_member' => 'int', 'membername' => 'string',
+				'subject' => 'string', 'body' => 'string', 'time_started' => 'int', 'time_updated' => 'int',
+				'num_reports' => 'int', 'closed' => 'int',
+			),
+			array(
+				0, 0, 0, $user['id_member'], $user_name,
+				'', '', time(), time(), 1, 0,
+			),
+			array('id_report')
+		);
+		$id_report = $smcFunc['db_insert_id']('{db_prefix}log_reported', 'id_report');
+	}
+
+	// Now just add our report...
+	if ($id_report)
+	{
+		$smcFunc['db_insert']('',
+			'{db_prefix}log_reported_comments',
+			array(
+				'id_report' => 'int', 'id_member' => 'int', 'membername' => 'string',
+				'member_ip' => 'string', 'comment' => 'string', 'time_sent' => 'int',
+			),
+			array(
+				$id_report, $user_info['id'], $user_info['name'],
+				$user_info['ip'], $reason, time(),
+			),
+			array('id_comment')
+		);
+
+		// And get ready to notify people.
+		$smcFunc['db_insert']('insert',
+			'{db_prefix}background_tasks',
+			array('task_file' => 'string', 'task_class' => 'string', 'task_data' => 'string', 'claimed_time' => 'int'),
+			array('$sourcedir/tasks/MemberReport-Notify.php', 'MemberReport_Notify_Background', serialize(array(
+				'report_id' => $id_report,
+				'user_id' => $user['id_member'],
+				'user_name' => $user_name,
+				'sender_id' => $context['user']['id'],
+				'sender_name' => $context['user']['name'],
+				'comment' => $reason,
+				'time' => time(),
+			)), 0),
+			array('id_task')
+		);
+	}
+
+	// Keep track of when the mod reports get updated, that way we know when we need to look again.
+	updateSettings(array('last_mod_report_action' => time()));
+
+	// Back to the post we reported!
+	redirectexit('reportsent;action=profile;u=' . $id_member);	
+}
+
 ?>

+ 11 - 36
Sources/Security.php

@@ -498,6 +498,17 @@ function banPermissions()
 	}
 	else
 		$context['open_mod_reports'] = 0;
+
+	if (isset($_SESSION['rmc']) && $_SESSION['rmc']['time'] > $modSettings['last_mod_report_action'] && $_SESSION['rmc']['id'] == $user_info['id'])
+		$contexct['open_member_reports'] = $_SESSION['rmc']['reports'];
+	elseif (allowedTo('moderate_forum'))
+	{
+		require_once($sourcedir . '/ModerationCenter.php');
+		recountOpenMemberReports();
+	}
+	else
+		$context['open_member_reports'] = 0;
+
 }
 
 /**
@@ -1135,42 +1146,6 @@ function boardsAllowedTo($permissions, $check_access = true, $simple = true)
 	return $boards;
 }
 
-/**
- * Returns whether an email address should be shown and how.
- * Possible outcomes are
- *  'yes': show the full email address
- *  'yes_permission_override': show the full email address, either you
- *   are a moderator or it's your own email address.
- *  'no_through_forum': don't show the email address, but do allow
- *    things to be mailed using the built-in forum mailer.
- *  'no': keep the email address hidden.
- *
- * @param bool $userProfile_hideEmail
- * @param int $userProfile_id
- * @return string (yes, yes_permission_override, no_through_forum, no)
- */
-function showEmailAddress($userProfile_hideEmail, $userProfile_id)
-{
-	global $user_info;
-
-	// Should this user's email address be shown?
-	// If you're guest and the forum is set to hide email for guests: no.
-	// If the user is post-banned: no.
-	// If it's your own profile and you've set your address hidden: yes_permission_override.
-	// If you're a moderator with sufficient permissions: yes_permission_override.
-	// If the user has set their email address to be hidden: no.
-	// Otherwise: no_through_forum.
-
-	if ($user_info['is_guest'] || isset($_SESSION['ban']['cannot_post']))
-		return 'no';
-	elseif ((!$user_info['is_guest'] && $user_info['id'] == $userProfile_id && !$userProfile_hideEmail) || allowedTo('moderate_forum'))
-		return 'yes_permission_override';
-	elseif ($userProfile_hideEmail)
-		return 'no';
-	else
-		return 'no_through_forum';
-}
-
 /**
  * This function attempts to protect from spammed messages and the like.
  * The time taken depends on error_type - generally uses the modSetting.

+ 1 - 1
Sources/Subs-Calendar.php

@@ -804,7 +804,7 @@ function getEventPoster($event_id)
  */
 function insertEvent(&$eventOptions)
 {
-	global $smcFunc;
+	global $smcFunc, $context;
 
 	// Add special chars to the title.
 	$eventOptions['title'] = $smcFunc['htmlspecialchars']($eventOptions['title'], ENT_QUOTES);

+ 3 - 0
Sources/Subs-Db-mysql.php

@@ -58,6 +58,9 @@ function smf_db_initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix,
 			'db_escape_wildcard_string' => 'smf_db_escape_wildcard_string',
 		);
 
+	if (!empty($db_options['port']))
+		$db_server .= ':' . $db_options['port'];
+
 	if (!empty($db_options['persist']))
 		$connection = @mysql_pconnect($db_server, $db_user, $db_passwd);
 	else

+ 4 - 1
Sources/Subs-Db-mysqli.php

@@ -59,7 +59,10 @@ function smf_db_initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix,
 		);
 
 	if (!empty($db_options['persist']))
-		$connection = @mysqli_connect('p:' . $db_server, $db_user, $db_passwd);
+		$db_server = 'p:' . $db_server;
+
+	if (!empty($db_options['port']))
+		$connection = @mysqli_connect($db_server, $db_user, $db_passwd, '', $db_options['port']);
 	else
 		$connection = @mysqli_connect($db_server, $db_user, $db_passwd);
 

+ 2 - 2
Sources/Subs-Db-postgresql.php

@@ -60,9 +60,9 @@ function smf_db_initiate($db_server, $db_name, $db_user, $db_passwd, &$db_prefix
 		);
 
 	if (!empty($db_options['persist']))
-		$connection = @pg_pconnect('host=' . $db_server . ' dbname=' . $db_name . ' user=\'' . $db_user . '\' password=\'' . $db_passwd . '\'');
+		$connection = @pg_pconnect('host=' . $db_server . ' dbname=' . $db_name . ' user=\'' . $db_user . '\' password=\'' . $db_passwd . '\'' . (empty($db_options['port']) ? '' : ' port=\'' . $db_options['port'] . '\''));
 	else
-		$connection = @pg_connect( 'host=' . $db_server . ' dbname=' . $db_name . ' user=\'' . $db_user . '\' password=\'' . $db_passwd . '\'');
+		$connection = @pg_connect( 'host=' . $db_server . ' dbname=' . $db_name . ' user=\'' . $db_user . '\' password=\'' . $db_passwd . '\'' . (empty($db_options['port']) ? '' : ' port=\'' . $db_options['port'] . '\''));
 
 	// Something's wrong, show an error if its fatal (which we assume it is)
 	if (!$connection)

+ 2 - 11
Sources/Subs-Members.php

@@ -625,11 +625,6 @@ function registerMember(&$regOptions, $return_errors = false)
 		'pm_ignore_list' => '',
 		'website_title' => '',
 		'website_url' => '',
-		'location' => '',
-		'icq' => '',
-		'aim' => '',
-		'yim' => '',
-		'skype' => '',
 		'time_format' => '',
 		'signature' => '',
 		'avatar' => '',
@@ -684,10 +679,6 @@ function registerMember(&$regOptions, $return_errors = false)
 			$regOptions['register_vars']['id_group'] = 0;
 	}
 
-	// ICQ cannot be zero.
-	if (isset($regOptions['extra_register_vars']['icq']) && empty($regOptions['extra_register_vars']['icq']))
-		$regOptions['extra_register_vars']['icq'] = '';
-
 	// Integrate optional member settings to be set.
 	if (!empty($regOptions['extra_register_vars']))
 		foreach ($regOptions['extra_register_vars'] as $var => $value)
@@ -702,7 +693,7 @@ function registerMember(&$regOptions, $return_errors = false)
 	// Right, now let's prepare for insertion.
 	$knownInts = array(
 		'date_registered', 'posts', 'id_group', 'last_login', 'instant_messages', 'unread_messages',
-		'new_pm', 'pm_prefs', 'gender', 'hide_email', 'show_online', 'pm_email_notify', 'karma_good', 'karma_bad',
+		'new_pm', 'pm_prefs', 'hide_email', 'show_online', 'pm_email_notify', 'karma_good', 'karma_bad',
 		'notify_announcements', 'notify_send_body', 'notify_regularity', 'notify_types',
 		'id_theme', 'is_activated', 'id_msg_last_visit', 'id_post_group', 'total_time_logged_in', 'warning',
 	);
@@ -1320,7 +1311,7 @@ function list_getMembers($start, $items_per_page, $sort, $where, $where_params =
 
 	$request = $smcFunc['db_query']('', '
 		SELECT
-			mem.id_member, mem.member_name, mem.real_name, mem.email_address, mem.icq, mem.aim, mem.yim, mem.skype, mem.member_ip, mem.member_ip2, mem.last_login,
+			mem.id_member, mem.member_name, mem.real_name, mem.email_address, mem.member_ip, mem.member_ip2, mem.last_login,
 			mem.posts, mem.is_activated, mem.date_registered, mem.id_group, mem.additional_groups, mg.group_name
 		FROM {db_prefix}members AS mem
 			LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = mem.id_group)

+ 63 - 17
Sources/Subs.php

@@ -89,23 +89,46 @@ function updateStats($type, $parameter1 = null, $parameter2 = null)
 			list ($changes['latestRealName']) = $smcFunc['db_fetch_row']($result);
 			$smcFunc['db_free_result']($result);
 
-			// Are we using registration approval?
-			if ((!empty($modSettings['registration_method']) && $modSettings['registration_method'] == 2) || !empty($modSettings['approveAccountDeletion']))
+			if (!empty($modSettings['registration_method']))
 			{
-				// Update the amount of members awaiting approval - ignoring COPPA accounts, as you can't approve them until you get permission.
-				$result = $smcFunc['db_query']('', '
-					SELECT COUNT(*)
-					FROM {db_prefix}members
-					WHERE is_activated IN ({array_int:activation_status})',
-					array(
-						'activation_status' => array(3, 4),
-					)
-				);
-				list ($changes['unapprovedMembers']) = $smcFunc['db_fetch_row']($result);
-				$smcFunc['db_free_result']($result);
+				// Are we using registration approval?
+				if ($modSettings['registration_method'] == 2 || !empty($modSettings['approveAccountDeletion']))
+				{
+					// Update the amount of members awaiting approval
+					$result = $smcFunc['db_query']('', '
+						SELECT COUNT(*)
+						FROM {db_prefix}members
+						WHERE is_activated IN ({array_int:activation_status})',
+						array(
+							'activation_status' => array(3, 4),
+						)
+					);
+					list ($changes['unapprovedMembers']) = $smcFunc['db_fetch_row']($result);
+					$smcFunc['db_free_result']($result);
+				}
+
+				// What about unapproved COPPA registrations?
+				if (!empty($modSettings['coppaType']) && $modSettings['coppaType'] != 1)
+				{
+					$result = $smcFunc['db_query']('', '
+						SELECT COUNT(*)
+						FROM {db_prefix}members
+						WHERE is_activated = {int:coppa_approval}',
+						array(
+							'coppa_approval' => 5,
+						)
+					);
+					list ($coppa_approvals) = $smcFunc['db_fetch_row']($result);
+					$smcFunc['db_free_result']($result);
+
+					// Add this to the number of unapproved members
+					if (!empty($changes['unapprovedMembers']))
+						$changes['unapprovedMembers'] += $coppa_approvals;
+					else
+						$changes['unapprovedMembers'] = $coppa_approvals;
+				}
 			}
 		}
-
 		updateSettings($changes);
 		break;
 
@@ -2869,7 +2892,7 @@ function setupThemeContext($forceload = false)
 		$_SESSION['unread_messages'] = $user_info['unread_messages'];
 
 		if (allowedTo('moderate_forum'))
-			$context['unapproved_members'] = (!empty($modSettings['registration_method']) && $modSettings['registration_method'] == 2) || !empty($modSettings['approveAccountDeletion']) ? $modSettings['unapprovedMembers'] : 0;
+			$context['unapproved_members'] = (!empty($modSettings['registration_method']) && ($modSettings['registration_method'] == 2 || (!empty($modSettings['coppaType']) && $modSettings['coppaType'] == 2))) || !empty($modSettings['approveAccountDeletion']) ? $modSettings['unapprovedMembers'] : 0;
 
 		$context['user']['avatar'] = array();
 
@@ -3789,8 +3812,13 @@ function setupMenuContext()
 						'title' => $txt['mc_reported_posts'],
 						'href' => $scripturl . '?action=moderate;area=reports',
 						'show' => !empty($user_info['mod_cache']) && $user_info['mod_cache']['bq'] != '0=1',
-						'is_last' => true,
 					),
+					'reported_members' => array(
+						'title' => $txt['mc_reported_members'],
+						'href' => $scripturl . '?action=moderate;area=memberreports',
+						'show' => allowedTo('moderate_forum'),
+						'is_last' => true,
+					)
 				),
 			),
 			'calendar' => array(
@@ -3936,17 +3964,35 @@ function setupMenuContext()
 	if (isset($context['menu_buttons'][$current_action]))
 		$context['menu_buttons'][$current_action]['active_button'] = true;
 
+	$total_mod_reports = 0;
+
 	if (!empty($user_info['mod_cache']) && $user_info['mod_cache']['bq'] != '0=1' && !empty($context['open_mod_reports']))
 	{
-		$context['menu_buttons']['moderate']['title'] .= ' <span class="amt">' . $context['open_mod_reports'] . '</span>';
+		$total_mod_reports = $context['open_mod_reports'];
 		$context['menu_buttons']['moderate']['sub_buttons']['reports']['title'] .= ' <span class="amt">' . $context['open_mod_reports'] . '</span>';
 	}
 
+	/**
+	 * @todo For some reason, $context['open_member_reports'] isn't getting set
+	 */
+	if (allowedTo('moderate_forum') && !empty($context['open_member_reports']))
+	{
+		$total_mod_reports += $context['open_member_reports'];
+		$context['menu_buttons']['moderate']['sub_buttons']['reported_members']['title'] .= ' <span class="amt">' . $context['open_member_reports'] . '</span>';
+	}
+
 	if (!empty($context['unapproved_members']))
 	{
 		$context['menu_buttons']['admin']['sub_buttons']['memberapprove']['title'] .= ' <span class="amt">' . $context['unapproved_members'] . '</span>';
 		$context['menu_buttons']['admin']['title'] .= ' <span class="amt">' . $context['unapproved_members'] . '</span>';
 	}
+
+	// Do we have any open reports?
+	if ($total_mod_reports > 0)
+	{
+		$context['menu_buttons']['moderate']['title'] .= ' <span class="amt">' . $total_mod_reports . '</span>';
+	}
+	
 }
 
 /**

+ 1 - 1
Sources/Themes.php

@@ -1388,7 +1388,7 @@ function InstallCopy()
 	mkdir($context['to_install']['theme_dir'] . '/scripts', 0777);
 
 	// Copy over the default non-theme files.
-	$to_copy = array('/index.php', '/index.template.php', '/css/index.css', '/css/rtl.css', '/css/admin.css', '/scripts/theme.js');
+	$to_copy = array('/index.php', '/index.template.php', '/css/index.css', '/css/rtl.css', '/css/calendar.css', '/css/calendar.rtl.css', '/css/admin.css', '/scripts/theme.js');
 
 	foreach ($to_copy as $file)
 	{

+ 5 - 1
Sources/tasks/EventNew-Notify.php

@@ -24,6 +24,10 @@ class EventNew_Notify_Background extends SMF_BackgroundTask
 		require_once($sourcedir . '/Subs-Members.php');
 		$members = membersAllowedTo('calendar_view');
 
+		// Don't alert the event creator
+		if (!empty($this->_details['sender_id']))
+			$members = array_diff($members, array($this->_details['sender_id']));
+
 		// Having successfully figured this out, now let's get the preferences of everyone.
 		require_once($sourcedir . '/Subs-Notify.php');
 		$prefs = getNotifyPrefs($members, 'event_new', true);
@@ -69,7 +73,7 @@ class EventNew_Notify_Background extends SMF_BackgroundTask
 					'content_id' => $this->_details['event_id'],
 					'content_action' => empty($this->_details['sender_id']) ? 'new_guest' : 'new',
 					'is_read' => 0,
-					'extra' => '',
+					'extra' => serialize(array($this->_details['event_id'], $this->_details['event_title'])),
 				);
 			}
 

+ 135 - 0
Sources/tasks/MemberReport-Notify.php

@@ -0,0 +1,135 @@
+<?php
+
+/**
+ * This task handles notifying users when another member's profile gets reported.
+ *
+ * Simple Machines Forum (SMF)
+ *
+ * @package SMF
+ * @author Simple Machines http://www.simplemachines.org
+ * @copyright 2014 Simple Machines and individual contributors
+ * @license http://www.simplemachines.org/about/smf/license.php BSD
+ *
+ * @version 2.1 Alpha 1
+ */
+
+class MemberReport_Notify_Background extends SMF_BackgroundTask
+{
+	public function execute()
+	{
+		global $smcFunc, $sourcedir, $modSettings, $language, $scripturl;
+
+		// Anyone with moderate_forum can see this report
+		require_once($sourcedir . '/Subs-Members.php');
+		$members = membersAllowedTo('moderate_forum');
+
+		// And don't send it to them if they're the one who reported it.
+		$members = array_diff($members, array($this->_details['sender_id']));
+
+		// Having successfully figured this out, now let's get the preferences of everyone.
+		require_once($sourcedir . '/Subs-Notify.php');
+		$prefs = getNotifyPrefs($members, 'member_report', true);
+
+		// So now we find out who wants what.
+		$alert_bits = array(
+			'alert' => 0x01,
+			'email' => 0x02,
+		);
+		$notifies = array();
+
+		foreach ($prefs as $member => $pref_option)
+		{
+			foreach ($alert_bits as $type => $bitvalue)
+				if ($pref_option['member_report'] & $bitvalue)
+					$notifies[$type][] = $member;
+		}
+
+		// Firstly, anyone who wants alerts.
+		if (!empty($notifies['alert']))
+		{
+			// Alerts are relatively easy.
+			$insert_rows = array();
+			foreach ($notifies['alert'] as $member)
+			{
+				$insert_rows[] = array(
+					'alert_time' => $this->_details['time'],
+					'id_member' => $member,
+					'id_member_started' => $this->_details['sender_id'],
+					'member_name' => $this->_details['sender_name'],
+					'content_type' => 'profile',
+					'content_id' => $this->_details['user_id'],
+					'content_action' => 'report',
+					'is_read' => 0,
+					'extra' => serialize(
+						array(
+							'report_link' => '?action=moderate;area=memberreports;report=' . $this->_details['report_id'], // We don't put $scripturl in these!
+							'user_name' => $this->_details['membername'],
+						)
+					),
+				);
+			}
+
+			$smcFunc['db_insert']('insert',
+				'{db_prefix}user_alerts',
+				array('alert_time' => 'int', 'id_member' => 'int', 'id_member_started' => 'int',
+					'member_name' => 'string', 'content_type' => 'string', 'content_id' => 'int',
+					'content_action' => 'string', 'is_read' => 'int', 'extra' => 'string'),
+				$insert_rows,
+				array('id_alert')
+			);
+
+			// And update the count of alerts for those people.
+			updateMemberData($notifies['alert'], array('alerts' => '+'));
+		}
+
+		// Secondly, anyone who wants emails.
+		if (!empty($notifies['email']))
+		{
+			// Emails are a bit complicated. We have to do language stuff.
+			require_once($sourcedir . '/Subs-Post.php');
+			require_once($sourcedir . '/ScheduledTasks.php');
+			loadEssentialThemeData();
+
+			// First, get everyone's language and details.
+			$emails = array();
+			$request = $smcFunc['db_query']('', '
+				SELECT id_member, lngfile, email_address
+				FROM {db_prefix}members
+				WHERE id_member IN ({array_int:members})',
+				array(
+					'members' => $notifies['email'],
+				)
+			);
+			while ($row = $smcFunc['db_fetch_assoc']($request))
+			{
+				if (empty($row['lngfile']))
+					$row['lngfile'] = $language;
+				$emails[$row['lngfile']][$row['id_member']] = $row['email_address'];
+			}
+			$smcFunc['db_free_result']($request);
+
+			// Iterate through each language, load the relevant templates and set up sending.
+			foreach ($emails as $this_lang => $recipients)
+			{
+				$replacements = array(
+					'MEMBERNAME' => $member_name,
+					'REPORTERNAME' => $this->_details['sender_name'],
+					'PROFILELINK' => $scripturl . '?action=profile;u=' . $this->_details['user_id'],
+					'REPORTLINK' => $scripturl . '?action=moderate;area=reports;report=' . $this->_details['report_id'],
+					'COMMENT' => $this->_details['comment'],
+				);
+
+				$emaildata = loadEmailTemplate('report_member_profile', $replacements, empty($modSettings['userLanguage']) ? $language : $this_lang);
+
+				// And do the actual sending...
+				foreach ($recipients as $id_member => $email_address)
+					sendmail($email_address, $emaildata['subject'], $emaildata['body'], null, 'ureport' . $this->_details['report_id'], false, 2);
+			}
+		}
+
+		// And now we're all done.
+		return true;
+	}
+}
+
+?>

+ 161 - 0
Sources/tasks/MemberReportReply-Notify.php

@@ -0,0 +1,161 @@
+<?php
+
+/**
+ * This task handles notifying users when they've commented to a moderation report and
+ * someone else replies to them.
+ *
+ * Simple Machines Forum (SMF)
+ *
+ * @package SMF
+ * @author Simple Machines http://www.simplemachines.org
+ * @copyright 2014 Simple Machines and individual contributors
+ * @license http://www.simplemachines.org/about/smf/license.php BSD
+ *
+ * @version 2.1 Alpha 1
+ */
+
+class MemberReportReply_Notify_Background extends SMF_BackgroundTask
+{
+	public function execute()
+	{
+		global $smcFunc, $sourcedir, $modSettings, $language, $scripturl;
+
+		// Let's see. Let us, first of all, establish the list of possible people.
+		$possible_members = array();
+		$request = $smcFunc['db_query']('', '
+			SELECT id_member
+			FROM {db_prefix}log_comments
+			WHERE id_notice = {int:report}
+				AND comment_type = {literal:reportc}
+				AND id_comment < {int:last_comment}',
+			array(
+				'report' => $this->_details['report_id'],
+				'last_comment' => $this->_details['comment_id'],
+			)
+		);
+		while ($row = $smcFunc['db_fetch_row']($request))
+			$possible_members[] = $row[0];
+		$smcFunc['db_free_result']($request);
+
+		// Presumably, there are some people?
+		if (!empty($possible_members))
+		{
+			$possible_members = array_flip(array_flip($possible_members));
+			$possible_members = array_diff($possible_members, array($this->_details['sender_id']));
+		}
+		if (empty($possible_members))
+			return true;
+
+		// We need to know who can moderate this board - and therefore who can see this report.
+		// First up, people who have moderate_board in the board this topic was in.
+		require_once($sourcedir . '/Subs-Members.php');
+		$members = membersAllowedTo('moderate_forum');
+
+		// Having successfully figured this out, now let's get the preferences of everyone.
+		require_once($sourcedir . '/Subs-Notify.php');
+		$prefs = getNotifyPrefs($members, 'member_report_reply', true);
+
+		// So now we find out who wants what.
+		$alert_bits = array(
+			'alert' => 0x01,
+			'email' => 0x02,
+		);
+		$notifies = array();
+
+		foreach ($prefs as $member => $pref_option)
+		{
+			foreach ($alert_bits as $type => $bitvalue)
+			{
+				if ($pref_option['member_report_reply'] & $bitvalue)
+					$notifies[$type][] = $member;
+			}
+		}
+
+		// Firstly, anyone who wants alerts.
+		if (!empty($notifies['alert']))
+		{
+			// Alerts are relatively easy.
+			$insert_rows = array();
+			foreach ($notifies['alert'] as $member)
+			{
+				$insert_rows[] = array(
+					'alert_time' => $this->_details['time'],
+					'id_member' => $member,
+					'id_member_started' => $this->_details['sender_id'],
+					'member_name' => $this->_details['sender_name'],
+					'content_type' => 'profile',
+					'content_id' => $this->_details['user_id'],
+					'content_action' => 'report_reply',
+					'is_read' => 0,
+					'extra' => serialize(
+						array(
+							'report_link' => '?action=moderate;area=memberreports;report=' . $this->_details['report_id'], // We don't put $scripturl in these!
+							'user_name' => $this->_details['user_name'],
+						)
+					),
+				);
+			}
+
+			$smcFunc['db_insert']('insert',
+				'{db_prefix}user_alerts',
+				array('alert_time' => 'int', 'id_member' => 'int', 'id_member_started' => 'int',
+					'member_name' => 'string', 'content_type' => 'string', 'content_id' => 'int',
+					'content_action' => 'string', 'is_read' => 'int', 'extra' => 'string'),
+				$insert_rows,
+				array('id_alert')
+			);
+
+			// And update the count of alerts for those people.
+			updateMemberData($notifies['alert'], array('alerts' => '+'));
+		}
+
+		// Secondly, anyone who wants emails.
+		if (!empty($notifies['email']))
+		{
+			// Emails are a bit complicated. We have to do language stuff.
+			require_once($sourcedir . '/Subs-Post.php');
+			require_once($sourcedir . '/ScheduledTasks.php');
+			loadEssentialThemeData();
+
+			// First, get everyone's language and details.
+			$emails = array();
+			$request = $smcFunc['db_query']('', '
+				SELECT id_member, lngfile, email_address
+				FROM {db_prefix}members
+				WHERE id_member IN ({array_int:members})',
+				array(
+					'members' => $notifies['email'],
+				)
+			);
+			while ($row = $smcFunc['db_fetch_assoc']($request))
+			{
+				if (empty($row['lngfile']))
+					$row['lngfile'] = $language;
+				$emails[$row['lngfile']][$row['id_member']] = $row['email_address'];
+			}
+			$smcFunc['db_free_result']($request);
+
+			// Iterate through each language, load the relevant templates and set up sending.
+			foreach ($emails as $this_lang => $recipients)
+			{
+				$replacements = array(
+					'MEMBERNAME' => $this->_details['member_name'],
+					'COMMENTERNAME' => $this->_details['sender_name'],
+					'PROFILELINK' => $scripturl . 'action=profile;u=' . $this->_details['user_id'],
+					'REPORTLINK' => $scripturl . '?action=moderate;area=userreports;report=' . $this->_details['report_id'],
+				);
+
+				$emaildata = loadEmailTemplate('reply_to_user_reports', $replacements, empty($modSettings['userLanguage']) ? $language : $this_lang);
+
+				// And do the actual sending...
+				foreach ($recipients as $id_member => $email_address)
+					sendmail($email_address, $emaildata['subject'], $emaildata['body'], null, 'urptrpy' . $this->_details['comment_id'], false, 3);
+			}
+		}
+
+		// And now we're all done.
+		return true;
+	}
+}
+
+?>

+ 11 - 5
Themes/default/Admin.template.php

@@ -169,7 +169,7 @@ function template_credits()
 					<div id="admincenter">
 						<div id="support_credits">
 							<div class="sub_bar">
-								<h3 class="subg">
+								<h3 class="subbg">
 									', $txt['support_title'], ' <img src="', $settings['images_url'], '/smflogo.png" id="credits_logo" alt="">
 								</h3>
 							</div>
@@ -203,7 +203,7 @@ function template_credits()
 	// Point the admin to common support resources.
 	echo '
 							<div id="support_resources" class="sub_bar">
-								<h3 class="subg">
+								<h3 class="subbg">
 									', $txt['support_resources'], '
 								</h3>
 							</div>
@@ -217,7 +217,7 @@ function template_credits()
 	// The most important part - the credits :P.
 	echo '
 							<div id="credits_sections" class="sub_bar">
-								<h3 class="subg">
+								<h3 class="subbg">
 									', $txt['admin_credits'], '
 								</h3>
 							</div>
@@ -894,10 +894,16 @@ function template_show_settings()
 				{
 					// Figure out the exact type - use "number" for "float" and "int".
 					$type = in_array($config_var['type'], $text_types) ? $config_var['type'] : ($config_var['type'] == 'int' || $config_var['type'] == 'float' ? 'number' : 'text');
-					$step = $config_var['type'] == 'float' ? ' step="0.1"' : '';
+
+					// Extra options for float/int values - how much to decrease/increase by, the min value and the max value
+					// The step - only set if incrementing by something other than 1 for int or 0.1 for float
+					$step = isset($config_var['step']) ? ' step="' . $config_var['step'] . '"' : ($config_var['type'] == 'float' ? ' step="0.1"' : '');
+					// Minimum allowed value for this setting. Most settings are 0
+					$min = isset($config_var['min']) ? ' min="' . $config_var['min'] . '"' : ($config_var['type'] == 'int' || $config_var['type'] == 'float' ? ' min="0"' : '');
+					$max = isset($config_var['max']) ? ' max="' . $config_var['max'] . '"' : '';
 
 					echo '
-											<input type="', $type ,'"', $javascript, $disabled, ' name="', $config_var['name'], '" id="', $config_var['name'], '" value="', $config_var['value'], '"', ($config_var['size'] ? ' size="' . $config_var['size'] . '"' : ''), ' class="input_text"', $step, '>';
+											<input type="', $type ,'"', $javascript, $disabled, ' name="', $config_var['name'], '" id="', $config_var['name'], '" value="', $config_var['value'], '"', ($config_var['size'] ? ' size="' . $config_var['size'] . '"' : ''), ' class="input_text"', $min . $max . $step, '>';
 				}
 
 				echo isset($config_var['postinput']) ? '

+ 4 - 4
Themes/default/BoardIndex.template.php

@@ -294,7 +294,7 @@ function template_ic_block_recent()
 	// This is the "Recent Posts" bar.
 	echo '
 			<div class="sub_bar">
-				<h4 class="subg">
+				<h4 class="subbg">
 					<a href="', $scripturl, '?action=recent"><img class="icon" src="', $settings['images_url'], '/post/xx.png" alt="">', $txt['recent_posts'], '</a>
 				</h4>
 			</div>
@@ -346,7 +346,7 @@ function template_ic_block_calendar()
 	// Show information about events, birthdays, and holidays on the calendar.
 	echo '
 			<div class="sub_bar">
-				<h4 class="subg">
+				<h4 class="subbg">
 					<a href="', $scripturl, '?action=calendar' . '"><img class="icon" src="', $settings['images_url'], '/icons/calendar.png', '" alt="">', $context['calendar_only_today'] ? $txt['calendar_today'] : $txt['calendar_upcoming'], '</a>
 				</h4>
 			</div>';
@@ -394,7 +394,7 @@ function template_ic_block_stats()
 	// Show statistical style information...
 	echo '
 			<div class="sub_bar">
-				<h4 class="subg">
+				<h4 class="subbg">
 					<a href="', $scripturl, '?action=stats" title="', $txt['more_stats'], '"><span class="stats_icon boards"></span>', $txt['forum_stats'], '</a>
 				</h4>
 			</div>
@@ -411,7 +411,7 @@ function template_ic_block_online()
 	// "Users online" - in order of activity.
 	echo '
 			<div class="sub_bar">
-				<h4 class="subg">
+				<h4 class="subbg">
 					', $context['show_who'] ? '<a href="' . $scripturl . '?action=who">' : '', '<span class="stats_icon people"></span>', $txt['online_users'], '', $context['show_who'] ? '</a>' : '', '
 				</h4>
 			</div>

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

@@ -611,16 +611,16 @@ function template_event_post()
 	}
 
 	// If this is a new event let the user specify which board they want the linked post to be put into.
-	if ($context['event']['new'] && !empty($context['event']['categories']))
+	if (!empty($context['event']['categories']))
 	{
 		echo '
 							<li>
 								', $txt['calendar_link_event'], '
-								<input type="checkbox" style="vertical-align: middle;" class="input_check" name="link_to_board" checked onclick="toggleLinked(this.form);">
+								<input type="checkbox" style="vertical-align: middle;" class="input_check" name="link_to_board"', ($context['event']['new'] ? ' checked' : ''), ' onclick="toggleLinked(this.form);">
 							</li>
 							<li>
 								', $txt['calendar_post_in'], '
-								<select id="board" name="board" onchange="this.form.submit();">';
+								<select id="board" name="board" onchange="this.form.submit();"', ($context['event']['new'] ? '' : ' disabled'), '>';
 		foreach ($context['event']['categories'] as $category)
 		{
 			echo '

+ 8 - 34
Themes/default/Display.template.php

@@ -22,14 +22,6 @@ function template_main()
 				', $txt['report_sent'], '
 			</div>';
 	}
-	// Topic was sent successfully
-	elseif ($context['topic_sent'])
-	{
-		echo '
-			<div class="infobox">
-				', $txt['topic_sent'], '
-			</div>';
-	}
 
 	// Show the anchor for the top and for the first message. If the first message is new, say so.
 	echo '
@@ -509,7 +501,7 @@ function template_single_post($message, $force_alternate = null)
 	echo '
 						<div class="poster">
 									<h4>';
-									
+
 	// Show online and offline buttons?
 	if (!empty($modSettings['onlineEnable']) && !$message['member']['is_guest'])
 		echo '
@@ -520,10 +512,10 @@ function template_single_post($message, $force_alternate = null)
 	echo '
 								', $message['member']['link'], '
 									</h4>';
-									
+
 	echo '
 								<ul>';
-								
+
 
 	// Show the user's avatar.
 	if (!empty($settings['show_user_images']) && empty($options['show_no_avatars']) && !empty($message['member']['avatar']['image']))
@@ -577,11 +569,6 @@ function template_single_post($message, $force_alternate = null)
 									<a href="', $scripturl, '?action=modifykarma;sa=smite;uid=', $message['member']['id'], ';topic=', $context['current_topic'], '.', $context['start'], ';m=', $message['id'], ';', $context['session_var'], '=', $context['session_id'], '">', $modSettings['karmaSmiteLabel'], '</a>
 								</li>';
 
-		// Show the member's gender icon?
-		if (!empty($settings['show_gender']) && $message['member']['gender']['image'] != '' && !isset($context['disabled_fields']['gender']))
-			echo '
-								<li class="gender">', $txt['gender'], ': ', $message['member']['gender']['image'], '</li>';
-
 		// Show their personal text?
 		if (!empty($settings['show_blurb']) && $message['member']['blurb'] != '')
 			echo '
@@ -612,18 +599,6 @@ function template_single_post($message, $force_alternate = null)
 								</li>';
 		}
 
-		// This shows the popular messaging icons.
-		if ($message['member']['has_messenger'] && $message['member']['can_view_profile'])
-			echo '
-								<li class="im_icons">
-									<ol>
-										', !empty($message['member']['icq']['link']) ? '<li>' . $message['member']['icq']['link'] . '</li>' : '', '
-										', !empty($message['member']['skype']['link']) ? '<li>' . $message['member']['skype']['link'] . '</li>' : '', '
-										', !empty($message['member']['aim']['link']) ? '<li>' . $message['member']['aim']['link'] . '</li>' : '', '
-										', !empty($message['member']['yim']['link']) ? '<li>' . $message['member']['yim']['link'] . '</li>' : '', '
-									</ol>
-								</li>';
-
 		// Show the website and email address buttons.
 		if ($message['member']['show_profile_buttons'])
 		{
@@ -635,7 +610,7 @@ function template_single_post($message, $force_alternate = null)
 			if ($message['member']['website']['url'] != '' && !isset($context['disabled_fields']['website']))
 				echo '
 										<li><a href="', $message['member']['website']['url'], '" title="' . $message['member']['website']['title'] . '" target="_blank" class="new_win">', ($settings['use_image_buttons'] ? '<span class="generic_icons www centericon" title="' . $message['member']['website']['title'] . '"></span>' : $txt['www']), '</a></li>';
-										
+
 			// Since we know this person isn't a guest, you *can* message them.
 			if ($context['can_send_pm'])
 				echo '
@@ -656,11 +631,10 @@ function template_single_post($message, $force_alternate = null)
 		}
 
 	}
-
 	// Otherwise, show the guest's email.
-	elseif (!empty($message['member']['email']) && in_array($message['member']['show_email'], array('yes', 'yes_permission_override', 'no_through_forum')) && $context['can_send_email'])
+	elseif (!empty($message['member']['email']) && $message['member']['show_email'])
 		echo '
-								<li class="email"><a href="', $scripturl, '?action=emailuser;sa=email;msg=', $message['id'], '" rel="nofollow">', ($settings['use_image_buttons'] ? '<span class="generic_icons mail centericon" title="' . $txt['email'] . '"></span>' : $txt['email']), '</a></li>';
+								<li class="email"><a href="mailto:' . $message['member']['email'] . '" rel="nofollow">', ($settings['use_image_buttons'] ? '<span class="generic_icons mail centericon" title="' . $txt['email'] . '"></span>' : $txt['email']), '</a></li>';
 
 	// Show the IP to this user for this post - because you can moderate?
 	if (!empty($context['can_moderate_forum']) && !empty($message['member']['ip']))
@@ -713,7 +687,7 @@ function template_single_post($message, $force_alternate = null)
 	// Because we insert into it through AJAX and we don't want to stop themers moving it around if they so wish so they can put it where they want it.
 	echo '
 									<span class="smalltext modified" id="modified_', $message['id'], '">';
-	
+
 	if ($settings['show_modify'] && !empty($message['modified']['name']))
 		echo $message['modified']['last_edit_text'];
 	echo '</span>';
@@ -973,4 +947,4 @@ function template_single_post($message, $force_alternate = null)
 				<hr class="post_separator">';
 }
 
-?>
+?>

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

@@ -21,7 +21,7 @@ function template_control_richedit($editor_id, $smileyContainer = null, $bbcCont
 		<div>
 			<div>
 				<div>
-					<textarea class="editor" name="', $editor_id, '" id="', $editor_id, '" rows="" cols="600" onselect="storeCaret(this);" onclick="storeCaret(this);" onkeyup="storeCaret(this);" onchange="storeCaret(this);" tabindex="', $context['tabindex']++, '" style="width: ', $editor_context['width'], ';height: ', $editor_context['height'], '; ', isset($context['post_error']['no_message']) || isset($context['post_error']['long_message']) ? 'border: 1px solid red;' : '', '"', !empty($context['editor']['required']) ? ' required' : '', '>', $editor_context['value'], '</textarea>
+					<textarea class="editor" name="', $editor_id, '" id="', $editor_id, '" cols="600" onselect="storeCaret(this);" onclick="storeCaret(this);" onkeyup="storeCaret(this);" onchange="storeCaret(this);" tabindex="', $context['tabindex']++, '" style="width: ', $editor_context['width'], '; height: ', $editor_context['height'], ';', isset($context['post_error']['no_message']) || isset($context['post_error']['long_message']) ? 'border: 1px solid red;' : '', '"', !empty($context['editor']['required']) ? ' required' : '', '>', $editor_context['value'], '</textarea>
 				</div>
 				<div id="', $editor_id, '_resizer" class="richedit_resize"></div>
 			</div>

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

@@ -64,7 +64,7 @@ function template_generic_menu_dropdown_above()
 					$url = isset($sub['url']) ? $sub['url'] : (isset($area['url']) ? $area['url'] : $menu_context['base_url'] . ';area=' . $i) . ';sa=' . $sa;
 
 					echo '
-										<li ', !empty($area['subsections']) ? ' class="subsections"' : '', '>
+										<li>
 											<a ', !empty($sub['selected']) ? 'class="chosen" ' : '', ' href="', $url, $menu_context['extra_parameters'], '">', $sub['label'], '</a>
 										</li>';
 				}

+ 0 - 20
Themes/default/ManageMembers.template.php

@@ -116,36 +116,16 @@ function template_search_members()
 								<dd>
 									<input type="url" name="website" id="website" value="" class="input_text">
 								</dd>
-								<dt class="righttext">
-									<strong><label for="location">', $txt['location'], ':</label></strong>
-								</dt>
-								<dd>
-									<input type="text" name="location" id="location" value="" class="input_text">
-								</dd>
 								<dt class="righttext">
 									<strong><label for="ip">', $txt['ip_address'], ':</label></strong>
 								</dt>
 								<dd>
 									<input type="text" name="ip" id="ip" value="" class="input_text">
 								</dd>
-								<dt class="righttext">
-									<strong><label for="messenger">', $txt['messenger_address'], ':</label></strong>
-								</dt>
-								<dd>
-									<input type="text" name="messenger" id="messenger" value="" class="input_text">
-								</dd>
 							</dl>
 						</div>
 					</div>
 					<div class="flow_hidden">
-						<div class="msearch_details floatleft">
-							<fieldset>
-								<legend>', $txt['gender'], '</legend>
-								<label for="gender-0"><input type="checkbox" name="gender[]" value="0" id="gender-0" checked class="input_check"> ', $txt['undefined_gender'], '</label>&nbsp;&nbsp;
-								<label for="gender-1"><input type="checkbox" name="gender[]" value="1" id="gender-1" checked class="input_check"> ', $txt['male'], '</label>&nbsp;&nbsp;
-								<label for="gender-2"><input type="checkbox" name="gender[]" value="2" id="gender-2" checked class="input_check"> ', $txt['female'], '</label>
-							</fieldset>
-						</div>
 						<div class="msearch_details floatright">
 							<fieldset>
 								<legend>', $txt['activation_status'], '</legend>

+ 5 - 0
Themes/default/ManageNews.template.php

@@ -14,6 +14,11 @@ function template_email_members()
 {
 	global $context, $settings, $txt, $scripturl;
 
+	// Are we done sending the newsletter?
+	if (!empty($context['newsletter_sent']))
+		echo '
+	<div class="infobox">', $txt['admin_news_newsletter_'. $context['newsletter_sent']] ,'</div>';
+
 	echo '
 	<div id="admincenter">
 		<form action="', $scripturl, '?action=admin;area=news;sa=mailingcompose" method="post" id="admin_newsletters" class="flow_hidden" accept-charset="', $context['character_set'], '">

+ 0 - 20
Themes/default/Memberlist.template.php

@@ -77,26 +77,6 @@ function template_main()
 			echo '
 					<td class="centertext">', $member['website']['url'] != '' ? '<a href="' . $member['website']['url'] . '" target="_blank" class="new_win"><span class="generic_icons www" title="' . $member['website']['title'] . '"></span></a>' : '', '</td>';
 
-		// ICQ?
-		if (!isset($context['disabled_fields']['icq']))
-			echo '
-					<td class="centertext">', $member['icq']['link'], '</td>';
-
-		// AIM?
-		if (!isset($context['disabled_fields']['aim']))
-			echo '
-					<td class="centertext">', $member['aim']['link'], '</td>';
-
-		// YIM?
-		if (!isset($context['disabled_fields']['yim']))
-			echo '
-					<td class="centertext">', $member['yim']['link'], '</td>';
-
-		// Skype?
-		if (!isset($context['disabled_fields']['skype']))
-			echo '
-					<td class="centertext">', $member['skype']['link'], '</td>';
-
 		// Group and date.
 		echo '
 					<td class="lefttext">', empty($member['group']) ? $member['post_group'] : $member['group'], '</td>

+ 327 - 0
Themes/default/ModerationCenter.template.php

@@ -320,6 +320,178 @@ function template_unapproved_posts()
 	</div>';
 }
 
+
+function template_viewmodreport()
+{
+	global $context, $scripturl, $txt;
+
+	echo '
+	<div id="modcenter">
+		<form action="', $scripturl, '?action=moderate;area=reports;report=', $context['report']['id'], '" method="post" accept-charset="', $context['character_set'], '">
+			<div class="cat_bar">
+				<h3 class="catbg">
+					', sprintf($txt['mc_viewmodreport'], $context['report']['message_link'], $context['report']['author']['link']), '
+				</h3>
+			</div>
+			<div class="title_bar">
+				<h3 class="titlebg">
+					<span class="floatleft">
+						', sprintf($txt['mc_modreport_summary'], $context['report']['num_reports'], $context['report']['last_updated']), '
+					</span>
+					<span class="floatright">';
+
+		// Make the buttons.
+		$close_button = create_button('close.png', $context['report']['closed'] ? 'mc_reportedp_open' : 'mc_reportedp_close', $context['report']['closed'] ? 'mc_reportedp_open' : 'mc_reportedp_close', 'class="centericon"');
+		$ignore_button = create_button('ignore.png', 'mc_reportedp_ignore', 'mc_reportedp_ignore', 'class="centericon"');
+		$unignore_button = create_button('ignore.png', 'mc_reportedp_unignore', 'mc_reportedp_unignore', 'class="centericon"');
+
+		echo '
+						<a href="', $scripturl, '?action=moderate;area=reports;ignore=', (int) !$context['report']['ignore'], ';rid=', $context['report']['id'], ';', $context['session_var'], '=', $context['session_id'], '" ', !$context['report']['ignore'] ? 'onclick="return confirm(\'' . $txt['mc_reportedp_ignore_confirm'] . '\');"' : '', '>', $context['report']['ignore'] ? $unignore_button : $ignore_button, '</a>
+						<a href="', $scripturl, '?action=moderate;area=reports;close=', (int) !$context['report']['closed'], ';rid=', $context['report']['id'], ';', $context['session_var'], '=', $context['session_id'], '">', $close_button, '</a>
+					</span>
+				</h3>
+			</div>
+			<div class="windowbg2">
+				<div class="content">
+					', $context['report']['body'], '
+				</div>
+			</div>
+			<br>
+			<div class="cat_bar">
+				<h3 class="catbg">', $txt['mc_modreport_whoreported_title'], '</h3>
+			</div>';
+
+	foreach ($context['report']['comments'] as $comment)
+		echo '
+			<div class="windowbg">
+				<div class="content">
+					<p class="smalltext">', sprintf($txt['mc_modreport_whoreported_data'], $comment['member']['link'] . (empty($comment['member']['id']) && !empty($comment['member']['ip']) ? ' (' . $comment['member']['ip'] . ')' : ''), $comment['time']), '</p>
+					<p>', $comment['message'], '</p>
+				</div>
+			</div>';
+
+	echo '
+			<br>
+			<div class="cat_bar">
+				<h3 class="catbg">', $txt['mc_modreport_mod_comments'], '</h3>
+			</div>';
+			
+		if (empty($context['report']['mod_comments']))
+		echo '
+				<div class="description">
+					<p class="centertext">', $txt['mc_modreport_no_mod_comment'], '</p>
+				</div>';
+	
+		echo '
+			<div class="windowbg2">
+				<div class="content">';
+
+	foreach ($context['report']['mod_comments'] as $comment)
+		echo
+					'<p>', $comment['member']['link'], ': ', $comment['message'], ' <em class="smalltext">(', $comment['time'], ')</em></p>';
+
+		echo '
+					<textarea rows="2" cols="60" style="' . (isBrowser('is_ie8') ? 'width: 635px; max-width: 60%; min-width: 60%' : 'width: 60%') . ';" name="mod_comment"></textarea>
+					<div>
+						<input type="submit" name="add_comment" value="', $txt['mc_modreport_add_mod_comment'], '" class="button_submit">
+					</div>
+				</div>
+			</div>
+			<br>';
+
+	$alt = false;
+
+	template_show_list('moderation_actions_list');
+
+	echo '
+			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '">
+		</form>
+	</div>';
+}
+
+function template_viewmemberreport()
+{
+	global $context, $scripturl, $txt;
+
+	echo '
+	<div id="modcenter">
+		<form action="', $scripturl, '?action=moderate;area=memberreports;report=', $context['report']['id'], '" method="post" accept-charset="', $context['character_set'], '">
+			<div class="cat_bar">
+				<h3 class="catbg">
+					', sprintf($txt['mc_viewmemberreport'], $context['report']['user']['link']), '
+				</h3>
+			</div>
+			<div class="title_bar">
+				<h3 class="titlebg">
+					<span class="floatleft">
+						', sprintf($txt['mc_memberreport_summary'], $context['report']['num_reports'], $context['report']['last_updated']), '
+					</span>
+					<span class="floatright">';
+
+		// Make the buttons.
+		$close_button = create_button('close.png', $context['report']['closed'] ? 'mc_reportedp_open' : 'mc_reportedp_close', $context['report']['closed'] ? 'mc_reportedp_open' : 'mc_reportedp_close', 'class="centericon"');
+		$ignore_button = create_button('ignore.png', 'mc_reportedp_ignore', 'mc_reportedp_ignore', 'class="centericon"');
+		$unignore_button = create_button('ignore.png', 'mc_reportedp_unignore', 'mc_reportedp_unignore', 'class="centericon"');
+
+		echo '
+						<a href="', $scripturl, '?action=moderate;area=memberreports;ignore=', (int) !$context['report']['ignore'], ';rid=', $context['report']['id'], ';', $context['session_var'], '=', $context['session_id'], '" ', !$context['report']['ignore'] ? 'onclick="return confirm(\'' . $txt['mc_reportedp_ignore_confirm'] . '\');"' : '', '>', $context['report']['ignore'] ? $unignore_button : $ignore_button, '</a>
+						<a href="', $scripturl, '?action=moderate;area=memberreports;close=', (int) !$context['report']['closed'], ';rid=', $context['report']['id'], ';', $context['session_var'], '=', $context['session_id'], '">', $close_button, '</a>
+					</span>
+				</h3>
+			</div>
+			<br>
+			<div class="cat_bar">
+				<h3 class="catbg">', $txt['mc_memberreport_whoreported_title'], '</h3>
+			</div>';
+
+	foreach ($context['report']['comments'] as $comment)
+		echo '
+			<div class="windowbg">
+				<div class="content">
+					<p class="smalltext">', sprintf($txt['mc_modreport_whoreported_data'], $comment['member']['link'] . (empty($comment['member']['id']) && !empty($comment['member']['ip']) ? ' (' . $comment['member']['ip'] . ')' : ''), $comment['time']), '</p>
+					<p>', $comment['message'], '</p>
+				</div>
+			</div>';
+
+	echo '
+			<br>
+			<div class="cat_bar">
+				<h3 class="catbg">', $txt['mc_modreport_mod_comments'], '</h3>
+			</div>';
+			
+		if (empty($context['report']['mod_comments']))
+		echo '
+				<div class="description">
+					<p class="centertext">', $txt['mc_modreport_no_mod_comment'], '</p>
+				</div>';
+	
+		echo '
+			<div class="windowbg2">
+				<div class="content">';
+
+	foreach ($context['report']['mod_comments'] as $comment)
+		echo
+					'<p>', $comment['member']['link'], ': ', $comment['message'], ' <em class="smalltext">(', $comment['time'], ')</em></p>';
+
+		echo '
+					<textarea rows="2" cols="60" style="' . (isBrowser('is_ie8') ? 'width: 635px; max-width: 60%; min-width: 60%' : 'width: 60%') . ';" name="mod_comment"></textarea>
+					<div>
+						<input type="submit" name="add_comment" value="', $txt['mc_modreport_add_mod_comment'], '" class="button_submit">
+					</div>
+				</div>
+			</div>
+			<br>';
+
+	$alt = false;
+
+	template_show_list('memreport_actions_list');
+
+	echo '
+			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '">
+		</form>
+	</div>';
+}
+
 // Callback function for showing a watched users post in the table.
 function template_user_watch_post_callback($post)
 {
@@ -539,4 +711,159 @@ function template_warn_template()
 	// ]]></script>';
 }
 
+// A block to show the current top reported member profiles.
+function template_reported_members_block()
+{
+	global $context, $txt, $scripturl;
+
+	echo '
+		<div class="cat_bar">
+			<h3 class="catbg">
+				<span id="reported_members_toggle" class="', !empty($context['admin_prefs']['mcru']) ? 'toggle_down' : 'toggle_up', ' floatright" style="display: none;"></span>
+				<a href="', $scripturl, '?action=moderate;area=memberreports" id="reported_members_link">', $txt['mc_recent_member_reports'], '</a>
+			</h3>
+		</div>
+		<div class="windowbg" id="reported_users_panel">
+			<div class="content modbox">
+				<ul class="reset">';
+
+		foreach ($context['reported_members'] as $report)
+			echo '
+					<li class="smalltext">
+						<a href="', $report['report_href'], '">', $report['user_name'], '</a>
+					</li>';
+
+		// Don't have any reported members right now?
+		if (empty($context['reported_members']))
+			echo '
+					<li>
+						<strong class="smalltext">', $txt['mc_recent_reports_none'], '</strong>
+					</li>';
+
+		echo '
+				</ul>
+			</div>
+		</div>
+		
+	<script><!-- // --><![CDATA[
+		var oReportedPostsPanelToggle = new smc_Toggle({
+			bToggleEnabled: true,
+			bCurrentlyCollapsed: ', !empty($context['admin_prefs']['mcrm']) ? 'true' : 'false', ',
+			aSwappableContainers: [
+				\'reported_posts_panel\'
+			],
+			aSwapImages: [
+				{
+					sId: \'reported_members_toggle\',
+					altExpanded: ', JavaScriptEscape($txt['hide']), ',
+					altCollapsed: ', JavaScriptEscape($txt['show']), '
+				}
+			],
+			aSwapLinks: [
+				{
+					sId: \'reported_members_link\',
+					msgExpanded: ', JavaScriptEscape($txt['mc_recent_member_reports']), ',
+					msgCollapsed: ', JavaScriptEscape($txt['mc_recent_member_reports']), '
+				}
+			],
+			oThemeOptions: {
+				bUseThemeSettings: true,
+				sOptionName: \'admin_preferences\',
+				sSessionVar: smf_session_var,
+				sSessionId: smf_session_id,
+				sThemeId: \'1\',
+				sAdditionalVars: \';admin_key=mcrm\'
+			}
+		});
+	// ]]></script>';
+}
+
+function template_reported_members()
+{
+	global $context, $txt, $scripturl;
+
+	// Let them know the action was a success.
+	if (!empty($context['report_post_action']) && !empty($txt['report_action_'. $context['report_post_action']]))
+	{
+		echo '
+			<div class="infobox">
+				', $txt['report_action_'. $context['report_post_action']], '
+			</div>';
+	}
+
+	echo '
+	<form id="reported_members" action="', $scripturl, '?action=moderate;area=memberreports', $context['view_closed'] ? ';sa=closed' : '', ';start=', $context['start'], '" method="post" accept-charset="', $context['character_set'], '">
+		<div class="cat_bar">
+			<h3 class="catbg">
+				', $context['view_closed'] ? $txt['mc_reportedp_closed'] : $txt['mc_reportedp_active'], '
+			</h3>
+		</div>
+		<div class="pagesection">
+			<div class="pagelinks">', $context['page_index'], '</div>
+		</div>';
+
+	// Make the buttons.
+	$close_button = create_button('close.png', $context['view_closed'] ? 'mc_reportedp_open' : 'mc_reportedp_close', $context['view_closed'] ? 'mc_reportedp_open' : 'mc_reportedp_close', 'class="centericon"');
+	$details_button = create_button('details.png', 'mc_reportedp_details', 'mc_reportedp_details', 'class="centericon"');
+	$ignore_button = create_button('ignore.png', 'mc_reportedp_ignore', 'mc_reportedp_ignore', 'class="centericon"');
+	$unignore_button = create_button('ignore.png', 'mc_reportedp_unignore', 'mc_reportedp_unignore', 'class="centericon"');
+	$ban_button = create_button('close.png', 'mc_reportedp_ban', 'mc_reportedp_ban', 'class="centericon"');
+
+	foreach ($context['reports'] as $report)
+	{
+		echo '
+		<div class="generic_list_wrapper ', $report['alternate'] ? 'windowbg' : 'windowbg2', '">
+			<div class="content">
+				<h5>
+					<strong><a href="', $report['user']['href'], '">', $report['user']['name'], '</a></strong>
+				</h5>
+				<div class="smalltext">
+					', $txt['mc_reportedp_last_reported'], ': ', $report['last_updated'], '&nbsp;-&nbsp;';
+
+		// Prepare the comments...
+		$comments = array();
+		foreach ($report['comments'] as $comment)
+			$comments[$comment['member']['id']] = $comment['member']['link'];
+
+		echo '
+					', $txt['mc_reportedp_reported_by'], ': ', implode(', ', $comments), '
+				</div>
+				<hr>
+				<ul class="quickbuttons">
+					<li><a href="', $report['report_href'], '">', $details_button, '</a></li>
+					<li><a href="', $scripturl, '?action=moderate;area=memberreports', $context['view_closed'] ? ';sa=closed' : '', ';ignore=', (int) !$report['ignore'], ';rid=', $report['id'], ';start=', $context['start'], ';', $context['session_var'], '=', $context['session_id'], '" ', !$report['ignore'] ? 'onclick="return confirm(\'' . $txt['mc_reportedp_ignore_confirm'] . '\');"' : '', '>', $report['ignore'] ? $unignore_button : $ignore_button, '</a></li>
+					<li><a href="', $scripturl, '?action=moderate;area=memberreports', $context['view_closed'] ? ';sa=closed' : '', ';close=', (int) !$report['closed'], ';rid=', $report['id'], ';start=', $context['start'], ';', $context['session_var'], '=', $context['session_id'], '">', $close_button, '</a></li>';
+
+		// Ban this user button.
+		if (!$report['closed'] && !empty($context['report_manage_bans']) && !empty($report['user']['id']))
+			echo '
+					<li><a href="', $scripturl, '?action=admin;area=ban;sa=add;u=', $report['user']['id'] ,';', $context['session_var'], '=', $context['session_id'], '">', $ban_button, '</a></li>';
+
+		echo '
+					<li>', !$context['view_closed'] ? '<input type="checkbox" name="close[]" value="' . $report['id'] . '" class="input_check">' : '', '</li>
+				</ul>
+			</div>
+		</div>';
+	}
+
+	// Were none found?
+	if (empty($context['reports']))
+		echo '
+		<div class="windowbg2">
+			<div class="content">
+				<p class="centertext">', $txt['mc_reportedp_none_found'], '</p>
+			</div>
+		</div>';
+
+	echo '
+		<div class="pagesection">
+			<div class="pagelinks floatleft">', $context['page_index'], '</div>
+			<div class="floatright">
+				', !$context['view_closed'] ? '<input type="submit" name="close_selected" value="' . $txt['mc_reportedp_close_selected'] . '" class="button_submit">' : '', '
+			</div>
+		</div>
+		<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '">
+	</form>';
+}
+
 ?>

+ 101 - 99
Themes/default/Packages.template.php

@@ -690,139 +690,141 @@ function template_servers()
 	echo '
 	<div id="admin_form_wrapper">
 		<div class="cat_bar">
-			<h3 class="catbg">', $txt['download_new_package'], '</h3>
-		</div>';
-
-	if ($context['package_download_broken'])
-	{
-		echo '
-		<div class="cat_bar">
-			<h3 class="catbg">', $txt['package_ftp_necessary'], '</h3>
+			<h3 class="catbg">' . $txt['package_upload_title'] . '</h3>
 		</div>
 		<div class="windowbg">
 			<div class="content">
-				<p>
-					', $txt['package_ftp_why_download'], '
-				</p>
-				<form action="', $scripturl, '?action=admin;area=packages;get" method="post" accept-charset="', $context['character_set'], '">
+				<form action="' . $scripturl . '?action=admin;area=packages;get;sa=upload" method="post" accept-charset="', $context['character_set'], '" enctype="multipart/form-data" style="margin-bottom: 0;">
 					<dl class="settings">
 						<dt>
-							<label for="ftp_server">', $txt['package_ftp_server'], ':</label>
-						</dt>
-						<dd>
-							<input type="text" size="30" name="ftp_server" id="ftp_server" value="', $context['package_ftp']['server'], '" class="input_text">
-							<label for="ftp_port">', $txt['package_ftp_port'], ':&nbsp;</label> <input type="text" size="3" name="ftp_port" id="ftp_port" value="', $context['package_ftp']['port'], '" class="input_text">
-						</dd>
-						<dt>
-							<label for="ftp_username">', $txt['package_ftp_username'], ':</label>
-						</dt>
-						<dd>
-							<input type="text" size="50" name="ftp_username" id="ftp_username" value="', $context['package_ftp']['username'], '" style="width: 99%;" class="input_text">
-						</dd>
-						<dt>
-							<label for="ftp_password">', $txt['package_ftp_password'], ':</label>
-						</dt>
-						<dd>
-							<input type="password" size="50" name="ftp_password" id="ftp_password" style="width: 99%;" class="input_password">
-						</dd>
-						<dt>
-							<label for="ftp_path">', $txt['package_ftp_path'], ':</label>
+							<strong>' . $txt['package_upload_select'] . ':</strong>
 						</dt>
 						<dd>
-							<input type="text" size="50" name="ftp_path" id="ftp_path" value="', $context['package_ftp']['path'], '" style="width: 99%;" class="input_text">
+							<input type="file" name="package" size="38" class="input_file">
 						</dd>
 					</dl>
-					<div class="righttext">
-						<input type="submit" value="', $txt['package_proceed'], '" class="button_submit">
-					</div>
+					<hr class="hrcolor">
+					<input type="submit" value="' . $txt['package_upload'] . '" class="button_submit">
+					<input type="hidden" name="' . $context['session_var'] . '" value="' . $context['session_id'] . '">
 				</form>
 			</div>
-		</div>';
-	}
+		</div>
+		<br>
+		<div class="cat_bar">
+			<h3 class="catbg"><a class="download_new_package">', $txt['download_new_package'], '</a></h3>
+		</div>
+		<div class="new_package_content">';
 
-	echo '
-		<div class="windowbg2">
-			<div class="content">
-				<fieldset>
-					<legend>' . $txt['package_servers'] . '</legend>
-					<ul class="package_servers">';
-	foreach ($context['servers'] as $server)
+	if ($context['package_download_broken'])
+	{
 		echo '
-						<li class="flow_auto">
-							<span class="floatleft">' . $server['name'] . '</span>
-							<span class="package_server floatright"><a href="' . $scripturl . '?action=admin;area=packages;get;sa=remove;server=' . $server['id'] . ';', $context['session_var'], '=', $context['session_id'], '">[ ' . $txt['delete'] . ' ]</a></span>
-							<span class="package_server floatright"><a href="' . $scripturl . '?action=admin;area=packages;get;sa=browse;server=' . $server['id'] . '">[ ' . $txt['package_browse'] . ' ]</a></span>
-						</li>';
-	echo '
-					</ul>
-				</fieldset>
-				<fieldset>
-					<legend>' . $txt['add_server'] . '</legend>
-					<form action="' . $scripturl . '?action=admin;area=packages;get;sa=add" method="post" accept-charset="', $context['character_set'], '">
+			<div class="cat_bar">
+				<h3 class="catbg">', $txt['package_ftp_necessary'], '</h3>
+			</div>
+			<div class="windowbg">
+				<div class="content">
+					<p>
+						', $txt['package_ftp_why_download'], '
+					</p>
+					<form action="', $scripturl, '?action=admin;area=packages;get" method="post" accept-charset="', $context['character_set'], '">
 						<dl class="settings">
 							<dt>
-								<strong>' . $txt['server_name'] . ':</strong>
+								<label for="ftp_server">', $txt['package_ftp_server'], ':</label>
 							</dt>
 							<dd>
-								<input type="text" name="servername" size="44" value="SMF" class="input_text">
+								<input type="text" size="30" name="ftp_server" id="ftp_server" value="', $context['package_ftp']['server'], '" class="input_text">
+								<label for="ftp_port">', $txt['package_ftp_port'], ':&nbsp;</label> <input type="text" size="3" name="ftp_port" id="ftp_port" value="', $context['package_ftp']['port'], '" class="input_text">
 							</dd>
 							<dt>
-								<strong>' . $txt['serverurl'] . ':</strong>
+								<label for="ftp_username">', $txt['package_ftp_username'], ':</label>
 							</dt>
 							<dd>
-								<input type="text" name="serverurl" size="44" value="http://" class="input_text">
+								<input type="text" size="50" name="ftp_username" id="ftp_username" value="', $context['package_ftp']['username'], '" style="width: 99%;" class="input_text">
 							</dd>
-						</dl>
-						<div class="righttext">
-							<input type="submit" value="' . $txt['add_server'] . '" class="button_submit">
-							<input type="hidden" name="' . $context['session_var'] . '" value="' . $context['session_id'] . '">
-						</div>
-					</form>
-				</fieldset>
-				<fieldset>
-					<legend>', $txt['package_download_by_url'], '</legend>
-					<form action="', $scripturl, '?action=admin;area=packages;get;sa=download;byurl;', $context['session_var'], '=', $context['session_id'], '" method="post" accept-charset="', $context['character_set'], '">
-						<dl class="settings">
 							<dt>
-								<strong>' . $txt['serverurl'] . ':</strong>
+								<label for="ftp_password">', $txt['package_ftp_password'], ':</label>
 							</dt>
 							<dd>
-								<input type="text" name="package" size="44" value="http://" class="input_text">
+								<input type="password" size="50" name="ftp_password" id="ftp_password" style="width: 99%;" class="input_password">
 							</dd>
 							<dt>
-								<strong>', $txt['package_download_filename'], ':</strong>
+								<label for="ftp_path">', $txt['package_ftp_path'], ':</label>
 							</dt>
 							<dd>
-								<input type="text" name="filename" size="44" class="input_text"><br>
-								<span class="smalltext">', $txt['package_download_filename_info'], '</span>
+								<input type="text" size="50" name="ftp_path" id="ftp_path" value="', $context['package_ftp']['path'], '" style="width: 99%;" class="input_text">
 							</dd>
 						</dl>
 						<div class="righttext">
-							<input type="submit" value="', $txt['download'], '" class="button_submit">
+							<input type="submit" value="', $txt['package_proceed'], '" class="button_submit">
 						</div>
 					</form>
-				</fieldset>
-			</div>
-		</div>
-		<br>
-		<div class="cat_bar">
-			<h3 class="catbg">' . $txt['package_upload_title'] . '</h3>
-		</div>
-		<div class="windowbg">
-			<div class="content">
-				<form action="' . $scripturl . '?action=admin;area=packages;get;sa=upload" method="post" accept-charset="', $context['character_set'], '" enctype="multipart/form-data" style="margin-bottom: 0;">
-					<dl class="settings">
-						<dt>
-							<strong>' . $txt['package_upload_select'] . ':</strong>
-						</dt>
-						<dd>
-							<input type="file" name="package" size="38" class="input_file">
-						</dd>
-					</dl>
-					<hr class="hrcolor">
-					<input type="submit" value="' . $txt['package_upload'] . '" class="button_submit">
-					<input type="hidden" name="' . $context['session_var'] . '" value="' . $context['session_id'] . '">
-				</form>
+				</div>
+			</div>';
+	}
+
+	echo '
+			<div class="windowbg2">
+				<div class="content">
+					<fieldset>
+						<legend>' . $txt['package_servers'] . '</legend>
+						<ul class="package_servers">';
+	foreach ($context['servers'] as $server)
+		echo '
+							<li class="flow_auto">
+								<span class="floatleft">' . $server['name'] . '</span>
+								<span class="package_server floatright"><a href="' . $scripturl . '?action=admin;area=packages;get;sa=remove;server=' . $server['id'] . ';', $context['session_var'], '=', $context['session_id'], '">[ ' . $txt['delete'] . ' ]</a></span>
+								<span class="package_server floatright"><a href="' . $scripturl . '?action=admin;area=packages;get;sa=browse;server=' . $server['id'] . '">[ ' . $txt['package_browse'] . ' ]</a></span>
+							</li>';
+	echo '
+						</ul>
+					</fieldset>
+					<fieldset>
+						<legend>' . $txt['add_server'] . '</legend>
+						<form action="' . $scripturl . '?action=admin;area=packages;get;sa=add" method="post" accept-charset="', $context['character_set'], '">
+							<dl class="settings">
+								<dt>
+									<strong>' . $txt['server_name'] . ':</strong>
+								</dt>
+								<dd>
+									<input type="text" name="servername" size="44" value="SMF" class="input_text">
+								</dd>
+								<dt>
+									<strong>' . $txt['serverurl'] . ':</strong>
+								</dt>
+								<dd>
+									<input type="text" name="serverurl" size="44" value="http://" class="input_text">
+								</dd>
+							</dl>
+							<div class="righttext">
+								<input type="submit" value="' . $txt['add_server'] . '" class="button_submit">
+								<input type="hidden" name="' . $context['session_var'] . '" value="' . $context['session_id'] . '">
+							</div>
+						</form>
+					</fieldset>
+					<fieldset>
+						<legend>', $txt['package_download_by_url'], '</legend>
+						<form action="', $scripturl, '?action=admin;area=packages;get;sa=download;byurl;', $context['session_var'], '=', $context['session_id'], '" method="post" accept-charset="', $context['character_set'], '">
+							<dl class="settings">
+								<dt>
+									<strong>' . $txt['serverurl'] . ':</strong>
+								</dt>
+								<dd>
+									<input type="text" name="package" size="44" value="http://" class="input_text">
+								</dd>
+								<dt>
+									<strong>', $txt['package_download_filename'], ':</strong>
+								</dt>
+								<dd>
+									<input type="text" name="filename" size="44" class="input_text"><br>
+									<span class="smalltext">', $txt['package_download_filename_info'], '</span>
+								</dd>
+							</dl>
+							<div class="righttext">
+								<input type="submit" value="', $txt['download'], '" class="button_submit">
+							</div>
+						</form>
+					</fieldset>
+				</div>
 			</div>
 		</div>
 	</div>';

+ 2 - 19
Themes/default/PersonalMessage.template.php

@@ -284,11 +284,6 @@ function template_folder()
 					<a href="', $scripturl, '?action=modifykarma;sa=applaud;uid=', $message['member']['id'], ';f=', $context['folder'], ';start=', $context['start'], $context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : '', ';pm=', $message['id'], ';', $context['session_var'], '=', $context['session_id'], '">', $modSettings['karmaApplaudLabel'], '</a> <a href="', $scripturl, '?action=modifykarma;sa=smite;uid=', $message['member']['id'], ';f=', $context['folder'], ';start=', $context['start'], $context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : '', ';pm=', $message['id'], ';', $context['session_var'], '=', $context['session_id'], '">', $modSettings['karmaSmiteLabel'], '</a>
 				</li>';
 
-				// Show the member's gender icon?
-				if (!empty($settings['show_gender']) && $message['member']['gender']['image'] != '' && !isset($context['disabled_fields']['gender']))
-					echo '
-				<li class="gender">', $txt['gender'], ': ', $message['member']['gender']['image'], '</li>';
-
 				// Show their personal text?
 				if (!empty($settings['show_blurb']) && $message['member']['blurb'] != '')
 					echo '
@@ -318,18 +313,6 @@ function template_folder()
 				</li>';
 				}
 
-				// This shows the popular messaging icons.
-				if ($message['member']['has_messenger'] && $message['member']['can_view_profile'])
-					echo '
-				<li class="im_icons">
-					<ol>
-						', !isset($context['disabled_fields']['icq']) && !empty($message['member']['icq']['link']) ? '<li>' . $message['member']['icq']['link'] . '</li>' : '', '
-						', !isset($context['disabled_fields']['skype']) && !empty($message['member']['skype']['link']) ? '<li>' . $message['member']['skype']['link'] . '</li>' : '', '
-						', !isset($context['disabled_fields']['aim']) && !empty($message['member']['aim']['link']) ? '<li>' . $message['member']['aim']['link'] . '</li>' : '', '
-						', !isset($context['disabled_fields']['yim']) && !empty($message['member']['yim']['link']) ? '<li>' . $message['member']['yim']['link'] . '</li>' : '', '
-					</ol>
-				</li>';
-
 				if ($message['can_report'])
 					echo '
 				<li class="report_link"><a href="' . $scripturl . '?action=pm;sa=report;l=' . $context['current_label_id'] . ';pmsg=' . $message['id'] . '">' . $txt['pm_report_to_admin'] . '</a></li>';
@@ -367,9 +350,9 @@ function template_folder()
 						<li><a href="', $message['member']['website']['url'], '" title="' . $message['member']['website']['title'] . '" target="_blank" class="new_win">', ($settings['use_image_buttons'] ? '<span class="generic_icons www centericon" title="' . $message['member']['website']['title'] . '"></span>' : $txt['www']), '</a></li>';
 
 					// Don't show the email address if they want it hidden.
-					if (in_array($message['member']['show_email'], array('yes', 'yes_permission_override', 'no_through_forum')) && $context['can_send_email'])
+					if ($message['member']['show_email'])
 						echo '
-						<li><a href="', $scripturl, '?action=emailuser;sa=email;uid=', $message['member']['id'], '" rel="nofollow">', ($settings['use_image_buttons'] ? '<span class="generic_icons mail centericon" title="' . $txt['email'] . '"></span>' : $txt['email']), '</a></li>';
+						<li><a href="mailto:', $message['member']['email'], '" rel="nofollow">', ($settings['use_image_buttons'] ? '<span class="generic_icons mail centericon" title="' . $txt['email'] . '"></span>' : $txt['email']), '</a></li>';
 
 					// Since we know this person isn't a guest, you *can* message them.
 					if ($context['can_send_pm'])

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

@@ -177,7 +177,7 @@ function template_main()
 
 	echo '
 							</select>
-							<img src="', $context['icon_url'], '" name="icons" hspace="15" alt="">
+							<img src="', $context['icon_url'], '" id="icons" alt="">
 						</dd>
 					</dl>';
 
@@ -443,7 +443,7 @@ function template_main()
 							</dt>
 							<dd class="smalltext">
 								', empty($modSettings['attachmentSizeLimit']) ? '' : ('<input type="hidden" name="MAX_FILE_SIZE" value="' . $modSettings['attachmentSizeLimit'] * 1028 . '">'), '
-								<input type="file" size="60" multiple="multiple" name="attachment[]" id="attachment1" class="input_file"> (<a href="javascript:void(0);" onclick="cleanFileInput(\'attachment1\');">', $txt['clean_attach'], '</a>)';
+								<input type="file" multiple="multiple" name="attachment[]" id="attachment1" class="input_file"> (<a href="javascript:void(0);" onclick="cleanFileInput(\'attachment1\');">', $txt['clean_attach'], '</a>)';
 
 			// Show more boxes if they aren't approaching that limit.
 			if ($context['num_allowed_attachments'] > 1)
@@ -459,7 +459,7 @@ function template_main()
 										if (allowed_attachments <= 0)
 											return alert("', $txt['more_attachments_error'], '");
 
-										setOuterHTML(document.getElementById("moreAttachments"), \'<dd class="smalltext"><input type="file" size="60" name="attachment[]" id="attachment\' + current_attachment + \'" class="input_file"> (<a href="javascript:void(0);" onclick="cleanFileInput(\\\'attachment\' + current_attachment + \'\\\');">', $txt['clean_attach'], '<\/a>)\' + \'<\/dd><dd class="smalltext" id="moreAttachments"><a href="#" onclick="addAttachment(); return false;">(', $txt['more_attachments'], ')<\' + \'/a><\' + \'/dd>\');
+										setOuterHTML(document.getElementById("moreAttachments"), \'<dd class="smalltext"><input type="file" name="attachment[]" id="attachment\' + current_attachment + \'" class="input_file"> (<a href="javascript:void(0);" onclick="cleanFileInput(\\\'attachment\' + current_attachment + \'\\\');">', $txt['clean_attach'], '<\/a>)\' + \'<\/dd><dd class="smalltext" id="moreAttachments"><a href="#" onclick="addAttachment(); return false;">(', $txt['more_attachments'], ')<\' + \'/a><\' + \'/dd>\');
 
 										return true;
 									}

+ 18 - 56
Themes/default/Profile.template.php

@@ -120,7 +120,7 @@ function template_alerts_popup()
 				</div>
 				<br class="clear">
 			</div>';
-		}	
+		}
 	}
 
 	echo '
@@ -164,11 +164,10 @@ function template_summary()
 				</div>
 				', $context['member']['avatar']['image'], '
 				<ul class="reset">';
-	// @TODO fix the <ul> when no fields are visible
-	// What about if we allow email only via the forum??
-	if ($context['member']['show_email'] === 'yes' || $context['member']['show_email'] === 'no_through_forum' || $context['member']['show_email'] === 'yes_permission_override' && $context['can_send_email'])
+	// Email is only visible if it's your profile or you have the moderate_forum permission
+	if ($context['member']['show_email'])
 		echo '
-					<li><a href="', $scripturl, '?action=emailuser;sa=email;uid=', $context['member']['id'], '" title="', $context['member']['show_email'] == 'yes' || $context['member']['show_email'] == 'yes_permission_override' ? $context['member']['email'] : '', '" rel="nofollow"><span class="generic_icons mail" title="' . $txt['email'] . '"></span></a></li>';
+					<li><a href="mailto:', $context['member']['email'], '" title="', $context['member']['email'], '" rel="nofollow"><span class="generic_icons mail" title="' . $txt['email'] . '"></span></a></li>';
 
 	// Don't show an icon if they haven't specified a website.
 	if ($context['member']['website']['url'] !== '' && !isset($context['disabled_fields']['website']))
@@ -185,10 +184,6 @@ function template_summary()
 	}
 
 	echo '
-				', !isset($context['disabled_fields']['icq']) && !empty($context['member']['icq']['link']) ? '<li>' . $context['member']['icq']['link'] . '</li>' : '', '
-				', !isset($context['disabled_fields']['skype']) && !empty($context['member']['skype']['link']) ? '<li>' . $context['member']['skype']['link'] . '</li>' : '', '
-				', !isset($context['disabled_fields']['aim']) && !empty($context['member']['aim']['link']) ? '<li>' . $context['member']['aim']['link'] . '</li>' : '', '
-				', !isset($context['disabled_fields']['yim']) && !empty($context['member']['yim']['link']) ? '<li>' . $context['member']['yim']['link'] . '</li>' : '', '
 			</ul>
 			<span id="userstatus">', $context['can_send_pm'] ? '<a href="' . $context['member']['online']['href'] . '" title="' . $context['member']['online']['text'] . '" rel="nofollow">' : '', $settings['use_image_buttons'] ? '<img src="' . $context['member']['online']['image_href'] . '" alt="' . $context['member']['online']['text'] . '" class="centericon">' : $context['member']['online']['label'], $context['can_send_pm'] ? '</a>' : '', $settings['use_image_buttons'] ? '<span class="smalltext"> ' . $context['member']['online']['label'] . '</span>' : '';
 
@@ -237,19 +232,11 @@ function template_summary()
 					<dt>', $txt['profile_posts'], ': </dt>
 					<dd>', $context['member']['posts'], ' (', $context['member']['posts_per_day'], ' ', $txt['posts_per_day'], ')</dd>';
 
-	if ($context['can_send_email'])
+	if ($context['member']['show_email'])
 	{
-		// Only show the email address fully if it's not hidden - and we reveal the email.
-		if ($context['member']['show_email'] == 'yes')
-			echo '
-						<dt>', $txt['email'], ': </dt>
-						<dd><a href="', $scripturl, '?action=emailuser;sa=email;uid=', $context['member']['id'], '">', $context['member']['email'], '</a></dd>';
-
-		// ... Or if the one looking at the profile is an admin they can see it anyway.
-		elseif ($context['member']['show_email'] == 'yes_permission_override')
-			echo '
-						<dt>', $txt['email'], ': </dt>
-						<dd><em><a href="', $scripturl, '?action=emailuser;sa=email;uid=', $context['member']['id'], '">', $context['member']['email'], '</a></em></dd>';
+		echo '
+					<dt>', $txt['email'], ': </dt>
+					<dd><a href="mailto:', $context['member']['email'], '">', $context['member']['email'], '</a></dd>';
 	}
 
 	if (!empty($modSettings['titlesEnable']) && !empty($context['member']['title']))
@@ -273,20 +260,10 @@ function template_summary()
 					<dt>', $modSettings['karmaLabel'], ' </dt>
 					<dd>+', $context['member']['karma']['good'], '/-', $context['member']['karma']['bad'], '</dd>';
 
-	if (!isset($context['disabled_fields']['gender']) && !empty($context['member']['gender']['name']))
-		echo '
-					<dt>', $txt['gender'], ': </dt>
-					<dd>', $context['member']['gender']['name'], '</dd>';
-
 	echo '
 					<dt>', $txt['age'], ':</dt>
 					<dd>', $context['member']['age'] . ($context['member']['today_is_birthday'] ? ' &nbsp; <img src="' . $settings['images_url'] . '/cake.png" alt="">' : ''), '</dd>';
 
-	if (!isset($context['disabled_fields']['location']) && !empty($context['member']['location']))
-		echo '
-					<dt>', $txt['location'], ':</dt>
-					<dd>', $context['member']['location'], '</dd>';
-
 	echo '
 				</dl>';
 
@@ -606,7 +583,6 @@ function template_editBuddies()
 	global $context, $settings, $scripturl, $modSettings, $txt;
 
 	$disabled_fields = isset($modSettings['disabled_profile_fields']) ? array_flip(explode(',', $modSettings['disabled_profile_fields'])) : array();
-	$buddy_fields = array('icq', 'aim', 'yim', 'skype');
 
 	if (!empty($context['saved_successful']))
 		echo '
@@ -626,18 +602,11 @@ function template_editBuddies()
 			<tr class="catbg">
 				<th class="first_th" scope="col" width="20%">', $txt['name'], '</th>
 				<th scope="col">', $txt['status'], '</th>';
-	if ($context['can_send_email'])
+
+	if (allowedTo('moderate_forum'))
 		echo '
 				<th scope="col">', $txt['email'], '</th>';
 
-	// don't show them if they are disabled
-	foreach ($buddy_fields as $key => $column)
-	{
-		if (!isset($disabled_fields[$column]))
-			echo '
-				<th scope="col">', $txt[$column], '</th>';
-	}
-
 	echo '
 				<th class="last_th" scope="col"></th>
 			</tr>';
@@ -657,9 +626,9 @@ function template_editBuddies()
 			<tr class="', $alternate ? 'windowbg' : 'windowbg2', '">
 				<td>', $buddy['link'], '</td>
 				<td align="center"><a href="', $buddy['online']['href'], '"><img src="', $buddy['online']['image_href'], '" alt="', $buddy['online']['text'], '" title="', $buddy['online']['text'], '"></a></td>';
-		if ($context['can_send_email'])
+		if ($buddy['show_email'])
 			echo '
-				<td align="center">', ($buddy['show_email'] == 'no' ? '' : '<a href="' . $scripturl . '?action=emailuser;sa=email;uid=' . $buddy['id'] . '" rel="nofollow"><span class="generic_icons mail icon" title="' . $txt['email'] . ' ' . $buddy['name'] . '"></span></a>'), '</td>';
+				<td align="center"><a href="mailto:' . $buddy['email'] . '" rel="nofollow"><span class="generic_icons mail icon" title="' . $txt['email'] . ' ' . $buddy['name'] . '"></span></a></td>';
 
 		// If these are off, don't show them
 		foreach ($buddy_fields as $key => $column)
@@ -745,15 +714,12 @@ function template_editIgnoreList()
 			<tr class="catbg">
 				<th class="first_th" scope="col" width="20%">', $txt['name'], '</th>
 				<th scope="col">', $txt['status'], '</th>';
-	if ($context['can_send_email'])
+
+	if (allowedTo('moderate_forum'))
 		echo '
 				<th scope="col">', $txt['email'], '</th>';
+
 	echo '
-				<th scope="col">', $txt['icq'], '</th>
-				<th scope="col">', $txt['aim'], '</th>
-				<th scope="col">', $txt['yim'], '</th>
-				<th scope="col">', $txt['skype'], '</th>
-				<th class="last_th" scope="col"></th>
 			</tr>';
 
 	// If they don't have anyone on their ignore list, don't list it!
@@ -771,14 +737,10 @@ function template_editIgnoreList()
 			<tr class="', $alternate ? 'windowbg' : 'windowbg2', '">
 				<td>', $member['link'], '</td>
 				<td align="center"><a href="', $member['online']['href'], '"><img src="', $member['online']['image_href'], '" alt="', $member['online']['text'], '" title="', $member['online']['text'], '"></a></td>';
-		if ($context['can_send_email'])
+		if ($member['show_email'])
 			echo '
-				<td align="center">', ($member['show_email'] == 'no' ? '' : '<a href="' . $scripturl . '?action=emailuser;sa=email;uid=' . $member['id'] . '" rel="nofollow"><span class="generic_icons mail icon" title="' . $txt['email'] . ' ' . $member['name'] . '"></span></a>'), '</td>';
+				<td align="center"><a href="mailto:' . $member['email'] . '" rel="nofollow"><span class="generic_icons mail icon" title="' . $txt['email'] . ' ' . $member['name'] . '"></span></a></td>';
 		echo '
-				<td align="center">', $member['icq']['link'], '</td>
-				<td align="center">', $member['aim']['link'], '</td>
-				<td align="center">', $member['yim']['link'], '</td>
-				<td align="center">', $member['skype']['link'], '</td>
 				<td align="center"><a href="', $scripturl, '?action=profile;u=', $context['id_member'], ';area=lists;sa=ignore;remove=', $member['id'], ';', $context['session_var'], '=', $context['session_id'], '"><span class="generic_icons delete" title="', $txt['ignore_remove'], '"></span></a></td>
 			</tr>';
 
@@ -1393,7 +1355,7 @@ function template_edit_options()
 				else
 					$type = $field['type'];
 				$step = $field['type'] == 'float' ? ' step="0.1"' : '';
-					
+
 
 				echo '
 							<input type="', $type, '" name="', $key, '" id="', $key, '" size="', empty($field['size']) ? 30 : $field['size'], '" value="', $field['value'], '" ', $field['input_attr'], ' class="input_', $field['type'] == 'password' ? 'password' : 'text', '"', $step, '>';

+ 6 - 0
Themes/default/Recent.template.php

@@ -25,6 +25,12 @@ function template_recent()
 			<span>', $context['page_index'], '</span>
 		</div>';
 
+	if (empty($context['posts']))
+	{
+		echo '
+			<div class="windowbg">', $txt['no_messages'], '</div>';
+	}
+
 	foreach ($context['posts'] as $post)
 	{
 		echo '

+ 105 - 0
Themes/default/ReportToMod.template.php

@@ -0,0 +1,105 @@
+<?php
+/**
+ * Simple Machines Forum (SMF)
+ *
+ * @package SMF
+ * @author Simple Machines http://www.simplemachines.org
+ * @copyright 2014 Simple Machines and individual contributors
+ * @license http://www.simplemachines.org/about/smf/license.php BSD
+ *
+ * @version 2.1 Alpha 1
+ */
+
+//------------------------------------------------------------------------------
+/*	This template contains two humble sub templates - main. Its job is pretty
+	simple: it collects the information we need to actually send the topic.
+
+	The report sub template gets shown from:
+		'?action=reporttm;topic=##.##;msg=##'
+		'?action=reporttm;u=#'
+	It should submit to:
+		'?action=reporttm;topic=' . $context['current_topic'] . '.' . $context['start']
+		'?action=reporttm;u=#'
+	It only needs to send the following fields:
+		comment: an additional comment to give the moderator.
+		sc: the session id, or $context['session_id'].
+*/
+
+function template_main()
+{
+	global $context, $txt, $scripturl;
+
+	// Want to see your master piece?
+	echo '
+	<div id="preview_section"', isset($context['preview_message']) ? '' : ' style="display: none;"', '>
+		<div class="cat_bar">
+			<h3 class="catbg">
+				<span>', $txt['preview'], '</span>
+			</h3>
+		</div>
+		<div class="windowbg">
+			<div class="content">
+				<div class="post" id="preview_body">
+					', empty($context['preview_message']) ? '<br>' : $context['preview_message'], '
+				</div>
+			</div>
+		</div>
+	</div><br>';
+
+	echo '
+	<div id="report_form">
+		<form action="', $context['submit_url'], '" method="post" accept-charset="', $context['character_set'], '">
+			<input type="hidden" name="', $context['report_type'], '" value="', $context['reported_item'], '">
+				<div class="cat_bar">
+					<h3 class="catbg">', $context['page_title'], '</h3>
+				</div>
+				<div class="windowbg">
+					<div class="content">';
+
+	if (!empty($context['post_errors']))
+	{
+		echo '
+						<div id="error_box" class="errorbox">
+							<ul id="error_list">';
+
+		foreach ($context['post_errors'] as $key => $error)
+			echo '
+								<li id="error_', $key, '" class="error">', $error, '</li>';
+
+		echo '
+							</ul>';
+	}
+	else
+		echo '
+							<div style="display:none" id="error_box" class="errorbox">';
+
+	echo '
+						</div>';
+
+	echo '
+						<p class="noticebox">', $context['notice'], '</p>
+						<br>
+						<dl class="settings" id="report_post">';
+
+	echo '
+							<dt>
+								<label for="report_comment">', $txt['enter_comment'], '</label>:
+							</dt>
+							<dd>
+								<textarea type="text" id="report_comment" name="comment" rows="5">', $context['comment_body'], '</textarea>
+							</dd>';
+
+	echo '
+						</dl>
+						<div class="flow_auto">
+							<input type="submit" name="preview" value="', $txt['preview'] , '" class="button_submit">
+							<input type="submit" name="save" value="', $txt['rtm10'], '" style="margin-left: 1ex;" class="button_submit">
+							<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '">
+						</div>
+					</div>
+				</div>
+		</form>
+	</div>';
+}
+
+?>

+ 0 - 197
Themes/default/SendTopic.template.php

@@ -1,197 +0,0 @@
-<?php
-/**
- * Simple Machines Forum (SMF)
- *
- * @package SMF
- * @author Simple Machines http://www.simplemachines.org
- * @copyright 2014 Simple Machines and individual contributors
- * @license http://www.simplemachines.org/about/smf/license.php BSD
- *
- * @version 2.1 Alpha 1
- */
-
-//------------------------------------------------------------------------------
-/*	This template contains two humble sub templates - main. Its job is pretty
-	simple: it collects the information we need to actually send the topic.
-
-	The report sub template gets shown from:
-		'?action=reporttm;topic=##.##;msg=##'
-	It should submit to:
-		'?action=reporttm;topic=' . $context['current_topic'] . '.' . $context['start']
-	It only needs to send the following fields:
-		comment: an additional comment to give the moderator.
-		sc: the session id, or $context['session_id'].
-*/
-
-// Send an email to a user!
-function template_custom_email()
-{
-	global $context, $txt, $scripturl;
-
-	echo '
-	<div id="send_topic">
-		<form action="', $scripturl, '?action=emailuser;sa=email" method="post" accept-charset="', $context['character_set'], '">
-			<div class="cat_bar">
-				<h3 class="catbg">
-					<span class="generic_icons mail icon"></span>', $context['page_title'], '
-				</h3>
-			</div>
-			<div class="windowbg">
-				<div class="content">
-					<dl class="settings send_mail">
-						<dt>
-							<strong>', $txt['sendtopic_receiver_name'], ':</strong>
-						</dt>
-						<dd>
-							', $context['recipient']['link'], '
-						</dd>';
-
-	// Can the user see the persons email?
-	if ($context['can_view_receipient_email'])
-		echo '
-						<dt>
-							<strong>', $txt['sendtopic_receiver_email'], ':</strong>
-						</dt>
-						<dd>
-							', $context['recipient']['email_link'], '
-						</dd>
-					</dl>
-					<hr>
-					<dl class="settings send_mail">';
-
-	// If it's a guest we need their details.
-	if ($context['user']['is_guest'])
-		echo '
-						<dt>
-							<label for="y_name"><strong>', $txt['sendtopic_sender_name'], ':</strong></label>
-						</dt>
-						<dd>
-							<input type="text" id="y_name" name="y_name" size="24" maxlength="40" value="', $context['user']['name'], '" class="input_text">
-						</dd>
-						<dt>
-							<label for="y_email"><strong>', $txt['sendtopic_sender_email'], ':</strong></label><br>
-							<span class="smalltext">', $txt['send_email_disclosed'], '</span>
-						</dt>
-						<dd>
-							<input type="email" id="y_mail" name="y_email" size="24" maxlength="50" value="', $context['user']['email'], '" class="input_text" required>
-						</dt>';
-	// Otherwise show the user that we know their email.
-	else
-		echo '
-						<dt>
-							<strong>', $txt['sendtopic_sender_email'], ':</strong><br>
-							<span class="smalltext">', $txt['send_email_disclosed'], '</span>
-						</dt>
-						<dd>
-							<em>', $context['user']['email'], '</em>
-						</dd>';
-
-	echo '
-						<dt>
-							<label for="email_subject"><strong>', $txt['send_email_subject'], ':</strong></label>
-						</dt>
-						<dd>
-							<input type="text" id="email_subject" name="email_subject" size="50" maxlength="100" class="input_text" required>
-						</dd>
-						<dt>
-							<label for="email_body"><strong>', $txt['message'], ':</strong></label>
-						</dt>
-						<dd>
-							<textarea id="email_body" name="email_body" rows="10" cols="20" style="' . (isBrowser('is_ie8') ? 'width: 635px; max-width: 90%; min-width: 90%' : 'width: 90%') . ';" required></textarea>
-						</dd>
-					</dl>
-					<hr class="hrcolor">
-					<div class="flow_auto">
-						<input type="submit" name="send" value="', $txt['sendtopic_send'], '" class="button_submit">
-					</div>
-				</div>
-			</div>';
-
-	foreach ($context['form_hidden_vars'] as $key => $value)
-		echo '
-			<input type="hidden" name="', $key, '" value="', $value, '">';
-
-	echo '
-			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '">
-		</form>
-	</div>';
-}
-
-function template_report()
-{
-	global $context, $txt, $scripturl;
-
-	// Want to see your master piece?
-	echo '
-	<div id="preview_section"', isset($context['preview_message']) ? '' : ' style="display: none;"', '>
-		<div class="cat_bar">
-			<h3 class="catbg">
-				<span>', $txt['preview'], '</span>
-			</h3>
-		</div>
-		<div class="windowbg">
-			<div class="content">
-				<div class="post" id="preview_body">
-					', empty($context['preview_message']) ? '<br>' : $context['preview_message'], '
-				</div>
-			</div>
-		</div>
-	</div><br>';
-
-	echo '
-	<div id="report_topic">
-		<form action="', $scripturl, '?action=reporttm;topic=', $context['current_topic'], '.', $context['start'], '" method="post" accept-charset="', $context['character_set'], '">
-			<input type="hidden" name="msg" value="' . $context['message_id'] . '">
-				<div class="cat_bar">
-					<h3 class="catbg">', $txt['report_to_mod'], '</h3>
-				</div>
-				<div class="windowbg">
-					<div class="content">';
-
-	if (!empty($context['post_errors']))
-	{
-	echo '
-				<div id="error_box" class="errorbox">
-					<ul id="error_list">';
-
-		foreach ($context['post_errors'] as $key => $error)
-			echo '
-						<li id="error_', $key, '" class="error">', $error, '</li>';
-
-		echo '
-					</ul>';
-	}
-	else
-		echo '
-				<div style="display:none" id="error_box" class="errorbox">';
-
-		echo '
-				</div>';
-
-	echo '
-						<p class="noticebox">', $txt['report_to_mod_func'], '</p>
-						<br>
-						<dl class="settings" id="report_post">';
-
-	echo '
-							<dt>
-								<label for="report_comment">', $txt['enter_comment'], '</label>:
-							</dt>
-							<dd>
-								<textarea type="text" id="report_comment" name="comment" rows="5">', $context['comment_body'], '</textarea>
-							</dd>';
-
-	echo '
-						</dl>
-						<div class="flow_auto">
-							<input type="submit" name="preview" value="', $txt['preview'] , '" class="button_submit">
-							<input type="submit" name="save" value="', $txt['rtm10'], '" style="margin-left: 1ex;" class="button_submit">
-							<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '">
-						</div>
-					</div>
-				</div>
-		</form>
-	</div>';
-}
-
-?>

+ 37 - 4
Themes/default/Themes.template.php

@@ -426,8 +426,25 @@ function template_set_options()
 							<br><span class="smalltext">', $setting['description'], '</span>';
 		echo '
 						</dt>
-						<dd ', $context['theme_options_reset'] ? 'style="width:40%"' : '', '>
-							<input type="text" name="', !empty($setting['default']) ? 'default_' : '', 'options[', $setting['id'], ']" id="options_', $setting['id'], '" value="', $setting['value'], '"', $setting['type'] == 'number' ? ' size="5"' : '', $context['theme_options_reset'] ? ' disabled' : '', ' class="input_text">';
+						<dd ', $context['theme_options_reset'] ? 'style="width:40%"' : '', '>';
+
+			if (isset($setting['type']) && $setting['type'] == 'number')
+			{
+				$min = isset($setting['min']) ? ' min="' . $setting['min'] . '"' : ' min="0"';
+				$max = isset($setting['max']) ? ' max="' . $setting['max'] . '"' : '';
+				$step = isset($setting['step']) ? ' step="' . $setting['step'] . '"' : '';
+
+				echo '
+							<input type="number"', $min . $max . $step;
+			}
+			else
+			{
+				echo '
+							<input type="text"';
+			}
+
+			
+			echo ' name="', !empty($setting['default']) ? 'default_' : '', 'options[', $setting['id'], ']" id="options_', $setting['id'], '" value="', $setting['value'], '"', $setting['type'] == 'number' ? ' size="5"' : '', $context['theme_options_reset'] ? ' disabled' : '', ' class="input_text">';
 		}
 
 		// end of this defintion
@@ -632,8 +649,24 @@ function template_set_settings()
 
 			echo '
 						</dt>
-						<dd>
-							<input type="text" name="', !empty($setting['default']) ? 'default_' : '', 'options[', $setting['id'], ']" id="', $setting['id'], '" value="', $setting['value'], '"', $setting['type'] == 'number' ? ' size="5"' : (empty($setting['size']) ? ' size="40"' : ' size="' . $setting['size'] . '"'), ' class="input_text">
+						<dd>';
+
+			if (isset($setting['type']) && $setting['type'] == 'number')
+			{
+				$min = isset($setting['min']) ? ' min="' . $setting['min'] . '"' : ' min="0"';
+				$max = isset($setting['max']) ? ' max="' . $setting['max'] . '"' : '';
+				$step = isset($setting['step']) ? ' step="' . $setting['step'] . '"' : '';
+
+				echo '
+							<input type="number"', $min . $max . $step;
+			}
+			else
+			{
+				echo '
+							<input type="text"';
+			}
+
+			echo ' name="', !empty($setting['default']) ? 'default_' : '', 'options[', $setting['id'], ']" id="options_', $setting['id'], '" value="', $setting['value'], '"', $setting['type'] == 'number' ? ' size="5"' : (empty($settings['size']) ? ' size="40"' : ' size="' . $setting['size'] . '"'), ' class="input_text">
 						</dd>';
 		}
 	}

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

@@ -59,13 +59,12 @@ function template_main()
 						<tr class="windowbg', $alternate ? '2' : '', '">
 							<td>';
 
-		// Guests don't have information like icq, skype, y!, and aim... and they can't be messaged.
+		// Guests can't be messaged.
 		if (!$member['is_guest'])
 		{
 			echo '
 								<span class="contact_info floatright">
 									', $context['can_send_pm'] ? '<a href="' . $member['online']['href'] . '" title="' . $member['online']['text'] . '">' : '', $settings['use_image_buttons'] ? '<img src="' . $member['online']['image_href'] . '" alt="' . $member['online']['text'] . '" align="bottom">' : $member['online']['label'], $context['can_send_pm'] ? '</a>' : '', '
-									', isset($context['disabled_fields']['icq']) ? '' : $member['icq']['link'] , ' ', isset($context['disabled_fields']['skype']) ? '' : $member['skype']['link'], ' ', isset($context['disabled_fields']['yim']) ? '' : $member['yim']['link'], ' ', isset($context['disabled_fields']['aim']) ? '' : $member['aim']['link'], '
 								</span>';
 		}
 

+ 199 - 0
Themes/default/css/calendar.css

@@ -0,0 +1,199 @@
+/* Styles for the calendar section.
+------------------------------------------------- */
+#calendar {
+	overflow: hidden;
+}
+/* Used to indicate the current day in the grid. */
+#main_grid .calendar_today span.day_text, #month_grid .calendar_today, .calendar_week tr.days_wrapper td.calendar_today:first-child {
+	font-weight: bold;
+}
+.calendar_today, td.days:hover {
+	background: #fff;
+}
+#month_grid {
+	width: 284px;
+	float: left;
+	text-align: center;
+	overflow: hidden;
+	margin-right: 1%;
+}
+#month_grid h3 a {
+	padding: 0 6px 0 6px;
+}
+#month_grid table {
+	width: 100%;
+	margin-bottom: 12px;
+	border-collapse: collapse;
+	background: #f0f4f7;
+	border: 1px solid #ccc;
+}
+#main_grid {
+	overflow: auto;
+}
+#main_grid table {
+	width: 99.9%;
+	border-collapse: collapse;
+	background: #f0f4f7;
+	margin: 1px 0 0 0;
+	border: 1px solid #ccc;
+	overflow: auto;
+	-moz-box-sizing: border-box; box-sizing: border-box; -webkit-box-sizing: border-box;
+	margin-left: 1px;
+}
+#main_grid .cat_bar {
+	border-radius: 5px 5px 0 0;
+	margin: 0 0 0 1px;
+}
+#month_grid table th:first-child {
+	background: #e7eaef;
+}
+#month_grid table th.days {
+	background: #e7eaef;
+}
+#month_grid table th.days, #month_grid table td.weeks {
+	padding: 5px;
+	text-align: center;
+}
+#month_grid table td.weeks {
+	font-size: large;
+	background: #e7eaef;
+}
+#month_grid td.weeks a:hover {
+	text-decoration: underline;
+}
+#month_grid h3.catbg, #main_grid h3.catbg {
+	padding: 8px 6px 4px 6px;
+}
+#main_grid h3.catbg span {
+	display: block;
+	font-size: 1.5em;
+	margin: -3px 4px 0 4px;
+}
+#main_grid table th:first-child {
+	background: #e7eaef;
+}
+#main_grid table th.days {
+	width: 14%;
+	padding: 10px;
+	text-align: left;
+	background: #e7eaef;
+}
+#main_grid table td.weeks {
+	text-align: center;
+	font-weight: bold;
+	font-size: 1.8em;
+	background: #e7eaef;
+}
+#main_grid table td.weeks a:hover {
+	text-decoration: none;
+}
+/* Main Highlighting */
+#main_grid table td.disabled, #month_grid table td.disabled {
+	background: rgba(238, 238, 238, 1.0);
+}
+#main_grid table td.events, #month_grid table td.events {
+	background: rgba(30, 245, 20, 0.1);
+}
+#main_grid table td.holidays, #month_grid table td.holidays {
+	background: rgba(23, 110, 245, 0.1);
+}
+#main_grid table td.birthdays, #month_grid table td.birthdays {
+	background: rgba(102, 0, 255, 0.1);
+}
+/* Special Case Highlighting */
+#main_grid table td.events:hover, #month_grid table td.events:hover, #month_grid table td.calendar_today.events {
+	background: rgba(30, 245, 20, 0.2);
+}
+#main_grid table td.holidays:hover, #month_grid table td.holidays:hover, #month_grid table td.calendar_today.holidays {
+	background: rgba(23, 110, 245, 0.2);
+}
+#main_grid table td.birthdays:hover, #month_grid table td.birthdays:hover, #month_grid table td.calendar_today.birthdays {
+	background: rgba(153, 51, 255, 0.2);
+}
+#main_grid table td.days, #month_grid table td.days {
+	vertical-align: top;
+	text-align: left;
+	border-right: 1px solid #ccc;
+	border-bottom: 1px solid #ccc;
+}
+#main_grid table td.days {
+	padding: 10px;
+}
+#month_grid table td.days {
+	padding: 5px;
+	width: 14.28%;
+	text-align: center;
+}
+#main_grid table tbody tr:nth-child(2) td.days, #month_grid table tbody tr:nth-child(2) {
+	border-top: 1px solid #ccc;
+}
+#main_grid table tbody tr.days_wrapper > td:nth-child(2), #month_grid table tr.days_wrapper > td:nth-child(2) {
+	border-left: 1px solid #ccc;
+}
+#main_grid table tr.days_wrapper:nth-child(2) > td.weeks {
+	border-top: 1px solid #ccc;
+}
+#main_grid table:last-child td.weeks {
+	border-bottom: 1px solid #ccc;
+}
+#main_grid td#post_event {
+	background: #e7eaef;
+	text-align: center;
+	padding-top: 12px;
+	margin-right: 0;
+}
+#main_grid img.calendar_icon {
+	float: left;
+	width: 16px;
+	margin: 2px 2px;
+}
+#main_grid .act_day {
+	font-size: 12pt;
+}
+#main_grid .active_post_event > a {
+	color: #999;
+}
+div.week_month_title {
+	font-weight: bold;
+	font-size: xx-large;
+	margin: 10px 0 12px 2px;
+}
+div.week_month_title a {
+	color: #555;
+}
+td.week_post {
+	vertical-align: middle !important;
+}
+div.week_add_event {
+	text-align: center;
+}
+div.week_add_event > a {
+	font-size: x-large;
+	color: #999;
+}
+div.week_add_event > a:hover {
+	color: #555;
+}
+span.hidelink {
+	font-style: italic;
+}
+#view_button {
+	margin-top: -2px;
+}
+/* Cheat and match this to the submit button. */
+#main_grid .buttonlist {
+	margin: -4px 12px 0 0;
+}
+#month_grid .compact {
+	padding: 2px;
+}
+#month_grid .comfortable {
+	padding: 5px;
+}
+#main_grid .compact, .calendar_week .compact {
+	height: 45px;
+}
+#main_grid .comfortable, .calendar_week .comfortable {
+	height: 100px;
+	padding: 10px;
+}

+ 24 - 0
Themes/default/css/calendar.rtl.css

@@ -0,0 +1,24 @@
+/* Styles for the calendar section.
+------------------------------------------------- */
+#main_grid .cat_bar {
+	margin: 0 0 0 2px;
+}
+#month_grid {
+	float: right;
+	margin: 0 0 0 1%;
+}
+#main_grid table.weeklist td.windowbg {
+
+	border-left: 2px solid #fff;
+	border-bottom: 2px solid #fff;
+}
+#main_grid img.calendar_icon {
+	float: right;
+	margin: 0 0 0 4px;
+}
+#main_grid table.weeklist td.weekdays {
+	text-align: left;
+	vertical-align: middle;
+	border-right: 2px solid #fff;
+	border-bottom: 2px solid #fff;
+}

+ 5 - 207
Themes/default/css/index.css

@@ -1274,9 +1274,6 @@ img.sort, .sort {
 	content: "";
 	background: url(../images/admin/subsection.png) no-repeat;
 }
-.dropmenu li li.subsections li a:after, .adm_section .dropmenu li.subsections li a:after{
-	display: none;
-}
 /* Highlighting of current section */
 .dropmenu li li a.chosen {
 	font-weight: bold;
@@ -2719,16 +2716,16 @@ dl.send_mail dd {
 	width: 64%;
 }
 
-/* Styles for the report topic section.
+/* Styles for the report topic/user section.
 ---------------------------------------------------- */
 
-#report_topic dl {
+#report_form dl {
 	margin-bottom: 0;
 }
-#report_topic dl.settings dt {
+#report_form dl.settings dt {
 	width: 20%;
 }
-#report_topic dl.settings dd {
+#report_form dl.settings dd {
 	width: 79%;
 }
 #report_comment {
@@ -3606,206 +3603,6 @@ dl.addrules dt.floatleft {
 	margin-right:10px;
 }
 
-/* Styles for the calendar section.
-------------------------------------------------- */
-#calendar {
-	overflow: hidden;
-}
-/* Used to indicate the current day in the grid. */
-#main_grid .calendar_today span.day_text, #month_grid .calendar_today, .calendar_week tr.days_wrapper td.calendar_today:first-child {
-	font-weight: bold;
-}
-.calendar_today, td.days:hover {
-	background: #fff;
-}
-#month_grid {
-	width: 284px;
-	float: left;
-	text-align: center;
-	overflow: hidden;
-	margin-right: 1%;
-}
-#month_grid h3 a {
-	padding: 0 6px 0 6px;
-}
-#month_grid table {
-	width: 100%;
-	margin-bottom: 12px;
-	border-collapse: collapse;
-	background: #f0f4f7;
-	border: 1px solid #ccc;
-}
-#main_grid {
-	overflow: auto;
-}
-#main_grid table {
-	width: 99.9%;
-	border-collapse: collapse;
-	background: #f0f4f7;
-	margin: 1px 0 0 0;
-	border: 1px solid #ccc;
-	overflow: auto;
-	-moz-box-sizing: border-box; box-sizing: border-box; -webkit-box-sizing: border-box;
-	margin-left: 1px;
-}
-#main_grid .cat_bar {
-	border-radius: 5px 5px 0 0;
-	margin: 0 0 0 1px;
-}
-#month_grid table th:first-child {
-	background: #e7eaef;
-}
-#month_grid table th.days {
-	background: #e7eaef;
-}
-#month_grid table th.days, #month_grid table td.weeks {
-	padding: 5px;
-	text-align: center;
-}
-#month_grid table td.weeks {
-	font-size: large;
-	background: #e7eaef;
-}
-#month_grid td.weeks a:hover {
-	text-decoration: underline;
-}
-#month_grid h3.catbg, #main_grid h3.catbg {
-	padding: 8px 6px 4px 6px;
-}
-#main_grid h3.catbg span {
-	display: block;
-	font-size: 1.5em;
-	margin: -3px 4px 0 4px;
-}
-#main_grid table th:first-child {
-	background: #e7eaef;
-}
-#main_grid table th.days {
-	width: 14%;
-	padding: 10px;
-	text-align: left;
-	background: #e7eaef;
-}
-#main_grid table td.weeks {
-	text-align: center;
-	font-weight: bold;
-	font-size: 1.8em;
-	background: #e7eaef;
-}
-#main_grid table td.weeks a:hover {
-	text-decoration: none;
-}
-/* Main Highlighting */
-#main_grid table td.disabled, #month_grid table td.disabled {
-	background: rgba(238, 238, 238, 1.0);
-}
-#main_grid table td.events, #month_grid table td.events {
-	background: rgba(30, 245, 20, 0.1);
-}
-#main_grid table td.holidays, #month_grid table td.holidays {
-	background: rgba(23, 110, 245, 0.1);
-}
-#main_grid table td.birthdays, #month_grid table td.birthdays {
-	background: rgba(102, 0, 255, 0.1);
-}
-/* Special Case Highlighting */
-#main_grid table td.events:hover, #month_grid table td.events:hover, #month_grid table td.calendar_today.events {
-	background: rgba(30, 245, 20, 0.2);
-}
-#main_grid table td.holidays:hover, #month_grid table td.holidays:hover, #month_grid table td.calendar_today.holidays {
-	background: rgba(23, 110, 245, 0.2);
-}
-#main_grid table td.birthdays:hover, #month_grid table td.birthdays:hover, #month_grid table td.calendar_today.birthdays {
-	background: rgba(153, 51, 255, 0.2);
-}
-#main_grid table td.days, #month_grid table td.days {
-	vertical-align: top;
-	text-align: left;
-	border-right: 1px solid #ccc;
-	border-bottom: 1px solid #ccc;
-}
-#main_grid table td.days {
-	padding: 10px;
-}
-#month_grid table td.days {
-	padding: 5px;
-	width: 14.28%;
-	text-align: center;
-}
-#main_grid table tbody tr:nth-child(2) td.days, #month_grid table tbody tr:nth-child(2) {
-	border-top: 1px solid #ccc;
-}
-#main_grid table tbody tr.days_wrapper > td:nth-child(2), #month_grid table tr.days_wrapper > td:nth-child(2) {
-	border-left: 1px solid #ccc;
-}
-#main_grid table tr.days_wrapper:nth-child(2) > td.weeks {
-	border-top: 1px solid #ccc;
-}
-#main_grid table:last-child td.weeks {
-	border-bottom: 1px solid #ccc;
-}
-#main_grid td#post_event {
-	background: #e7eaef;
-	text-align: center;
-	padding-top: 12px;
-	margin-right: 0;
-}
-#main_grid img.calendar_icon {
-	float: left;
-	width: 16px;
-	margin: 2px 2px;
-}
-#main_grid .act_day {
-	font-size: 12pt;
-}
-#main_grid .active_post_event > a {
-	color: #999;
-}
-div.week_month_title {
-	font-weight: bold;
-	font-size: xx-large;
-	margin: 10px 0 12px 2px;
-}
-div.week_month_title a {
-	color: #555;
-}
-td.week_post {
-	vertical-align: middle !important;
-}
-div.week_add_event {
-	text-align: center;
-}
-div.week_add_event > a {
-	font-size: x-large;
-	color: #999;
-}
-div.week_add_event > a:hover {
-	color: #555;
-}
-span.hidelink {
-	font-style: italic;
-}
-#view_button {
-	margin-top: -2px;
-}
-/* Cheat and match this to the submit button. */
-#main_grid .buttonlist {
-	margin: -4px 12px 0 0;
-}
-#month_grid .compact {
-	padding: 2px;
-}
-#month_grid .comfortable {
-	padding: 5px;
-}
-#main_grid .compact, .calendar_week .compact {
-	height: 45px;
-}
-#main_grid .comfortable, .calendar_week .comfortable {
-	height: 100px;
-	padding: 10px;
-}
-
 /* Styles for the memberlist section.
 ------------------------------------------------- */
 #mlist_search {
@@ -3951,6 +3748,7 @@ span.hidelink {
 	width: 100%;
 	height: 100%;
 	background: rgba(40,64,80,0.5);
+	z-index: 3;
 }
 .popup_window
 {

+ 0 - 25
Themes/default/css/rtl.css

@@ -749,31 +749,6 @@ tr.windowbg2 th.stats_month, tr.windowbg2 td.stats_day {
 	text-align: right;
 }
 
-/* Styles for the calendar section.
-------------------------------------------------- */
-#main_grid .cat_bar {
-	margin: 0 0 0 2px;
-}
-#month_grid {
-	float: right;
-	margin: 0 0 0 1%;
-}
-#main_grid table.weeklist td.windowbg {
-
-	border-left: 2px solid #fff;
-	border-bottom: 2px solid #fff;
-}
-#main_grid img.calendar_icon {
-	float: right;
-	margin: 0 0 0 4px;
-}
-#main_grid table.weeklist td.weekdays {
-	text-align: left;
-	vertical-align: middle;
-	border-right: 2px solid #fff;
-	border-bottom: 2px solid #fff;
-}
-
 /* Styles for the advanced search section.
 ------------------------------------------------- */
 #searchform fieldset {

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

@@ -133,7 +133,7 @@ $txt['security_wrong'] = 'Administration login attempt!' . "\n" . 'Referer: %1$s
 $txt['email_preview_warning'] = 'The preview is not 100% accurate. In order to preserve the functionality of the page only the basic html tags are represented';
 $txt['email_as_html'] = 'Send in HTML format.  (with this you can put normal HTML in the email.)';
 $txt['email_parsed_html'] = 'Add &lt;br /&gt;s and &amp;nbsp;s to this message.';
-$txt['email_variables'] = 'In this message you can use a few &quot;variables&quot;.  Click <a href="' . $scripturl . '?action=helpadmin;help=emailmembers" onclick="return reqOverlayDiv(this.href);" class="help">here</a> for more information.';
+$txt['email_variables'] = 'In this message you can use a few &quot;variables&quot;.  Click <a href="' . $scripturl . '?action=helpadmin;help=email_members" onclick="return reqOverlayDiv(this.href);" class="help">here</a> for more information.';
 $txt['email_force'] = 'Send this to members even if they have chosen not to receive announcements.';
 $txt['email_as_pms'] = 'Send this to these groups using personal messages.';
 $txt['email_continue'] = 'Continue';
@@ -283,7 +283,6 @@ $txt['activated'] = 'Activated';
 $txt['not_activated'] = 'Not activated';
 $txt['primary'] = 'Primary';
 $txt['additional'] = 'Additional';
-$txt['messenger_address'] = 'Messenger Address';
 $txt['wild_cards_allowed'] = 'wildcard characters * and ? are allowed';
 $txt['search_for'] = 'Search for';
 $txt['search_match'] = 'Match';
@@ -444,6 +443,7 @@ $txt['attachment_transfer_progress'] = 'Please wait. Transfer in progess.';
 
 $txt['mods_cat_avatars'] = 'Avatars';
 $txt['avatar_directory'] = 'Avatars directory';
+$txt['avatar_directory_wrong'] = 'The Avatars directory is not valid. This will cause several issues with your forum.';
 $txt['avatar_url'] = 'Avatars URL';
 $txt['avatar_max_width_external'] = 'Maximum width of external avatar';
 $txt['avatar_max_height_external'] = 'Maximum height of external avatar';
@@ -467,6 +467,7 @@ $txt['avatar_select_permission'] = 'Select permissions for each group';
 $txt['avatar_download_external'] = 'Download avatar at given URL';
 $txt['option_attachment_dir'] = 'Attachment directory';
 $txt['option_specified_dir'] = 'Specific directory...';
+$txt['custom_avatar_dir_wrong'] = 'The Attachments directory is not valid. This will prevent attachments from working properly.';
 $txt['custom_avatar_dir'] = 'Upload directory';
 $txt['custom_avatar_dir_desc'] = 'This should be a valid and writable directory, different than the server-stored directory.';
 $txt['custom_avatar_url'] = 'Upload URL';
@@ -607,6 +608,7 @@ $txt['could_not_language_backup'] = 'A backup could not be made before removing
 $txt['advanced'] = 'Advanced';
 $txt['simple'] = 'Simple';
 
+$txt['admin_news_newsletter_queue_done'] = 'The newsletter has been added to the mail queue successfully.';
 $txt['admin_news_select_recipients'] = 'Please select who should receive a copy of the newsletter';
 $txt['admin_news_select_group'] = 'Membergroups';
 $txt['admin_news_select_group_desc'] = 'Select the groups to receive this newsletter.';

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

@@ -12,6 +12,8 @@ $txt['alerts_no_unread'] = 'No unread alerts.';
 $txt['alert_msg_like'] = '{member_link} liked your post {msg_msg}';
 $txt['alert_msg_report'] = '{member_link} <a href="{scripturl}{report_link}">reported a post</a> - {msg_msg}';
 $txt['alert_msg_report_reply'] = '{member_link} replied to <a href="{scripturl}{report_link}">the report</a> about {msg_msg}';
+$txt['alert_profile_report'] = '{member_link} <a href="{scriptur}{report_link}">reported</a> the profile of {profile_msg}';
+$txt['alert_profile_report_reply'] = '{member_link} replied to <a href="{scripturl}{report_link}">the report</a> about the profile of {profile_msg}';
 $txt['alert_member_register_standard'] = '{member_link} just signed up';
 $txt['alert_member_register_approval'] = '{member_link} just signed up (account requires approval)';
 $txt['alert_member_register_activation'] = '{member_link} just signed up (account requires activation)';

+ 36 - 0
Themes/default/languages/EmailTemplates.english.php

@@ -458,6 +458,42 @@ Moderation center: {REPORTLINK}
 
 {REGARDS}';
 
+/**
+	@additional_params: report_user_profile
+		MEMBERNAME: The display name of the reported user
+		REPORTERNAME: The name of the person reporting the profile
+		PROFILELINK: The link to the profile that was reported
+		COMMENT: The comment left by the reporter.
+ 	@description: When a user's profile is reported
+*/
+$txt['report_member_profile_subject'] = 'Reported profile: {MEMBERNAME}';
+$txt['report_member_profile_body'] = 'The profile of "{MEMBERNAME}" has been reported by {REPORTERNAME}.
+
+The profile: {PROFILELINK}
+Moderation center: {REPORTLINK}
+
+The reporter has made the following comment:
+{COMMENT}
+
+{REGARDS}';
+
+/**
+	@additional_params: report_user_profile
+		MEMBERNAME: The display name of the reported user
+		COMMENTERNAME: The name of the person who added the comment
+		PROFILELINK: The link to the profile that was reported
+ 	@description: When someone replies to a report about a profile, this can be sent to others who replied
+*/
+$txt['reply_to_member_report_subject'] = 'Follow-up to reported profile: {MEMBERNAME}';
+$txt['reply_to_member_report_body'] = 'Previously, the profile of {MEMBERNAME} was reported.
+
+Since then, {COMMENTERNAME} has added a comment to the report. More information can be found in the forum.
+
+The profile: {PROFILELINK}
+Moderation center: {REPORTLINK}
+
+{REGARDS}';
+
 /**
 	@additional_params: change_password
 		USERNAME: The user name for the member receiving the email.

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

@@ -314,7 +314,7 @@ $txt['error_invalid_search_string'] = 'Did you forget to put something to search
 $txt['error_invalid_search_string_blacklist'] = 'Your search query contained too trivial words. Please try again with a different query.';
 $txt['error_search_string_small_words'] = 'Each word must be at least two characters long.';
 $txt['error_query_not_specific_enough'] = 'Your search query didn\'t return any matches.';
-$txt['error_no_messages_in_time_frame'] = 'No messages found in selected time frame.';
+$txt['error_no_messages_in_time_frame'] = 'No posts found in selected time frame.';
 $txt['error_no_labels_selected'] = 'No labels were selected.';
 $txt['error_no_search_daemon'] = 'Unable to access the search daemon';
 
@@ -340,7 +340,6 @@ $txt['profile_error_password_chars'] = 'Your password must contain a mix of uppe
 $txt['profile_error_already_requested_group'] = 'You already have an outstanding request for this group!';
 $txt['profile_error_openid_in_use'] = 'Another user is already using that OpenID authentication URL';
 $txt['profile_error_signature_not_yet_saved'] = 'The signature has not been saved.';
-$txt['profile_error_aim_too_long'] = 'The AIM nickname is too long.';
 $txt['profile_error_personal_text_too_long'] = 'The personal text is too long.';
 $txt['profile_error_user_title_too_long'] = 'The custom title is too long.';
 

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

@@ -377,7 +377,7 @@ $helptxt['securityDisable'] = 'This <em>disables</em> the additional password ch
 $helptxt['securityDisable_why'] = 'This is your current password. (the same one you use to login.)<br><br>Having to type this helps ensure that you want to do whatever administration you are doing, and that it is <strong>you</strong> doing it.';
 $helptxt['securityDisable_moderate'] = 'This <em>disables</em> the additional password check for the moderation section. This is not recommended!';
 $helptxt['securityDisable_moderate_why'] = 'This is your current password. (the same one you use to login.)<br><br>Having to type this helps ensure that you want to do whatever moderation you are doing, and that it is <strong>you</strong> doing it.';
-$helptxt['emailmembers'] = 'In this message you can use a few &quot;variables&quot;.  These are:<br>
+$helptxt['email_members'] = 'In this message you can use a few &quot;variables&quot;.  These are:<br>
 	{$board_url} - The URL to your forum.<br>
 	{$current_time} - The current time.<br>
 	{$member.email} - The current member\'s email.<br>

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

@@ -130,6 +130,8 @@ $txt['db_settings_password_info'] = 'Here, put the password you need to connect
 $txt['db_settings_database'] = 'Database name';
 $txt['db_settings_database_info'] = 'Fill in the name of the database you want to use for SMF to store its data in.';
 $txt['db_settings_database_info_note'] = 'If this database does not exist, this installer will try to create it.';
+$txt['db_settings_port'] = 'Database port';
+$txt['db_settings_port_info'] = 'Leave blank to use the default';
 $txt['db_settings_database_file'] = 'Database filename';
 $txt['db_settings_database_file_info'] = 'This is the name of the file in which to store the SMF data. We recommend you use the randomly generated name for this and set the path of this file to be outside of the public area of your webserver.';
 $txt['db_settings_prefix'] = 'Table prefix';

+ 5 - 2
Themes/default/languages/ManagePermissions.english.php

@@ -43,8 +43,8 @@ $txt['permissionname_profile_forum'] = 'Allow Forum Profile edits';
 $txt['permissionhelp_profile_forum'] = 'This option will allow a member to edit their Forum Profile';
 $txt['permissionname_profile_forum_own'] = 'Own profile';
 $txt['permissionname_profile_forum_any'] = 'Any profile';
-$txt['permissionname_profile_other'] = 'Edit website and location';
-$txt['permissionhelp_profile_other'] = 'Allow the member to edit the website, and location fields in their profile';
+$txt['permissionname_profile_other'] = 'Edit website';
+$txt['permissionhelp_profile_other'] = 'Allow the member to edit the website fields in their profile';
 $txt['permissionname_profile_other_own'] = 'Own profile';
 $txt['permissionname_profile_other_any'] = 'Any profile';
 $txt['permissionname_profile_blurb'] = 'Edit personal text';
@@ -183,6 +183,9 @@ $txt['permissionhelp_profile_remove'] = 'This permission allows a user to delete
 $txt['permissionname_profile_remove_own'] = 'Own account';
 $txt['permissionname_profile_remove_any'] = 'Any account';
 
+$txt['permissionname_report_user'] = 'Report users\' profiles';
+$txt['permissionhelp_report_user'] = 'This permission will allow members to report other users\' profiles to the admins to alert them of spam or other inappropriate content in the profile.';
+
 $txt['permissiongroup_general_board'] = 'General';
 $txt['permissionname_moderate_board'] = 'Moderate board';
 $txt['permissionhelp_moderate_board'] = 'The moderate board permission adds a few small permissions that make a moderator a real moderator. Permissions include replying to locked topics, changing the poll expire time and viewing poll results.';

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

@@ -12,6 +12,7 @@ $txt['setting_smiley_sets_enable'] = 'Enable smiley set selection by members';
 $txt['setting_smiley_enable'] = 'Enable customized smileys';
 $txt['setting_smileys_url'] = 'Base URL to all smiley sets';
 $txt['setting_smileys_dir'] = 'Absolute path to all smiley sets';
+$txt['setting_smileys_dir_wrong'] = 'The path to all smiley sets is wrong. This will prevent smileys from working';
 $txt['setting_messageIcons_enable'] = 'Enable customized message icons';
 $txt['setting_messageIcons_enable_note'] = '(otherwise, the default message icons will be used.)';
 $txt['groups_manage_smileys'] = 'Groups allowed to manage smileys and message icons';

+ 11 - 1
Themes/default/languages/ModerationCenter.english.php

@@ -5,7 +5,8 @@ $txt['moderation_center'] = 'Moderation Center';
 $txt['mc_main'] = 'Main';
 $txt['mc_logs'] = 'Logs';
 $txt['mc_posts'] = 'Posts';
-$txt['mc_groups'] = 'Members and groups';
+$txt['mc_groups'] = 'Groups';
+$txt['mc_members'] = 'Members';
 
 $txt['mc_view_groups'] = 'View Membergroups';
 
@@ -17,6 +18,7 @@ $txt['mc_watched_topics'] = 'Watched Topics';
 $txt['mc_scratch_board'] = 'Moderator Scratch Board';
 $txt['mc_latest_news'] = 'Simple Machines Latest News';
 $txt['mc_recent_reports'] = 'Recent Topic Reports';
+$txt['mc_recent_user_reports'] = 'Recent Profile Reports';
 $txt['mc_warnings'] = 'Warnings';
 $txt['mc_notes'] = 'Moderator Notes';
 
@@ -89,6 +91,10 @@ $txt['mc_modreport_no_mod_comment'] = 'There are not currently any moderator com
 $txt['mc_modreport_add_mod_comment'] = 'Add Comment';
 $txt['mc_modreport_edit_mod_comment'] = 'Edit Comment';
 
+$txt['mc_viewmemberreport'] = 'Report for profile of %1$s';
+$txt['mc_memberreport_summary'] = 'There have been %1$d report(s) concerning this member.  The last report was %2$s.';
+$txt['mc_memberreport_whoreported_title'] = 'Members who have reported this member.';
+
 $txt['show_notice'] = 'Notice Text';
 $txt['show_notice_subject'] = 'Subject';
 $txt['show_notice_text'] = 'Text';
@@ -157,4 +163,8 @@ $txt['mc_logoff'] = 'End Moderator Session';
 $txt['mc_click_add_note'] = 'Add a new note';
 $txt['mc_add_note'] = 'Add';
 
+// Do not use numeric entries in the below string.
+$txt['mc_reportedm_ignore_confirm'] = 'Are you sure you wish to ignore further reports about this user\'s profile?\\n\\nThis will turn off further reports for everyone.';
+$txt['mc_reported_members_title'] = 'Reported Members';
+$txt['mc_reported_members_desc'] = 'Allows you to view a list of all users whose profiles have been reported';
 ?>

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

@@ -101,6 +101,12 @@ $txt['modlog_ac_ignore_report'] = 'Disregarded {report} on &quot;{message}&quot;
 $txt['modlog_ac_open_report'] = 'Reopened {report} on &quot;{message}&quot;';
 $txt['modlog_ac_unignore_report'] = 'Undone disregard of {report} on &quot;{message}&quot;';
 
+// Handling reports on users
+$txt['modlog_ac_close_user_report'] = 'Closed {report} on profile of {member}';
+$txt['modlog_ac_ignore_user_report'] = 'Disregarded {report} on profile of {member}';
+$txt['modlog_ac_open_user_report'] = 'Reopened {report} on profile of {member}';
+$txt['modlog_ac_unignore_user_report'] = 'Undone disregard of {report} on profile of {member}';
+
 // Poll stuff
 $txt['modlog_add_poll'] = 'Added a poll to &quot;{topic}&quot;';
 $txt['modlog_edit_poll'] = 'Edited the poll in &quot;{topic}&quot;';

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

@@ -195,5 +195,6 @@ $txt['pm_readable_buddy'] = 'sender is a buddy';
 $txt['pm_readable_label'] = 'apply label &quot;{LABEL}&quot;';
 $txt['pm_readable_delete'] = 'delete the message';
 $txt['pm_readable_then'] = '<strong>then</strong>';
+$txt['pm_remove_message'] = 'Remove this message';
 
 ?>

+ 5 - 0
Themes/default/languages/Post.english.php

@@ -65,6 +65,11 @@ $txt['reported_by'] = 'has been reported by';
 $txt['board_moderate'] = 'on a board you moderate';
 $txt['report_comment'] = 'The reporter has made the following comment';
 
+// Use numeric entities in the below three strings.
+$txt['report_profile'] = 'Report profile of \'%1$s\'';
+$txt['reported_profile'] = 'Reported user';
+$txt['report_following_user'] = 'The profile of "%1$s" at %2$s';
+
 $txt['attach_restrict_attachmentPostLimit'] = 'maximum total size %1$d KB';
 $txt['attach_restrict_attachmentPostLimit_MB'] = 'maximum total size %1$d MB';
 $txt['attach_restrict_attachmentSizeLimit'] = 'maximum individual size %1$d KB';

+ 6 - 4
Themes/default/languages/Profile.english.php

@@ -43,9 +43,6 @@ $txt['dob_year'] = 'Year (YYYY)';
 $txt['password_strength'] = 'For best security, you should use eight or more characters with a combination of letters, numbers, and symbols.';
 $txt['include_website_url'] = 'This must be included if you specify a URL below.';
 $txt['complete_url'] = 'This must be a complete URL.';
-$txt['your_icq'] = 'This is your ICQ number.';
-$txt['your_aim'] = 'This is your AOL Instant Messenger nickname.';
-$txt['your_yim'] = 'This is your Yahoo! Instant Messenger nickname.';
 $txt['sig_info'] = 'Signatures are displayed at the bottom of each post or personal message. BBCode and smileys may be used in your signature.';
 $txt['no_signature_set'] = 'No signature set.';
 $txt['max_sig_characters'] = 'Max characters: %1$d; characters remaining: ';
@@ -144,13 +141,16 @@ $txt['alert_pm_new'] = 'When I receive a new personal message';
 $txt['alert_pm_reply'] = 'When a personal message I sent gets replied to';
 $txt['alert_group_moderation'] = 'Moderation';
 $txt['alert_msg_report'] = 'When a message is reported';
-$txt['alert_msg_report_reply'] = 'When a report I\'ve replied to gets replied to';
+$txt['alert_msg_report_reply'] = 'When a post report I\'ve replied to gets replied to';
 $txt['alert_group_members'] = 'Members';
 $txt['alert_member_register'] = 'When a new person registers';
 $txt['alert_warn_any'] = 'When other members receive a warning';
 $txt['alert_group_calendar'] = 'Calendar';
 $txt['alert_event_new'] = 'When a new event goes into the calendar';
 $txt['alert_request_group'] = 'When someone requests to join a group I moderate';
+$txt['alert_member_report'] = 'When another member\'s profile is reported';
+$txt['alert_member_report_reply'] = 'When a member report I\'ve replied to gets replied to';
+
 
 $txt['notifications_topics'] = 'Current Topic Notifications';
 $txt['notifications_topics_list'] = 'You are being notified of replies to the following topics';
@@ -523,4 +523,6 @@ $txt['outcome_pending'] = 'Open';
 $txt['outcome_approved'] = 'Approved by %1$s on %2$s';
 $txt['outcome_refused'] = 'Refused by %1$s on %2$s';
 $txt['outcome_refused_reason'] = 'Refused by %1$s on %2$s, reason given: %3$s';
+
+$txt['report_profile'] = 'Report This Member';
 ?>

+ 5 - 22
Themes/default/languages/index.english.php

@@ -158,7 +158,7 @@ $txt['msg_alert_one_message'] = 'you have <a href="%1$s">1 message</a>';
 $txt['msg_alert_many_message'] = 'you have <a href="%1$s">%2$d messages</a>';
 $txt['msg_alert_one_new'] = '1 is new';
 $txt['msg_alert_many_new'] = '%1$d are new';
-$txt['remove_message'] = 'Remove this message';
+$txt['remove_message'] = 'Remove this post';
 
 $txt['topic_alert_none'] = 'No messages...';
 $txt['pm_alert_none'] = 'No messages...';
@@ -277,7 +277,6 @@ $txt['redirect_board'] = 'Redirect Board';
 
 $txt['sendtopic_send'] = 'Send';
 $txt['report_sent'] = 'Your report has been sent successfully.';
-$txt['topic_sent'] = 'Your email has been sent successfully.';
 
 $txt['time_offset'] = 'Time Offset';
 $txt['or'] = 'or';
@@ -332,17 +331,6 @@ $txt['days_word'] = 'days';
 $txt['search_for'] = 'Search for';
 $txt['search_match'] = 'Match';
 
-$txt['aim'] = 'AIM';
-// In this string, please use +'s for spaces.
-$txt['aim_default_message'] = 'Hi.+Are+you+there?';
-$txt['aim_title'] = 'AOL Instant Messenger';
-$txt['icq'] = 'ICQ';
-$txt['icq_title'] = 'ICQ Messenger';
-$txt['yim'] = 'YIM';
-$txt['yim_title'] = 'Yahoo Instant Messenger';
-
-$txt['skype'] = 'Skype';
-
 $txt['forum_in_maintainence'] = 'Your forum is in Maintenance Mode. Only administrators can currently log in.';
 $txt['maintenance_page'] = 'You can turn off Maintenance Mode from the <a href="%1$s">Server Settings</a> area.';
 
@@ -369,13 +357,6 @@ $txt['send_topic'] = 'Send this topic';
 $txt['watch'] = 'Watch';
 $txt['unwatch'] = 'Stop watching';
 
-$txt['sendtopic_sender_name'] = 'Your name';
-$txt['sendtopic_sender_email'] = 'Your email address';
-$txt['sendtopic_receiver_name'] = 'Recipient\'s name';
-$txt['sendtopic_receiver_email'] = 'Recipient\'s email address';
-
-$txt['allow_user_email'] = 'Allow users to email me';
-
 $txt['check_all'] = 'Check all';
 
 // Use numeric entities in the below string.
@@ -451,7 +432,7 @@ $txt['split_after_and_this_post'] = 'Split topic after and including this post.'
 $txt['select_split_posts'] = 'Select posts to split.';
 $txt['new_topic'] = 'New Topic';
 $txt['split_successful'] = 'Topic successfully split into two topics.';
-$txt['origin_topic'] = 'Origin Topic';
+$txt['origin_topic'] = 'Original Topic';
 $txt['please_select_split'] = 'Please select which posts you wish to split.';
 $txt['merge_successful'] = 'Topics successfully merged.';
 $txt['new_merged_topic'] = 'Newly Merged Topic';
@@ -480,6 +461,7 @@ $txt['cache_writable'] = 'The cache directory is not writable - this will advers
 $txt['page_created_full'] = 'Page created in %1$.3f seconds with %2$d queries.';
 
 $txt['report_to_mod_func'] = 'Use this function to inform the moderators and administrators of an abusive or wrongly posted message.';
+$txt['report_profile_func'] = 'Use this function to inform the administrators of abusive profile content, such as spam or inappropriate images.';
 
 $txt['online'] = 'Online';
 $txt['member_is_online'] = '%1$s is online';
@@ -620,6 +602,7 @@ $txt['you_likes_1'] = 'You and <a href="%1$s">1 other person</a> like this.';
 $txt['you_likes_n'] = 'You and <a href="%1$s">%2$s other people</a> like this.';
 
 $txt['report_to_mod'] = 'Report to moderator';
+$txt['report_profile'] = 'Report profile of %1$s';
 
 $txt['unread_topics_visit'] = 'Recent Unread Topics';
 $txt['unread_topics_visit_none'] = 'No unread topics found since your last visit.  <a href="' . $scripturl . '?action=unread;all">Click here to try all unread topics</a>.';
@@ -771,13 +754,13 @@ $txt['edit_permissions'] = 'Permissions';
 $txt['mc_unapproved_attachments'] = 'Unapproved Attachments';
 $txt['mc_unapproved_poststopics'] = 'Unapproved Posts and Topics';
 $txt['mc_reported_posts'] = 'Reported Posts';
+$txt['mc_reported_members'] = 'Reported Members';
 $txt['modlog_view'] = 'Moderation Log';
 $txt['calendar_menu'] = 'View Calendar';
 
 // @todo Send email strings - should move?
 $txt['send_email'] = 'Send Email';
 $txt['send_email_disclosed'] = 'Note this will be visible to the recipient.';
-$txt['send_email_subject'] = 'Email Subject';
 
 $txt['ignoring_user'] = 'You are ignoring this user.';
 $txt['show_ignore_user_post'] = 'Show me the post.';

+ 1 - 2
index.php

@@ -290,7 +290,6 @@ function smf_main()
 		'dlattach' => array('Display.php', 'Download'),
 		'editpoll' => array('Poll.php', 'EditPoll'),
 		'editpoll2' => array('Poll.php', 'EditPoll2'),
-		'emailuser' => array('SendTopic.php', 'EmailUser'),
 		'findmember' => array('Subs-Auth.php', 'JSMembers'),
 		'groups' => array('Groups.php', 'Groups'),
 		'help' => array('Help.php', 'ShowHelp'),
@@ -329,7 +328,7 @@ function smf_main()
 		'reminder' => array('Reminder.php', 'RemindMe'),
 		'removepoll' => array('Poll.php', 'RemovePoll'),
 		'removetopic2' => array('RemoveTopic.php', 'RemoveTopic2'),
-		'reporttm' => array('SendTopic.php', 'ReportToModerator'),
+		'reporttm' => array('ReportToMod.php', 'ReportToModerator'),
 		'requestmembers' => array('Subs-Auth.php', 'RequestMembers'),
 		'restoretopic' => array('RemoveTopic.php', 'RestoreTopic'),
 		'search' => array('Search.php', 'PlushSearch1'),

+ 49 - 12
other/install.php

@@ -391,7 +391,7 @@ function load_lang_file()
 function load_database()
 {
 	global $db_prefix, $db_connection, $db_character_set, $sourcedir, $language;
-	global $smcFunc, $mbname, $scripturl, $boardurl, $modSettings, $db_type, $db_name, $db_user, $db_persist;
+	global $smcFunc, $mbname, $scripturl, $boardurl, $modSettings, $db_type, $db_name, $db_user, $db_persist, $db_port;
 
 	if (empty($sourcedir))
 		$sourcedir = dirname(__FILE__) . '/Sources';
@@ -412,8 +412,28 @@ function load_database()
 		if (version_compare(PHP_VERSION, '5', '<'))
 			require_once($sourcedir . '/Subs-Compat.php');
 
+		$db_options = array('persist' => $db_persist);
+		$port = '';
+
+		// Figure out the port...
+		if (!empty($_POST['db_port']))
+		{
+			if ($db_type == 'mysql' || $db_type == 'mysqli')
+			{
+				$port = ((int) $_POST['db_port'] == ini_get($db_type . 'default_port')) ? '' : (int) $_POST['db_port'];
+			}
+			elseif ($db_type == 'postgresql')
+			{
+				// PostgreSQL doesn't have a default port setting in php.ini, so just check against the default
+				$port = ((int) $_POST['db_port'] == 5432) ? '' : (int) $_POST['db_port'];
+			}
+		}
+
+		if (!empty($port))
+			$db_options['port'] = $port;
+
 		if (!$db_connection)
-			$db_connection = smf_db_initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, array('persist' => $db_persist));
+			$db_connection = smf_db_initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_options);
 	}
 }
 
@@ -758,8 +778,9 @@ function DatabaseSettings()
 				}
 				if (isset($db['default_password']))
 					$incontext['db']['pass'] = ini_get($db['default_password']);
-				if (isset($db['default_port']))
-					$db_port = ini_get($db['default_port']);
+
+				// For simplicity and less confusion, leave the port blank by default
+				$incontext['db']['port'] = '';
 
 				$incontext['db']['type'] = $key;
 				$foundOne = true;
@@ -774,14 +795,13 @@ function DatabaseSettings()
 		$incontext['db']['name'] = ($_POST['db_type'] == 'sqlite' || $_POST['db_type'] == 'sqlite3') && isset($_POST['db_filename']) ? $_POST['db_filename'] : $_POST['db_name'];
 		$incontext['db']['server'] = $_POST['db_server'];
 		$incontext['db']['prefix'] = $_POST['db_prefix'];
+		
+		if (!empty($_POST['db_port']))
+			$incontext['db']['port'] = $_POST['db_port'];
 	}
 	else
 	{
 		$incontext['db']['prefix'] = 'smf_';
-
-		// Should we use a non standard port?
-		if (!empty($db_port))
-			$incontext['db']['server'] .= ':' . $db_port;
 	}
 
 	// Are we submitting?
@@ -827,6 +847,16 @@ function DatabaseSettings()
 			'cookiename' => 'SMFCookie' . abs(crc32($_POST['db_name'] . preg_replace('~[^A-Za-z0-9_$]~', '', $_POST['db_prefix'])) % 1000),
 		);
 
+		// Only set the port if we're not using the default
+		if (!empty($_POST['db_port']))
+		{
+			// For MySQL, we can get the "default port" from PHP. PostgreSQL has no such option though.
+			if (($db_type == 'mysql' || $db_type == 'mysqli') && $_POST['db_port'] != ini_get($db_type . '.default_port'))
+				$vars['db_port'] == (int) $_POST['db_port'];
+			elseif ($db_type == 'postgresql' && $_POST['db_port'] != 5432)
+				$vars['db_port'] == (int) $_POST['db_port'];
+		}
+
 		// God I hope it saved!
 		if (!updateSettingsFile($vars) && substr(__FILE__, 1, 2) == ':\\')
 		{
@@ -1432,8 +1462,8 @@ function AdminAccount()
 					'id_group' => 'int', 'posts' => 'int', 'date_registered' => 'int', 'hide_email' => 'int',
 					'password_salt' => 'string', 'lngfile' => 'string', 'personal_text' => 'string', 'avatar' => 'string',
 					'member_ip' => 'string', 'member_ip2' => 'string', 'buddy_list' => 'string', 'pm_ignore_list' => 'string',
-					'website_title' => 'string', 'website_url' => 'string', 'location' => 'string',
-					'aim' => 'string', 'icq' => 'string', 'skype' => 'string', 'signature' => 'string', 'usertitle' => 'string', 'secret_question' => 'string',
+					'website_title' => 'string', 'website_url' => 'string',
+					'signature' => 'string', 'usertitle' => 'string', 'secret_question' => 'string',
 					'additional_groups' => 'string', 'ignore_boards' => 'string', 'openid_uri' => 'string',
 				),
 				array(
@@ -1442,7 +1472,7 @@ function AdminAccount()
 					$incontext['member_salt'], '', '', '',
 					$ip, $ip, '', '',
 					'', '', '',
-					'', '', '', '', '', '',
+					'', '', '',
 					'', '', '',
 				),
 				array('id_member')
@@ -2397,6 +2427,12 @@ function template_database_settings()
 					<input type="text" name="db_server" id="db_server_input" value="', $incontext['db']['server'], '" size="30" class="input_text" /><br />
 					<div style="font-size: smaller; margin-bottom: 2ex;">', $txt['db_settings_server_info'], '</div>
 				</td>
+			</tr><tr id="db_port_contain">
+				<td width="20%" valign="top" class="textbox"><label for="db_port_input">', $txt['db_settings_port'], ':</label></td>
+				<td>
+					<input type="text" name="db_port" id="db_port_input" value="', $incontext['db']['port'], '"><br>
+					<div style="font-size: smaller; margin-bottom: 2ex;">', $txt['db_settings_port_info'], '</div>
+				</td>
 			</tr><tr id="db_user_contain">
 				<td valign="top" class="textbox"><label for="db_user_input">', $txt['db_settings_username'], ':</label></td>
 				<td>
@@ -2456,6 +2492,7 @@ function template_database_settings()
 			document.getElementById(\'db_name_contain\').style.display = showAll ? \'\' : \'none\';
 			document.getElementById(\'db_filename_contain\').style.display = !showAll ? \'\' : \'none\';
 			document.getElementById(\'db_sqlite_warning\').style.display = !showAll ? \'\' : \'none\';
+			document.getElementById(\'db_port_contain\').style.display = showAll ? \'\' : \'none\';
 			if (document.getElementById(\'db_type_input\').value == \'postgresql\')
 				document.getElementById(\'db_name_info_warning\').style.display = \'none\';
 			else
@@ -2685,4 +2722,4 @@ function template_delete_install()
 		', $txt['good_luck'];
 }
 
-?>
+?>

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

@@ -1224,15 +1224,9 @@ CREATE TABLE {$db_prefix}members (
   openid_uri text NOT NULL,
   email_address varchar(255) NOT NULL default '',
   personal_text varchar(255) NOT NULL default '',
-  gender tinyint(4) unsigned NOT NULL default '0',
   birthdate date NOT NULL default '0001-01-01',
   website_title varchar(255) NOT NULL default '',
   website_url varchar(255) NOT NULL default '',
-  location varchar(255) NOT NULL default '',
-  icq varchar(255) NOT NULL default '',
-  aim varchar(255) NOT NULL default '',
-  yim varchar(32) NOT NULL default '',
-  skype varchar(255) NOT NULL default '',
   hide_email tinyint(4) NOT NULL default '0',
   show_online tinyint(4) NOT NULL default '1',
   time_format varchar(80) NOT NULL default '',
@@ -2032,7 +2026,6 @@ VALUES (1, 'name', '{$default_theme_name}'),
 	(1, 'show_modify', '1'),
 	(1, 'show_user_images', '1'),
 	(1, 'show_blurb', '1'),
-	(1, 'show_gender', '0'),
 	(1, 'show_newsfader', '0'),
 	(1, 'number_recent_posts', '0'),
 	(1, 'show_profile_buttons', '1'),

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

@@ -1623,15 +1623,9 @@ CREATE TABLE {$db_prefix}members (
   openid_uri text NOT NULL,
   email_address varchar(255) NOT NULL,
   personal_text varchar(255) NOT NULL,
-  gender smallint NOT NULL default '0',
   birthdate date NOT NULL default '0001-01-01',
   website_title varchar(255) NOT NULL,
   website_url varchar(255) NOT NULL,
-  location varchar(255) NOT NULL,
-  icq varchar(255) NOT NULL,
-  aim varchar(255) NOT NULL default '',
-  yim varchar(32) NOT NULL default '',
-  skype varchar(255) NOT NULL default '',
   hide_email smallint NOT NULL default '0',
   show_online smallint NOT NULL default '1',
   time_format varchar(80) NOT NULL default '',
@@ -2565,7 +2559,6 @@ INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_late
 INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_modify', '1');
 INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_user_images', '1');
 INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_blurb', '1');
-INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_gender', '0');
 INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_newsfader', '0');
 INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'number_recent_posts', '0');
 INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_profile_buttons', '1');

+ 0 - 7
other/install_2-1_sqlite.sql

@@ -1324,15 +1324,9 @@ CREATE TABLE {$db_prefix}members (
   openid_uri text NOT NULL,
   email_address varchar(255) NOT NULL,
   personal_text varchar(255) NOT NULL,
-  gender smallint NOT NULL default '0',
   birthdate date NOT NULL default '0001-01-01',
   website_title varchar(255) NOT NULL,
   website_url varchar(255) NOT NULL,
-  location varchar(255) NOT NULL,
-  icq varchar(255) NOT NULL,
-  aim varchar(255) NOT NULL default '',
-  yim varchar(32) NOT NULL default '',
-  skype varchar(255) NOT NULL default '',
   hide_email smallint NOT NULL default '0',
   show_online smallint NOT NULL default '1',
   time_format varchar(80) NOT NULL default '',
@@ -2184,7 +2178,6 @@ INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_late
 INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_modify', '1');
 INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_user_images', '1');
 INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_blurb', '1');
-INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_gender', '0');
 INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_newsfader', '0');
 INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'number_recent_posts', '0');
 INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_profile_buttons', '1');

+ 0 - 7
other/install_2-1_sqlite3.sql

@@ -1324,15 +1324,9 @@ CREATE TABLE {$db_prefix}members (
   openid_uri text NOT NULL,
   email_address varchar(255) NOT NULL,
   personal_text varchar(255) NOT NULL,
-  gender smallint NOT NULL default '0',
   birthdate date NOT NULL default '0001-01-01',
   website_title varchar(255) NOT NULL,
   website_url varchar(255) NOT NULL,
-  location varchar(255) NOT NULL,
-  icq varchar(255) NOT NULL,
-  aim varchar(255) NOT NULL default '',
-  yim varchar(32) NOT NULL default '',
-  skype varchar(255) NOT NULL default '',
   hide_email smallint NOT NULL default '0',
   show_online smallint NOT NULL default '1',
   time_format varchar(80) NOT NULL default '',
@@ -2184,7 +2178,6 @@ INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_late
 INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_modify', '1');
 INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_user_images', '1');
 INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_blurb', '1');
-INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_gender', '0');
 INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_newsfader', '0');
 INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'number_recent_posts', '0');
 INSERT INTO {$db_prefix}themes (id_theme, variable, value) VALUES (1, 'show_profile_buttons', '1');

+ 30 - 2
other/upgrade.php

@@ -1028,7 +1028,11 @@ function WelcomeLogin()
 	if(!is_writable($custom_av_dir))
 		return throw_error(sprintf('The directory: %1$s has to be writable to continue the upgrade. Please make sure permissions are correctly set to allow this.', $custom_av_dir));
 	elseif ($need_settings_update)
-		updateSettings(array('custom_av_dir' => $custom_av_dir));
+	{
+		if (!function_exists('cache_put_data'))
+			require_once($sourcedir . '/Load.php');
+		updateSettings(array('custom_avatar_dir' => $custom_av_dir));
+	}
 
 	require_once($sourcedir . '/Security.php');
 
@@ -1278,7 +1282,7 @@ function checkLogin()
 function UpgradeOptions()
 {
 	global $db_prefix, $command_line, $modSettings, $is_debug, $smcFunc, $packagesdir;
-	global $boarddir, $boardurl, $sourcedir, $maintenance, $mmessage, $cachedir, $upcontext, $db_type;
+	global $boarddir, $boardurl, $sourcedir, $maintenance, $mmessage, $cachedir, $upcontext, $db_type, $db_server;
 
 	$upcontext['sub_template'] = 'upgrade_options';
 	$upcontext['page_title'] = 'Upgrade Options';
@@ -1383,6 +1387,30 @@ function UpgradeOptions()
 	if (!empty($_POST['convertMysql']) && $db_type == 'mysql')
 		$changes['db_type'] = '\'mysqli\'';
 
+	// If they have a "host:port" setup for the host, split that into separate values
+	// You should never have a : in the hostname if you're not on MySQL, but better safe than sorry
+	if (strpos($db_server, ':') !== false && ($db_type == 'mysql' || $db_type == 'mysqli'))
+	{
+		list($db_server, $db_port) = explode(':', $db_server);
+
+		$changes['db_server'] = '\'' . $db_server . '\'';
+
+		// Only set this if we're not using the default port
+		if ($db_port != ini_get('mysql' . ($db_type == 'mysqli' || !empty($_POST['convertMysql']) ? 'i' : '') . '.default_port'))
+			$changes['db_port'] = (int) $db_port;
+	}
+	elseif(!empty($db_port))
+	{
+		// If db_port is set and is the same as the default, set it to ''
+		if ($db_type == 'mysql' || $db_type == 'mysqli')
+		{
+			if ($db_port == ini_get('mysql' . ($db_type == 'mysqli' || !empty($_POST['convertMysql']) ? 'i' : '') . '.default_port'))
+				$changes['db_port'] = '\'\'';
+			elseif ($db_type == 'postgresql' && $db_port == 5432)
+				$changes['db_port'] = '\'\'';
+		}
+	}
+
 	// Maybe we haven't had this option yet?
 	if (empty($packagesdir))
 		$changes['packagesdir'] = '\'' . fixRelativePath($boarddir) . '/Packages\'';

+ 64 - 8
other/upgrade_2-1_mysql.sql

@@ -334,14 +334,6 @@ CREATE TABLE IF NOT EXISTS {$db_prefix}background_tasks (
 ) ENGINE=MyISAM;
 ---#
 
-/******************************************************************************/
----- Replacing MSN with Skype
-/******************************************************************************/
----# Modifying the "msn" column...
-ALTER TABLE {$db_prefix}members
-CHANGE msn skype varchar(255) NOT NULL DEFAULT '';
----#
-
 /******************************************************************************/
 --- Adding support for deny boards access
 /******************************************************************************/
@@ -568,6 +560,70 @@ if (file_exists($GLOBALS['boarddir'] . '/Themes/core'))
 ---}
 ---#
 
+/******************************************************************************/
+--- Messenger fields
+/******************************************************************************/
+---# Insert fields
+INSERT INTO `{$db_prefix}custom_fields` (`col_name`, `field_name`, `field_desc`, `field_type`, `field_length`, `field_options`, `mask`, `show_reg`, `show_display`, `show_profile`, `private`, `active`, `bbc`, `can_search`, `default_value`, `enclose`, `placement`) VALUES
+('cust_aolins', 'AOL Instant Messenger', 'This is your AOL Instant Messenger nickname.', 'text', 50, '', 'regex~[a-z][0-9a-z.-]{1,31}~i', 0, 1, 'forumprofile', 0, 1, 0, 0, '', '<a class="aim" href="aim:goim?screenname={INPUT}&message=Hello!+Are+you+there?" target="_blank" title="AIM - {INPUT}"><img src="{IMAGES_URL}/fields/aim.gif" alt="AIM - {INPUT}"></a>', 1),
+('cust_icq', 'ICQ', 'This is your ICQ number.', 'text', 12, '', 'regex~[1-9][0-9]{4,9}~i', 0, 1, 'forumprofile', 0, 1, 0, 0, '', '<a class="icq" href="http://www.icq.com/whitepages/about_me.php?uin={INPUT}" target="_blank" title="ICQ - {INPUT}"><img src="http://status.icq.com/online.gif?img=5&icq={INPUT}" alt="ICQ - {INPUT}" width="18" height="18"></a>', 1),
+('cust_skype', 'Skype', 'Your Skype name', 'text', 50, '', 'email', 0, 1, 'forumprofile', 0, 1, 0, 0, '', '<a class="skype new_win" href="skype:{INPUT}?chat" title="Live - {INPUT}"><img src="{IMAGES_URL}/skype.png" alt="Live - {INPUT}"></a>', 1),
+('cust_yahoo', 'Yahoo! Messenger', 'This is your Yahoo! Instant Messenger nickname.', 'text', 50, '', 'email', 0, 1, 'forumprofile', 0, 1, 0, 0, '', '<a class="yim" href="http://edit.yahoo.com/config/send_webmesg?.target={INPUT}" target="_blank" title="Yahoo! Messenger - {INPUT}"><img src="http://opi.yahoo.com/online?m=g&t=0&u={INPUT}" alt="Yahoo! Messenger - {INPUT}"></a>', 1);
+('cust_loca', 'Location', 'Geographic location.', 'text', 50, '', 'email', 0, 1, 'forumprofile', 0, 1, 0, 0, '', '', 1);
+('cust_gender', 'Gender', 'Your gender.', 'text', 50, '', 'email', 0, 1, 'forumprofile', 0, 1, 0, 0, '', '', 1);
+---#
+
+---# Converting member values...
+---{
+// We cannot do this twice
+if (@$modSettings['smfVersion'] < '2.2')
+{
+	$request = upgrade_query("
+		SELECT id_member, aim, icq, msn, yim, location, gender
+		FROM {$db_prefix}members");
+	$inserts = array();
+	while ($row = mysql_fetch_assoc($request))
+	{
+		if (!empty($row[aim]))
+			$inserts[] = "($row[id_member], -1, 'cust_aolins', $row[aim])";
+
+		if (!empty($row[icq]))
+			$inserts[] = "($row[id_member], -1, 'cust_icq', $row[icq])";
+
+		if (!empty($row[msn]))
+			$inserts[] = "($row[id_member], -1, 'cust_skype', $row[msn])";
+
+		if (!empty($row[yim]))
+			$inserts[] = "($row[id_member], -1, 'cust_yahoo', $row[yim])";
+
+		if (!empty($row[location]))
+			$inserts[] = "($row[id_member], -1, 'cust_loca', $row[location])";
+
+		if (!empty($row[gender]))
+			$inserts[] = "($row[id_member], -1, 'cust_gender', $row[gender])";
+	}
+	mysql_free_result($request);
+
+	if (!empty($inserts))
+		upgrade_query("
+			INSERT INTO {$db_prefix}themes
+				(id_member, id_theme, variable, value)
+			VALUES
+				" . implode(',', $inserts));
+}
+---}
+---#
+
+---# Dropping old fields
+ALTER TABLE `{$db_prefix}members`
+  DROP `icq`,
+  DROP `aim`,
+  DROP `yim`,
+  DROP `msn`;
+  DROP `location`;
+  DROP `gender`;
+---#
+
 /******************************************************************************/
 --- Adding support for drafts
 /******************************************************************************/

+ 64 - 8
other/upgrade_2-1_postgresql.sql

@@ -391,14 +391,6 @@ CREATE TABLE {$db_prefix}background_tasks (
 );
 ---#
 
-/******************************************************************************/
----- Replacing MSN with Skype
-/******************************************************************************/
----# Modifying the "msn" column...
-ALTER TABLE {$db_prefix}members
-RENAME msn TO skype;
----#
-
 /******************************************************************************/
 --- Adding support for deny boards access
 /******************************************************************************/
@@ -638,6 +630,70 @@ if (file_exists($GLOBALS['boarddir'] . '/Themes/core'))
 ---}
 ---#
 
+/******************************************************************************/
+--- Messenger fields
+/******************************************************************************/
+---# Insert fields
+INSERT INTO `{$db_prefix}custom_fields` (`col_name`, `field_name`, `field_desc`, `field_type`, `field_length`, `field_options`, `mask`, `show_reg`, `show_display`, `show_profile`, `private`, `active`, `bbc`, `can_search`, `default_value`, `enclose`, `placement`) VALUES
+('cust_aolins', 'AOL Instant Messenger', 'This is your AOL Instant Messenger nickname.', 'text', 50, '', 'regex~[a-z][0-9a-z.-]{1,31}~i', 0, 1, 'forumprofile', 0, 1, 0, 0, '', '<a class="aim" href="aim:goim?screenname={INPUT}&message=Hello!+Are+you+there?" target="_blank" title="AIM - {INPUT}"><img src="{IMAGES_URL}/fields/aim.gif" alt="AIM - {INPUT}"></a>', 1),
+('cust_icq', 'ICQ', 'This is your ICQ number.', 'text', 12, '', 'regex~[1-9][0-9]{4,9}~i', 0, 1, 'forumprofile', 0, 1, 0, 0, '', '<a class="icq" href="http://www.icq.com/whitepages/about_me.php?uin={INPUT}" target="_blank" title="ICQ - {INPUT}"><img src="http://status.icq.com/online.gif?img=5&icq={INPUT}" alt="ICQ - {INPUT}" width="18" height="18"></a>', 1),
+('cust_skype', 'Skype', 'Your Skype name', 'text', 50, '', 'email', 0, 1, 'forumprofile', 0, 1, 0, 0, '', '<a class="skype new_win" href="skype:{INPUT}?chat" title="Live - {INPUT}"><img src="{IMAGES_URL}/skype.png" alt="Live - {INPUT}"></a>', 1),
+('cust_yahoo', 'Yahoo! Messenger', 'This is your Yahoo! Instant Messenger nickname.', 'text', 50, '', 'email', 0, 1, 'forumprofile', 0, 1, 0, 0, '', '<a class="yim" href="http://edit.yahoo.com/config/send_webmesg?.target={INPUT}" target="_blank" title="Yahoo! Messenger - {INPUT}"><img src="http://opi.yahoo.com/online?m=g&t=0&u={INPUT}" alt="Yahoo! Messenger - {INPUT}"></a>', 1);
+('cust_loca', 'Location', 'Geographic location.', 'text', 50, '', 'email', 0, 1, 'forumprofile', 0, 1, 0, 0, '', '', 1);
+('cust_gender', 'Gender', 'Your gender.', 'text', 50, '', 'email', 0, 1, 'forumprofile', 0, 1, 0, 0, '', '', 1);
+---#
+
+---# Converting member values...
+---{
+// We cannot do this twice
+if (@$modSettings['smfVersion'] < '2.2')
+{
+	$request = upgrade_query("
+		SELECT id_member, aim, icq, msn, yim, location, gender
+		FROM {$db_prefix}members");
+	$inserts = array();
+	while ($row = mysql_fetch_assoc($request))
+	{
+		if (!empty($row[aim]))
+			$inserts[] = "($row[id_member], -1, 'cust_aolins', $row[aim])";
+
+		if (!empty($row[icq]))
+			$inserts[] = "($row[id_member], -1, 'cust_icq', $row[icq])";
+
+		if (!empty($row[msn]))
+			$inserts[] = "($row[id_member], -1, 'cust_skype', $row[msn])";
+
+		if (!empty($row[yim]))
+			$inserts[] = "($row[id_member], -1, 'cust_yahoo', $row[yim])";
+
+		if (!empty($row[location]))
+			$inserts[] = "($row[id_member], -1, 'cust_loca', $row[location])";
+
+		if (!empty($row[gender]))
+			$inserts[] = "($row[id_member], -1, 'cust_gender', $row[gender])";
+	}
+	mysql_free_result($request);
+
+	if (!empty($inserts))
+		upgrade_query("
+			INSERT INTO {$db_prefix}themes
+				(id_member, id_theme, variable, value)
+			VALUES
+				" . implode(',', $inserts));
+}
+---}
+---#
+
+---# Dropping old fields
+ALTER TABLE `{$db_prefix}members`
+  DROP `icq`,
+  DROP `aim`,
+  DROP `yim`,
+  DROP `msn`;
+  DROP `location`;
+  DROP `gender`;
+---#
+
 /******************************************************************************/
 --- Adding support for drafts
 /******************************************************************************/

+ 64 - 8
other/upgrade_2-1_sqlite.sql

@@ -354,14 +354,6 @@ CREATE TABLE IF NOT EXISTS {$db_prefix}background_tasks (
 );
 ---#
 
-/******************************************************************************/
----- Replacing MSN with Skype
-/******************************************************************************/
----# Modifying the "msn" column...
-ALTER TABLE {$db_prefix}members
-CHANGE msn skype varchar(255) NOT NULL DEFAULT '';
----#
-
 /******************************************************************************/
 --- Adding support for deny boards access
 /******************************************************************************/
@@ -634,6 +626,70 @@ if (file_exists($GLOBALS['boarddir'] . '/Themes/core'))
 	}
 }
 
+/******************************************************************************/
+--- Messenger fields
+/******************************************************************************/
+---# Insert fields
+INSERT INTO `{$db_prefix}custom_fields` (`col_name`, `field_name`, `field_desc`, `field_type`, `field_length`, `field_options`, `mask`, `show_reg`, `show_display`, `show_profile`, `private`, `active`, `bbc`, `can_search`, `default_value`, `enclose`, `placement`) VALUES
+('cust_aolins', 'AOL Instant Messenger', 'This is your AOL Instant Messenger nickname.', 'text', 50, '', 'regex~[a-z][0-9a-z.-]{1,31}~i', 0, 1, 'forumprofile', 0, 1, 0, 0, '', '<a class="aim" href="aim:goim?screenname={INPUT}&message=Hello!+Are+you+there?" target="_blank" title="AIM - {INPUT}"><img src="{IMAGES_URL}/fields/aim.gif" alt="AIM - {INPUT}"></a>', 1),
+('cust_icq', 'ICQ', 'This is your ICQ number.', 'text', 12, '', 'regex~[1-9][0-9]{4,9}~i', 0, 1, 'forumprofile', 0, 1, 0, 0, '', '<a class="icq" href="http://www.icq.com/whitepages/about_me.php?uin={INPUT}" target="_blank" title="ICQ - {INPUT}"><img src="http://status.icq.com/online.gif?img=5&icq={INPUT}" alt="ICQ - {INPUT}" width="18" height="18"></a>', 1),
+('cust_skype', 'Skype', 'Your Skype name', 'text', 50, '', 'email', 0, 1, 'forumprofile', 0, 1, 0, 0, '', '<a class="skype new_win" href="skype:{INPUT}?chat" title="Live - {INPUT}"><img src="{IMAGES_URL}/skype.png" alt="Live - {INPUT}"></a>', 1),
+('cust_yahoo', 'Yahoo! Messenger', 'This is your Yahoo! Instant Messenger nickname.', 'text', 50, '', 'email', 0, 1, 'forumprofile', 0, 1, 0, 0, '', '<a class="yim" href="http://edit.yahoo.com/config/send_webmesg?.target={INPUT}" target="_blank" title="Yahoo! Messenger - {INPUT}"><img src="http://opi.yahoo.com/online?m=g&t=0&u={INPUT}" alt="Yahoo! Messenger - {INPUT}"></a>', 1);
+('cust_loca', 'Location', 'Geographic location.', 'text', 50, '', 'email', 0, 1, 'forumprofile', 0, 1, 0, 0, '', '', 1);
+('cust_gender', 'Gender', 'Your gender.', 'text', 50, '', 'email', 0, 1, 'forumprofile', 0, 1, 0, 0, '', '', 1);
+---#
+
+---# Converting member values...
+---{
+// We cannot do this twice
+if (@$modSettings['smfVersion'] < '2.2')
+{
+	$request = upgrade_query("
+		SELECT id_member, aim, icq, msn, yim, location, gender
+		FROM {$db_prefix}members");
+	$inserts = array();
+	while ($row = mysql_fetch_assoc($request))
+	{
+		if (!empty($row[aim]))
+			$inserts[] = "($row[id_member], -1, 'cust_aolins', $row[aim])";
+
+		if (!empty($row[icq]))
+			$inserts[] = "($row[id_member], -1, 'cust_icq', $row[icq])";
+
+		if (!empty($row[msn]))
+			$inserts[] = "($row[id_member], -1, 'cust_skype', $row[msn])";
+
+		if (!empty($row[yim]))
+			$inserts[] = "($row[id_member], -1, 'cust_yahoo', $row[yim])";
+
+		if (!empty($row[location]))
+			$inserts[] = "($row[id_member], -1, 'cust_loca', $row[location])";
+
+		if (!empty($row[gender]))
+			$inserts[] = "($row[id_member], -1, 'cust_gender', $row[gender])";
+	}
+	mysql_free_result($request);
+
+	if (!empty($inserts))
+		upgrade_query("
+			INSERT INTO {$db_prefix}themes
+				(id_member, id_theme, variable, value)
+			VALUES
+				" . implode(',', $inserts));
+}
+---}
+---#
+
+---# Dropping old fields
+ALTER TABLE `{$db_prefix}members`
+  DROP `icq`,
+  DROP `aim`,
+  DROP `yim`,
+  DROP `msn`;
+  DROP `location`;
+  DROP `gender`;
+---#
+
 /******************************************************************************/
 --- Adding support for drafts
 /******************************************************************************/