Chris@76: = 10: a member is banned. Chris@76: */ Chris@76: Chris@76: // Ban center. Chris@76: function Ban() Chris@76: { Chris@76: global $context, $txt, $scripturl; Chris@76: Chris@76: isAllowedTo('manage_bans'); Chris@76: Chris@76: loadTemplate('ManageBans'); Chris@76: Chris@76: $subActions = array( Chris@76: 'add' => 'BanEdit', Chris@76: 'browse' => 'BanBrowseTriggers', Chris@76: 'edittrigger' => 'BanEditTrigger', Chris@76: 'edit' => 'BanEdit', Chris@76: 'list' => 'BanList', Chris@76: 'log' => 'BanLog', Chris@76: ); Chris@76: Chris@76: // Default the sub-action to 'view ban list'. Chris@76: $_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'list'; Chris@76: Chris@76: $context['page_title'] = $txt['ban_title']; Chris@76: $context['sub_action'] = $_REQUEST['sa']; Chris@76: Chris@76: // Tabs for browsing the different ban functions. Chris@76: $context[$context['admin_menu_name']]['tab_data'] = array( Chris@76: 'title' => $txt['ban_title'], Chris@76: 'help' => 'ban_members', Chris@76: 'description' => $txt['ban_description'], Chris@76: 'tabs' => array( Chris@76: 'list' => array( Chris@76: 'description' => $txt['ban_description'], Chris@76: 'href' => $scripturl . '?action=admin;area=ban;sa=list', Chris@76: 'is_selected' => $_REQUEST['sa'] == 'list' || $_REQUEST['sa'] == 'edit' || $_REQUEST['sa'] == 'edittrigger', Chris@76: ), Chris@76: 'add' => array( Chris@76: 'description' => $txt['ban_description'], Chris@76: 'href' => $scripturl . '?action=admin;area=ban;sa=add', Chris@76: 'is_selected' => $_REQUEST['sa'] == 'add', Chris@76: ), Chris@76: 'browse' => array( Chris@76: 'description' => $txt['ban_trigger_browse_description'], Chris@76: 'href' => $scripturl . '?action=admin;area=ban;sa=browse', Chris@76: 'is_selected' => $_REQUEST['sa'] == 'browse', Chris@76: ), Chris@76: 'log' => array( Chris@76: 'description' => $txt['ban_log_description'], Chris@76: 'href' => $scripturl . '?action=admin;area=ban;sa=log', Chris@76: 'is_selected' => $_REQUEST['sa'] == 'log', Chris@76: 'is_last' => true, Chris@76: ), Chris@76: ), Chris@76: ); Chris@76: Chris@76: // Call the right function for this sub-acton. Chris@76: $subActions[$_REQUEST['sa']](); Chris@76: } Chris@76: Chris@76: // List all the bans. Chris@76: function BanList() Chris@76: { Chris@76: global $txt, $context, $ban_request, $ban_counts, $scripturl; Chris@76: global $user_info, $smcFunc, $sourcedir; Chris@76: Chris@76: // User pressed the 'remove selection button'. Chris@76: if (!empty($_POST['removeBans']) && !empty($_POST['remove']) && is_array($_POST['remove'])) Chris@76: { Chris@76: checkSession(); Chris@76: Chris@76: // Make sure every entry is a proper integer. Chris@76: foreach ($_POST['remove'] as $index => $ban_id) Chris@76: $_POST['remove'][(int) $index] = (int) $ban_id; Chris@76: Chris@76: // Unban them all! Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}ban_groups Chris@76: WHERE id_ban_group IN ({array_int:ban_list})', Chris@76: array( Chris@76: 'ban_list' => $_POST['remove'], Chris@76: ) Chris@76: ); Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}ban_items Chris@76: WHERE id_ban_group IN ({array_int:ban_list})', Chris@76: array( Chris@76: 'ban_list' => $_POST['remove'], Chris@76: ) Chris@76: ); Chris@76: Chris@76: // No more caching this ban! Chris@76: updateSettings(array('banLastUpdated' => time())); Chris@76: Chris@76: // Some members might be unbanned now. Update the members table. Chris@76: updateBanMembers(); Chris@76: } Chris@76: Chris@76: // Create a date string so we don't overload them with date info. Chris@76: if (preg_match('~%[AaBbCcDdeGghjmuYy](?:[^%]*%[AaBbCcDdeGghjmuYy])*~', $user_info['time_format'], $matches) == 0 || empty($matches[0])) Chris@76: $context['ban_time_format'] = $user_info['time_format']; Chris@76: else Chris@76: $context['ban_time_format'] = $matches[0]; Chris@76: Chris@76: $listOptions = array( Chris@76: 'id' => 'ban_list', Chris@76: 'items_per_page' => 20, Chris@76: 'base_href' => $scripturl . '?action=admin;area=ban;sa=list', Chris@76: 'default_sort_col' => 'added', Chris@76: 'default_sort_dir' => 'desc', Chris@76: 'get_items' => array( Chris@76: 'function' => 'list_getBans', Chris@76: ), Chris@76: 'get_count' => array( Chris@76: 'function' => 'list_getNumBans', Chris@76: ), Chris@76: 'no_items_label' => $txt['ban_no_entries'], Chris@76: 'columns' => array( Chris@76: 'name' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['ban_name'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'db' => 'name', Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'bg.name', Chris@76: 'reverse' => 'bg.name DESC', Chris@76: ), Chris@76: ), Chris@76: 'notes' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['ban_notes'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'db' => 'notes', Chris@76: 'class' => 'smalltext', Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'LENGTH(bg.notes) > 0 DESC, bg.notes', Chris@76: 'reverse' => 'LENGTH(bg.notes) > 0, bg.notes DESC', Chris@76: ), Chris@76: ), Chris@76: 'reason' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['ban_reason'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'db' => 'reason', Chris@76: 'class' => 'smalltext', Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'LENGTH(bg.reason) > 0 DESC, bg.reason', Chris@76: 'reverse' => 'LENGTH(bg.reason) > 0, bg.reason DESC', Chris@76: ), Chris@76: ), Chris@76: 'added' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['ban_added'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'function' => create_function('$rowData', ' Chris@76: global $context; Chris@76: Chris@76: return timeformat($rowData[\'ban_time\'], empty($context[\'ban_time_format\']) ? true : $context[\'ban_time_format\']); Chris@76: '), Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'bg.ban_time', Chris@76: 'reverse' => 'bg.ban_time DESC', Chris@76: ), Chris@76: ), Chris@76: 'expires' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['ban_expires'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'function' => create_function('$rowData', ' Chris@76: global $txt; Chris@76: Chris@76: // This ban never expires...whahaha. Chris@76: if ($rowData[\'expire_time\'] === null) Chris@76: return $txt[\'never\']; Chris@76: Chris@76: // This ban has already expired. Chris@76: elseif ($rowData[\'expire_time\'] < time()) Chris@76: return sprintf(\'%1$s\', $txt[\'ban_expired\']); Chris@76: Chris@76: // Still need to wait a few days for this ban to expire. Chris@76: else Chris@76: return sprintf(\'%1$d %2$s\', ceil(($rowData[\'expire_time\'] - time()) / (60 * 60 * 24)), $txt[\'ban_days\']); Chris@76: '), Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'IFNULL(bg.expire_time, 1=1) DESC, bg.expire_time DESC', Chris@76: 'reverse' => 'IFNULL(bg.expire_time, 1=1), bg.expire_time', Chris@76: ), Chris@76: ), Chris@76: 'num_triggers' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['ban_triggers'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'db' => 'num_triggers', Chris@76: 'style' => 'text-align: center;', Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'num_triggers DESC', Chris@76: 'reverse' => 'num_triggers', Chris@76: ), Chris@76: ), Chris@76: 'actions' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['ban_actions'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'sprintf' => array( Chris@76: 'format' => '' . $txt['modify'] . '', Chris@76: 'params' => array( Chris@76: 'id_ban_group' => false, Chris@76: ), Chris@76: ), Chris@76: 'style' => 'text-align: center;', Chris@76: ), Chris@76: ), Chris@76: 'check' => array( Chris@76: 'header' => array( Chris@76: 'value' => '', Chris@76: ), Chris@76: 'data' => array( Chris@76: 'sprintf' => array( Chris@76: 'format' => '', Chris@76: 'params' => array( Chris@76: 'id_ban_group' => false, Chris@76: ), Chris@76: ), Chris@76: 'style' => 'text-align: center', Chris@76: ), Chris@76: ), Chris@76: ), Chris@76: 'form' => array( Chris@76: 'href' => $scripturl . '?action=admin;area=ban;sa=list', Chris@76: ), Chris@76: 'additional_rows' => array( Chris@76: array( Chris@76: 'position' => 'below_table_data', Chris@76: 'value' => '', Chris@76: 'style' => 'text-align: right;', Chris@76: ), Chris@76: ), Chris@76: ); Chris@76: Chris@76: require_once($sourcedir . '/Subs-List.php'); Chris@76: createList($listOptions); Chris@76: Chris@76: $context['sub_template'] = 'show_list'; Chris@76: $context['default_list'] = 'ban_list'; Chris@76: } Chris@76: Chris@76: function list_getBans($start, $items_per_page, $sort) Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT bg.id_ban_group, bg.name, bg.ban_time, bg.expire_time, bg.reason, bg.notes, COUNT(bi.id_ban) AS num_triggers Chris@76: FROM {db_prefix}ban_groups AS bg Chris@76: LEFT JOIN {db_prefix}ban_items AS bi ON (bi.id_ban_group = bg.id_ban_group) Chris@76: GROUP BY bg.id_ban_group, bg.name, bg.ban_time, bg.expire_time, bg.reason, bg.notes Chris@76: ORDER BY {raw:sort} Chris@76: LIMIT {int:offset}, {int:limit}', Chris@76: array( Chris@76: 'sort' => $sort, Chris@76: 'offset' => $start, Chris@76: 'limit' => $items_per_page, Chris@76: ) Chris@76: ); Chris@76: $bans = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $bans[] = $row; Chris@76: Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: return $bans; Chris@76: } Chris@76: Chris@76: function list_getNumBans() Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT COUNT(*) AS num_bans Chris@76: FROM {db_prefix}ban_groups', Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: list ($numBans) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: return $numBans; Chris@76: } Chris@76: Chris@76: function BanEdit() Chris@76: { Chris@76: global $txt, $modSettings, $context, $ban_request, $scripturl, $smcFunc; Chris@76: Chris@76: $_REQUEST['bg'] = empty($_REQUEST['bg']) ? 0 : (int) $_REQUEST['bg']; Chris@76: Chris@76: // Adding or editing a ban trigger? Chris@76: if (!empty($_POST['add_new_trigger']) || !empty($_POST['edit_trigger'])) Chris@76: { Chris@76: checkSession(); Chris@76: Chris@76: $newBan = !empty($_POST['add_new_trigger']); Chris@76: $values = array( Chris@76: 'id_ban_group' => $_REQUEST['bg'], Chris@76: 'hostname' => '', Chris@76: 'email_address' => '', Chris@76: 'id_member' => 0, Chris@76: 'ip_low1' => 0, Chris@76: 'ip_high1' => 0, Chris@76: 'ip_low2' => 0, Chris@76: 'ip_high2' => 0, Chris@76: 'ip_low3' => 0, Chris@76: 'ip_high3' => 0, Chris@76: 'ip_low4' => 0, Chris@76: 'ip_high4' => 0, Chris@76: ); Chris@76: Chris@76: // Preset all values that are required. Chris@76: if ($newBan) Chris@76: { Chris@76: $insertKeys = array( Chris@76: 'id_ban_group' => 'int', Chris@76: 'hostname' => 'string', Chris@76: 'email_address' => 'string', Chris@76: 'id_member' => 'int', Chris@76: 'ip_low1' => 'int', Chris@76: 'ip_high1' => 'int', Chris@76: 'ip_low2' => 'int', Chris@76: 'ip_high2' => 'int', Chris@76: 'ip_low3' => 'int', Chris@76: 'ip_high3' => 'int', Chris@76: 'ip_low4' => 'int', Chris@76: 'ip_high4' => 'int', Chris@76: ); Chris@76: } Chris@76: else Chris@76: $updateString = ' Chris@76: hostname = {string:hostname}, email_address = {string:email_address}, id_member = {int:id_member}, Chris@76: ip_low1 = {int:ip_low1}, ip_high1 = {int:ip_high1}, Chris@76: ip_low2 = {int:ip_low2}, ip_high2 = {int:ip_high2}, Chris@76: ip_low3 = {int:ip_low3}, ip_high3 = {int:ip_high3}, Chris@76: ip_low4 = {int:ip_low4}, ip_high4 = {int:ip_high4}'; Chris@76: Chris@76: if ($_POST['bantype'] == 'ip_ban') Chris@76: { Chris@76: $ip = trim($_POST['ip']); Chris@76: $ip_parts = ip2range($ip); Chris@76: $ip_check = checkExistingTriggerIP($ip_parts, $ip); Chris@76: if (!$ip_check) Chris@76: fatal_lang_error('invalid_ip', false); Chris@76: $values = array_merge($values, $ip_check); Chris@76: Chris@76: $modlogInfo['ip_range'] = $_POST['ip']; Chris@76: } Chris@76: elseif ($_POST['bantype'] == 'hostname_ban') Chris@76: { Chris@76: if (preg_match('/[^\w.\-*]/', $_POST['hostname']) == 1) Chris@76: fatal_lang_error('invalid_hostname', false); Chris@76: Chris@76: // Replace the * wildcard by a MySQL compatible wildcard %. Chris@76: $_POST['hostname'] = str_replace('*', '%', $_POST['hostname']); Chris@76: Chris@76: $values['hostname'] = $_POST['hostname']; Chris@76: Chris@76: $modlogInfo['hostname'] = $_POST['hostname']; Chris@76: } Chris@76: elseif ($_POST['bantype'] == 'email_ban') Chris@76: { Chris@76: if (preg_match('/[^\w.\-\+*@]/', $_POST['email']) == 1) Chris@76: fatal_lang_error('invalid_email', false); Chris@76: $_POST['email'] = strtolower(str_replace('*', '%', $_POST['email'])); Chris@76: Chris@76: // Check the user is not banning an admin. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_member Chris@76: FROM {db_prefix}members Chris@76: WHERE (id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups) != 0) Chris@76: AND email_address LIKE {string:email} Chris@76: LIMIT 1', Chris@76: array( Chris@76: 'admin_group' => 1, Chris@76: 'email' => $_POST['email'], Chris@76: ) Chris@76: ); Chris@76: if ($smcFunc['db_num_rows']($request) != 0) Chris@76: fatal_lang_error('no_ban_admin', 'critical'); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: $values['email_address'] = $_POST['email']; Chris@76: Chris@76: $modlogInfo['email'] = $_POST['email']; Chris@76: } Chris@76: elseif ($_POST['bantype'] == 'user_ban') Chris@76: { Chris@76: $_POST['user'] = preg_replace('~&#(\d{4,5}|[2-9]\d{2,4}|1[2-9]\d);~', '&#$1;', $smcFunc['htmlspecialchars']($_POST['user'], ENT_QUOTES)); Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_member, (id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups) != 0) AS isAdmin Chris@76: FROM {db_prefix}members Chris@76: WHERE member_name = {string:user_name} OR real_name = {string:user_name} Chris@76: LIMIT 1', Chris@76: array( Chris@76: 'admin_group' => 1, Chris@76: 'user_name' => $_POST['user'], Chris@76: ) Chris@76: ); Chris@76: if ($smcFunc['db_num_rows']($request) == 0) Chris@76: fatal_lang_error('invalid_username', false); Chris@76: list ($memberid, $isAdmin) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: if ($isAdmin && $isAdmin != 'f') Chris@76: fatal_lang_error('no_ban_admin', 'critical'); Chris@76: Chris@76: $values['id_member'] = $memberid; Chris@76: Chris@76: $modlogInfo['member'] = $memberid; Chris@76: } Chris@76: else Chris@76: fatal_lang_error('no_bantype_selected', false); Chris@76: Chris@76: if ($newBan) Chris@76: $smcFunc['db_insert']('', Chris@76: '{db_prefix}ban_items', Chris@76: $insertKeys, Chris@76: $values, Chris@76: array('id_ban') Chris@76: ); Chris@76: else Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}ban_items Chris@76: SET ' . $updateString . ' Chris@76: WHERE id_ban = {int:ban_item} Chris@76: AND id_ban_group = {int:id_ban_group}', Chris@76: array_merge($values, array( Chris@76: 'ban_item' => (int) $_REQUEST['bi'], Chris@76: )) Chris@76: ); Chris@76: Chris@76: // Log the addion of the ban entry into the moderation log. Chris@76: logAction('ban', $modlogInfo + array( Chris@76: 'new' => $newBan, Chris@76: 'type' => $_POST['bantype'], Chris@76: )); Chris@76: Chris@76: // Register the last modified date. Chris@76: updateSettings(array('banLastUpdated' => time())); Chris@76: Chris@76: // Update the member table to represent the new ban situation. Chris@76: updateBanMembers(); Chris@76: } Chris@76: Chris@76: // The user pressed 'Remove selected ban entries'. Chris@76: elseif (!empty($_POST['remove_selection']) && !empty($_POST['ban_items']) && is_array($_POST['ban_items'])) Chris@76: { Chris@76: checkSession(); Chris@76: Chris@76: // Making sure every deleted ban item is an integer. Chris@76: foreach ($_POST['ban_items'] as $key => $value) Chris@76: $_POST['ban_items'][$key] = (int) $value; Chris@76: Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}ban_items Chris@76: WHERE id_ban IN ({array_int:ban_list}) Chris@76: AND id_ban_group = {int:ban_group}', Chris@76: array( Chris@76: 'ban_list' => $_POST['ban_items'], Chris@76: 'ban_group' => $_REQUEST['bg'], Chris@76: ) Chris@76: ); Chris@76: Chris@76: // It changed, let the settings and the member table know. Chris@76: updateSettings(array('banLastUpdated' => time())); Chris@76: updateBanMembers(); Chris@76: } Chris@76: Chris@76: // Modify OR add a ban. Chris@76: elseif (!empty($_POST['modify_ban']) || !empty($_POST['add_ban'])) Chris@76: { Chris@76: checkSession(); Chris@76: Chris@76: $addBan = !empty($_POST['add_ban']); Chris@76: if (empty($_POST['ban_name'])) Chris@76: fatal_lang_error('ban_name_empty', false); Chris@76: Chris@76: // Let's not allow HTML in ban names, it's more evil than beneficial. Chris@76: $_POST['ban_name'] = $smcFunc['htmlspecialchars']($_POST['ban_name'], ENT_QUOTES); Chris@76: Chris@76: // Check whether a ban with this name already exists. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_ban_group Chris@76: FROM {db_prefix}ban_groups Chris@76: WHERE name = {string:new_ban_name}' . ($addBan ? '' : ' Chris@76: AND id_ban_group != {int:ban_group}') . ' Chris@76: LIMIT 1', Chris@76: array( Chris@76: 'ban_group' => $_REQUEST['bg'], Chris@76: 'new_ban_name' => $_POST['ban_name'], Chris@76: ) Chris@76: ); Chris@76: if ($smcFunc['db_num_rows']($request) == 1) Chris@76: fatal_lang_error('ban_name_exists', false, array($_POST['ban_name'])); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: $_POST['reason'] = $smcFunc['htmlspecialchars']($_POST['reason'], ENT_QUOTES); Chris@76: $_POST['notes'] = $smcFunc['htmlspecialchars']($_POST['notes'], ENT_QUOTES); Chris@76: $_POST['notes'] = str_replace(array("\r", "\n", ' '), array('', '
', '  '), $_POST['notes']); Chris@76: $_POST['expiration'] = $_POST['expiration'] == 'never' ? 'NULL' : ($_POST['expiration'] == 'expired' ? '0' : ($_POST['expire_date'] != $_POST['old_expire'] ? time() + 24 * 60 * 60 * (int) $_POST['expire_date'] : 'expire_time')); Chris@76: $_POST['full_ban'] = empty($_POST['full_ban']) ? '0' : '1'; Chris@76: $_POST['cannot_post'] = !empty($_POST['full_ban']) || empty($_POST['cannot_post']) ? '0' : '1'; Chris@76: $_POST['cannot_register'] = !empty($_POST['full_ban']) || empty($_POST['cannot_register']) ? '0' : '1'; Chris@76: $_POST['cannot_login'] = !empty($_POST['full_ban']) || empty($_POST['cannot_login']) ? '0' : '1'; Chris@76: Chris@76: if ($addBan) Chris@76: { Chris@76: // Adding some ban triggers? Chris@76: if ($addBan && !empty($_POST['ban_suggestion']) && is_array($_POST['ban_suggestion'])) Chris@76: { Chris@76: $ban_triggers = array(); Chris@76: $ban_logs = array(); Chris@76: if (in_array('main_ip', $_POST['ban_suggestion']) && !empty($_POST['main_ip'])) Chris@76: { Chris@76: $ip = trim($_POST['main_ip']); Chris@76: $ip_parts = ip2range($ip); Chris@76: if (!checkExistingTriggerIP($ip_parts, $ip)) Chris@76: fatal_lang_error('invalid_ip', false); Chris@76: Chris@76: $ban_triggers[] = array( Chris@76: $ip_parts[0]['low'], Chris@76: $ip_parts[0]['high'], Chris@76: $ip_parts[1]['low'], Chris@76: $ip_parts[1]['high'], Chris@76: $ip_parts[2]['low'], Chris@76: $ip_parts[2]['high'], Chris@76: $ip_parts[3]['low'], Chris@76: $ip_parts[3]['high'], Chris@76: '', Chris@76: '', Chris@76: 0, Chris@76: ); Chris@76: Chris@76: $ban_logs[] = array( Chris@76: 'ip_range' => $_POST['main_ip'], Chris@76: ); Chris@76: } Chris@76: if (in_array('hostname', $_POST['ban_suggestion']) && !empty($_POST['hostname'])) Chris@76: { Chris@76: if (preg_match('/[^\w.\-*]/', $_POST['hostname']) == 1) Chris@76: fatal_lang_error('invalid_hostname', false); Chris@76: Chris@76: // Replace the * wildcard by a MySQL wildcard %. Chris@76: $_POST['hostname'] = str_replace('*', '%', $_POST['hostname']); Chris@76: Chris@76: $ban_triggers[] = array( Chris@76: 0, 0, 0, 0, 0, 0, 0, 0, Chris@76: substr($_POST['hostname'], 0, 255), Chris@76: '', Chris@76: 0, Chris@76: ); Chris@76: $ban_logs[] = array( Chris@76: 'hostname' => $_POST['hostname'], Chris@76: ); Chris@76: } Chris@76: if (in_array('email', $_POST['ban_suggestion']) && !empty($_POST['email'])) Chris@76: { Chris@76: if (preg_match('/[^\w.\-\+*@]/', $_POST['email']) == 1) Chris@76: fatal_lang_error('invalid_email', false); Chris@76: $_POST['email'] = strtolower(str_replace('*', '%', $_POST['email'])); Chris@76: Chris@76: $ban_triggers[] = array( Chris@76: 0, 0, 0, 0, 0, 0, 0, 0, Chris@76: '', Chris@76: substr($_POST['email'], 0, 255), Chris@76: 0, Chris@76: ); Chris@76: $ban_logs[] = array( Chris@76: 'email' => $_POST['email'], Chris@76: ); Chris@76: } Chris@76: if (in_array('user', $_POST['ban_suggestion']) && (!empty($_POST['bannedUser']) || !empty($_POST['user']))) Chris@76: { Chris@76: // We got a username, let's find its ID. Chris@76: if (empty($_POST['bannedUser'])) Chris@76: { Chris@76: $_POST['user'] = preg_replace('~&#(\d{4,5}|[2-9]\d{2,4}|1[2-9]\d);~', '&#$1;', $smcFunc['htmlspecialchars']($_POST['user'], ENT_QUOTES)); Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_member, (id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups) != 0) AS isAdmin Chris@76: FROM {db_prefix}members Chris@76: WHERE member_name = {string:username} OR real_name = {string:username} Chris@76: LIMIT 1', Chris@76: array( Chris@76: 'admin_group' => 1, Chris@76: 'username' => $_POST['user'], Chris@76: ) Chris@76: ); Chris@76: if ($smcFunc['db_num_rows']($request) == 0) Chris@76: fatal_lang_error('invalid_username', false); Chris@76: list ($_POST['bannedUser'], $isAdmin) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: if ($isAdmin && $isAdmin != 'f') Chris@76: fatal_lang_error('no_ban_admin', 'critical'); Chris@76: } Chris@76: Chris@76: $ban_triggers[] = array( Chris@76: 0, 0, 0, 0, 0, 0, 0, 0, Chris@76: '', Chris@76: '', Chris@76: (int) $_POST['bannedUser'], Chris@76: ); Chris@76: $ban_logs[] = array( Chris@76: 'member' => $_POST['bannedUser'], Chris@76: ); Chris@76: } Chris@76: Chris@76: if (!empty($_POST['ban_suggestion']['ips']) && is_array($_POST['ban_suggestion']['ips'])) Chris@76: { Chris@76: $_POST['ban_suggestion']['ips'] = array_unique($_POST['ban_suggestion']['ips']); Chris@76: Chris@76: // Don't add the main IP again. Chris@76: if (in_array('main_ip', $_POST['ban_suggestion'])) Chris@76: $_POST['ban_suggestion']['ips'] = array_diff($_POST['ban_suggestion']['ips'], array($_POST['main_ip'])); Chris@76: Chris@76: foreach ($_POST['ban_suggestion']['ips'] as $ip) Chris@76: { Chris@76: $ip_parts = ip2range($ip); Chris@76: Chris@76: // They should be alright, but just to be sure... Chris@76: if (count($ip_parts) != 4) Chris@76: fatal_lang_error('invalid_ip', false); Chris@76: Chris@76: $ban_triggers[] = array( Chris@76: $ip_parts[0]['low'], Chris@76: $ip_parts[0]['high'], Chris@76: $ip_parts[1]['low'], Chris@76: $ip_parts[1]['high'], Chris@76: $ip_parts[2]['low'], Chris@76: $ip_parts[2]['high'], Chris@76: $ip_parts[3]['low'], Chris@76: $ip_parts[3]['high'], Chris@76: '', Chris@76: '', Chris@76: 0, Chris@76: ); Chris@76: $ban_logs[] = array( Chris@76: 'ip_range' => $ip, Chris@76: ); Chris@76: } Chris@76: } Chris@76: } Chris@76: Chris@76: // Yes yes, we're ready to add now. Chris@76: $smcFunc['db_insert']('', Chris@76: '{db_prefix}ban_groups', Chris@76: array( Chris@76: 'name' => 'string-20', 'ban_time' => 'int', 'expire_time' => 'raw', 'cannot_access' => 'int', 'cannot_register' => 'int', Chris@76: 'cannot_post' => 'int', 'cannot_login' => 'int', 'reason' => 'string-255', 'notes' => 'string-65534', Chris@76: ), Chris@76: array( Chris@76: $_POST['ban_name'], time(), $_POST['expiration'], $_POST['full_ban'], $_POST['cannot_register'], Chris@76: $_POST['cannot_post'], $_POST['cannot_login'], $_POST['reason'], $_POST['notes'], Chris@76: ), Chris@76: array('id_ban_group') Chris@76: ); Chris@76: $_REQUEST['bg'] = $smcFunc['db_insert_id']('{db_prefix}ban_groups', 'id_ban_group'); Chris@76: Chris@76: // Now that the ban group is added, add some triggers as well. Chris@76: if (!empty($ban_triggers) && !empty($_REQUEST['bg'])) Chris@76: { Chris@76: // Put in the ban group ID. Chris@76: foreach ($ban_triggers as $k => $trigger) Chris@76: array_unshift($ban_triggers[$k], $_REQUEST['bg']); Chris@76: Chris@76: // Log what we are doing! Chris@76: foreach ($ban_logs as $log_details) Chris@76: logAction('ban', $log_details + array('new' => 1)); Chris@76: Chris@76: $smcFunc['db_insert']('', Chris@76: '{db_prefix}ban_items', Chris@76: array( Chris@76: 'id_ban_group' => 'int', 'ip_low1' => 'int', 'ip_high1' => 'int', 'ip_low2' => 'int', 'ip_high2' => 'int', Chris@76: 'ip_low3' => 'int', 'ip_high3' => 'int', 'ip_low4' => 'int', 'ip_high4' => 'int', 'hostname' => 'string-255', Chris@76: 'email_address' => 'string-255', 'id_member' => 'int', Chris@76: ), Chris@76: $ban_triggers, Chris@76: array('id_ban') Chris@76: ); Chris@76: } Chris@76: } Chris@76: else Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}ban_groups Chris@76: SET Chris@76: name = {string:ban_name}, Chris@76: reason = {string:reason}, Chris@76: notes = {string:notes}, Chris@76: expire_time = {raw:expiration}, Chris@76: cannot_access = {int:cannot_access}, Chris@76: cannot_post = {int:cannot_post}, Chris@76: cannot_register = {int:cannot_register}, Chris@76: cannot_login = {int:cannot_login} Chris@76: WHERE id_ban_group = {int:id_ban_group}', Chris@76: array( Chris@76: 'expiration' => $_POST['expiration'], Chris@76: 'cannot_access' => $_POST['full_ban'], Chris@76: 'cannot_post' => $_POST['cannot_post'], Chris@76: 'cannot_register' => $_POST['cannot_register'], Chris@76: 'cannot_login' => $_POST['cannot_login'], Chris@76: 'id_ban_group' => $_REQUEST['bg'], Chris@76: 'ban_name' => $_POST['ban_name'], Chris@76: 'reason' => $_POST['reason'], Chris@76: 'notes' => $_POST['notes'], Chris@76: ) Chris@76: ); Chris@76: Chris@76: // No more caching, we have something new here. Chris@76: updateSettings(array('banLastUpdated' => time())); Chris@76: updateBanMembers(); Chris@76: } Chris@76: Chris@76: // If we're editing an existing ban, get it from the database. Chris@76: if (!empty($_REQUEST['bg'])) Chris@76: { Chris@76: $context['ban_items'] = array(); Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT Chris@76: bi.id_ban, bi.hostname, bi.email_address, bi.id_member, bi.hits, Chris@76: bi.ip_low1, bi.ip_high1, bi.ip_low2, bi.ip_high2, bi.ip_low3, bi.ip_high3, bi.ip_low4, bi.ip_high4, Chris@76: bg.id_ban_group, bg.name, bg.ban_time, bg.expire_time, bg.reason, bg.notes, bg.cannot_access, bg.cannot_register, bg.cannot_login, bg.cannot_post, Chris@76: IFNULL(mem.id_member, 0) AS id_member, mem.member_name, mem.real_name Chris@76: FROM {db_prefix}ban_groups AS bg Chris@76: LEFT JOIN {db_prefix}ban_items AS bi ON (bi.id_ban_group = bg.id_ban_group) Chris@76: LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = bi.id_member) Chris@76: WHERE bg.id_ban_group = {int:current_ban}', Chris@76: array( Chris@76: 'current_ban' => $_REQUEST['bg'], Chris@76: ) Chris@76: ); Chris@76: if ($smcFunc['db_num_rows']($request) == 0) Chris@76: fatal_lang_error('ban_not_found', false); Chris@76: Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: { Chris@76: if (!isset($context['ban'])) Chris@76: { Chris@76: $context['ban'] = array( Chris@76: 'id' => $row['id_ban_group'], Chris@76: 'name' => $row['name'], Chris@76: 'expiration' => array( Chris@76: 'status' => $row['expire_time'] === null ? 'never' : ($row['expire_time'] < time() ? 'expired' : 'still_active_but_we_re_counting_the_days'), Chris@76: 'days' => $row['expire_time'] > time() ? floor(($row['expire_time'] - time()) / 86400) : 0 Chris@76: ), Chris@76: 'reason' => $row['reason'], Chris@76: 'notes' => $row['notes'], Chris@76: 'cannot' => array( Chris@76: 'access' => !empty($row['cannot_access']), Chris@76: 'post' => !empty($row['cannot_post']), Chris@76: 'register' => !empty($row['cannot_register']), Chris@76: 'login' => !empty($row['cannot_login']), Chris@76: ), Chris@76: 'is_new' => false, Chris@76: ); Chris@76: } Chris@76: if (!empty($row['id_ban'])) Chris@76: { Chris@76: $context['ban_items'][$row['id_ban']] = array( Chris@76: 'id' => $row['id_ban'], Chris@76: 'hits' => $row['hits'], Chris@76: ); Chris@76: if (!empty($row['ip_high1'])) Chris@76: { Chris@76: $context['ban_items'][$row['id_ban']]['type'] = 'ip'; Chris@76: $context['ban_items'][$row['id_ban']]['ip'] = range2ip(array($row['ip_low1'], $row['ip_low2'], $row['ip_low3'], $row['ip_low4']), array($row['ip_high1'], $row['ip_high2'], $row['ip_high3'], $row['ip_high4'])); Chris@76: } Chris@76: elseif (!empty($row['hostname'])) Chris@76: { Chris@76: $context['ban_items'][$row['id_ban']]['type'] = 'hostname'; Chris@76: $context['ban_items'][$row['id_ban']]['hostname'] = str_replace('%', '*', $row['hostname']); Chris@76: } Chris@76: elseif (!empty($row['email_address'])) Chris@76: { Chris@76: $context['ban_items'][$row['id_ban']]['type'] = 'email'; Chris@76: $context['ban_items'][$row['id_ban']]['email'] = str_replace('%', '*', $row['email_address']); Chris@76: } Chris@76: elseif (!empty($row['id_member'])) Chris@76: { Chris@76: $context['ban_items'][$row['id_ban']]['type'] = 'user'; Chris@76: $context['ban_items'][$row['id_ban']]['user'] = array( Chris@76: 'id' => $row['id_member'], Chris@76: 'name' => $row['real_name'], Chris@76: 'href' => $scripturl . '?action=profile;u=' . $row['id_member'], Chris@76: 'link' => '' . $row['real_name'] . '', Chris@76: ); Chris@76: } Chris@76: // Invalid ban (member probably doesn't exist anymore). Chris@76: else Chris@76: { Chris@76: unset($context['ban_items'][$row['id_ban']]); Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}ban_items Chris@76: WHERE id_ban = {int:current_ban}', Chris@76: array( Chris@76: 'current_ban' => $row['id_ban'], Chris@76: ) Chris@76: ); Chris@76: } Chris@76: } Chris@76: } Chris@76: $smcFunc['db_free_result']($request); Chris@76: } Chris@76: // Not an existing one, then it's probably a new one. Chris@76: else Chris@76: { Chris@76: $context['ban'] = array( Chris@76: 'id' => 0, Chris@76: 'name' => '', Chris@76: 'expiration' => array( Chris@76: 'status' => 'never', Chris@76: 'days' => 0 Chris@76: ), Chris@76: 'reason' => '', Chris@76: 'notes' => '', Chris@76: 'ban_days' => 0, Chris@76: 'cannot' => array( Chris@76: 'access' => true, Chris@76: 'post' => false, Chris@76: 'register' => false, Chris@76: 'login' => false, Chris@76: ), Chris@76: 'is_new' => true, Chris@76: ); Chris@76: $context['ban_suggestions'] = array( Chris@76: 'main_ip' => '', Chris@76: 'hostname' => '', Chris@76: 'email' => '', Chris@76: 'member' => array( Chris@76: 'id' => 0, Chris@76: ), Chris@76: ); Chris@76: Chris@76: // Overwrite some of the default form values if a user ID was given. Chris@76: if (!empty($_REQUEST['u'])) Chris@76: { Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_member, real_name, member_ip, email_address Chris@76: FROM {db_prefix}members Chris@76: WHERE id_member = {int:current_user} Chris@76: LIMIT 1', Chris@76: array( Chris@76: 'current_user' => (int) $_REQUEST['u'], Chris@76: ) Chris@76: ); Chris@76: if ($smcFunc['db_num_rows']($request) > 0) Chris@76: list ($context['ban_suggestions']['member']['id'], $context['ban_suggestions']['member']['name'], $context['ban_suggestions']['main_ip'], $context['ban_suggestions']['email']) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: if (!empty($context['ban_suggestions']['member']['id'])) Chris@76: { Chris@76: $context['ban_suggestions']['href'] = $scripturl . '?action=profile;u=' . $context['ban_suggestions']['member']['id']; Chris@76: $context['ban_suggestions']['member']['link'] = '' . $context['ban_suggestions']['member']['name'] . ''; Chris@76: Chris@76: // Default the ban name to the name of the banned member. Chris@76: $context['ban']['name'] = $context['ban_suggestions']['member']['name']; Chris@76: Chris@76: // Would be nice if we could also ban the hostname. Chris@76: if (preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $context['ban_suggestions']['main_ip']) == 1 && empty($modSettings['disableHostnameLookup'])) Chris@76: $context['ban_suggestions']['hostname'] = host_from_ip($context['ban_suggestions']['main_ip']); Chris@76: Chris@76: // Find some additional IP's used by this member. Chris@76: $context['ban_suggestions']['message_ips'] = array(); Chris@76: $request = $smcFunc['db_query']('ban_suggest_message_ips', ' Chris@76: SELECT DISTINCT poster_ip Chris@76: FROM {db_prefix}messages Chris@76: WHERE id_member = {int:current_user} Chris@76: AND poster_ip RLIKE {string:poster_ip_regex} Chris@76: ORDER BY poster_ip', Chris@76: array( Chris@76: 'current_user' => (int) $_REQUEST['u'], Chris@76: 'poster_ip_regex' => '^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$', Chris@76: ) Chris@76: ); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $context['ban_suggestions']['message_ips'][] = $row['poster_ip']; Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: $context['ban_suggestions']['error_ips'] = array(); Chris@76: $request = $smcFunc['db_query']('ban_suggest_error_ips', ' Chris@76: SELECT DISTINCT ip Chris@76: FROM {db_prefix}log_errors Chris@76: WHERE id_member = {int:current_user} Chris@76: AND ip RLIKE {string:poster_ip_regex} Chris@76: ORDER BY ip', Chris@76: array( Chris@76: 'current_user' => (int) $_REQUEST['u'], Chris@76: 'poster_ip_regex' => '^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$', Chris@76: ) Chris@76: ); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $context['ban_suggestions']['error_ips'][] = $row['ip']; Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // Borrowing a few language strings from profile. Chris@76: loadLanguage('Profile'); Chris@76: } Chris@76: } Chris@76: } Chris@76: Chris@76: // Template needs this to show errors using javascript Chris@76: loadLanguage('Errors'); Chris@76: Chris@76: // If we're in wireless mode remove the admin template layer and use a special template. Chris@76: if (WIRELESS && WIRELESS_PROTOCOL != 'wap') Chris@76: { Chris@76: $context['sub_template'] = WIRELESS_PROTOCOL . '_ban_edit'; Chris@76: foreach ($context['template_layers'] as $k => $v) Chris@76: if (strpos($v, 'generic_menu') === 0) Chris@76: unset($context['template_layers'][$k]); Chris@76: } Chris@76: else Chris@76: $context['sub_template'] = 'ban_edit'; Chris@76: } Chris@76: Chris@76: function BanEditTrigger() Chris@76: { Chris@76: global $context, $smcFunc; Chris@76: Chris@76: $context['sub_template'] = 'ban_edit_trigger'; Chris@76: Chris@76: if (empty($_REQUEST['bg'])) Chris@76: fatal_lang_error('ban_not_found', false); Chris@76: Chris@76: if (empty($_REQUEST['bi'])) Chris@76: { Chris@76: $context['ban_trigger'] = array( Chris@76: 'id' => 0, Chris@76: 'group' => (int) $_REQUEST['bg'], Chris@76: 'ip' => array( Chris@76: 'value' => '', Chris@76: 'selected' => true, Chris@76: ), Chris@76: 'hostname' => array( Chris@76: 'selected' => false, Chris@76: 'value' => '', Chris@76: ), Chris@76: 'email' => array( Chris@76: 'value' => '', Chris@76: 'selected' => false, Chris@76: ), Chris@76: 'banneduser' => array( Chris@76: 'value' => '', Chris@76: 'selected' => false, Chris@76: ), Chris@76: 'is_new' => true, Chris@76: ); Chris@76: } Chris@76: else Chris@76: { Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT Chris@76: bi.id_ban, bi.id_ban_group, bi.hostname, bi.email_address, bi.id_member, Chris@76: bi.ip_low1, bi.ip_high1, bi.ip_low2, bi.ip_high2, bi.ip_low3, bi.ip_high3, bi.ip_low4, bi.ip_high4, Chris@76: mem.member_name, mem.real_name Chris@76: FROM {db_prefix}ban_items AS bi Chris@76: LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = bi.id_member) Chris@76: WHERE bi.id_ban = {int:ban_item} Chris@76: AND bi.id_ban_group = {int:ban_group} Chris@76: LIMIT 1', Chris@76: array( Chris@76: 'ban_item' => (int) $_REQUEST['bi'], Chris@76: 'ban_group' => (int) $_REQUEST['bg'], Chris@76: ) Chris@76: ); Chris@76: if ($smcFunc['db_num_rows']($request) == 0) Chris@76: fatal_lang_error('ban_not_found', false); Chris@76: $row = $smcFunc['db_fetch_assoc']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: $context['ban_trigger'] = array( Chris@76: 'id' => $row['id_ban'], Chris@76: 'group' => $row['id_ban_group'], Chris@76: 'ip' => array( Chris@76: 'value' => empty($row['ip_low1']) ? '' : range2ip(array($row['ip_low1'], $row['ip_low2'], $row['ip_low3'], $row['ip_low4']), array($row['ip_high1'], $row['ip_high2'], $row['ip_high3'], $row['ip_high4'])), Chris@76: 'selected' => !empty($row['ip_low1']), Chris@76: ), Chris@76: 'hostname' => array( Chris@76: 'value' => str_replace('%', '*', $row['hostname']), Chris@76: 'selected' => !empty($row['hostname']), Chris@76: ), Chris@76: 'email' => array( Chris@76: 'value' => str_replace('%', '*', $row['email_address']), Chris@76: 'selected' => !empty($row['email_address']) Chris@76: ), Chris@76: 'banneduser' => array( Chris@76: 'value' => $row['member_name'], Chris@76: 'selected' => !empty($row['member_name']) Chris@76: ), Chris@76: 'is_new' => false, Chris@76: ); Chris@76: } Chris@76: } Chris@76: Chris@76: function BanBrowseTriggers() Chris@76: { Chris@76: global $modSettings, $context, $scripturl, $smcFunc, $txt; Chris@76: global $sourcedir, $settings; Chris@76: Chris@76: if (!empty($_POST['remove_triggers']) && !empty($_POST['remove']) && is_array($_POST['remove'])) Chris@76: { Chris@76: checkSession(); Chris@76: Chris@76: // Clean the integers. Chris@76: foreach ($_POST['remove'] as $key => $value) Chris@76: $_POST['remove'][$key] = $value; Chris@76: Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}ban_items Chris@76: WHERE id_ban IN ({array_int:ban_list})', Chris@76: array( Chris@76: 'ban_list' => $_POST['remove'], Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Rehabilitate some members. Chris@76: if ($_REQUEST['entity'] == 'member') Chris@76: updateBanMembers(); Chris@76: Chris@76: // Make sure the ban cache is refreshed. Chris@76: updateSettings(array('banLastUpdated' => time())); Chris@76: } Chris@76: Chris@76: $context['selected_entity'] = isset($_REQUEST['entity']) && in_array($_REQUEST['entity'], array('ip', 'hostname', 'email', 'member')) ? $_REQUEST['entity'] : 'ip'; Chris@76: Chris@76: $listOptions = array( Chris@76: 'id' => 'ban_trigger_list', Chris@76: 'title' => $txt['ban_trigger_browse'], Chris@76: 'items_per_page' => $modSettings['defaultMaxMessages'], Chris@76: 'base_href' => $scripturl . '?action=admin;area=ban;sa=browse;entity=' . $context['selected_entity'], Chris@76: 'default_sort_col' => 'banned_entity', Chris@76: 'no_items_label' => $txt['ban_no_triggers'], Chris@76: 'get_items' => array( Chris@76: 'function' => 'list_getBanTriggers', Chris@76: 'params' => array( Chris@76: $context['selected_entity'], Chris@76: ), Chris@76: ), Chris@76: 'get_count' => array( Chris@76: 'function' => 'list_getNumBanTriggers', Chris@76: 'params' => array( Chris@76: $context['selected_entity'], Chris@76: ), Chris@76: ), Chris@76: 'columns' => array( Chris@76: 'banned_entity' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['ban_banned_entity'], Chris@76: ), Chris@76: ), Chris@76: 'ban_name' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['ban_name'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'sprintf' => array( Chris@76: 'format' => '%2$s', Chris@76: 'params' => array( Chris@76: 'id_ban_group' => false, Chris@76: 'name' => false, Chris@76: ), Chris@76: ), Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'bg.name', Chris@76: 'reverse' => 'bg.name DESC', Chris@76: ), Chris@76: ), Chris@76: 'hits' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['ban_hits'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'db' => 'hits', Chris@76: 'style' => 'text-align: center;', Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'bi.hits DESC', Chris@76: 'reverse' => 'bi.hits', Chris@76: ), Chris@76: ), Chris@76: 'check' => array( Chris@76: 'header' => array( Chris@76: 'value' => '', Chris@76: ), Chris@76: 'data' => array( Chris@76: 'sprintf' => array( Chris@76: 'format' => '', Chris@76: 'params' => array( Chris@76: 'id_ban' => false, Chris@76: ), Chris@76: ), Chris@76: 'style' => 'text-align: center', Chris@76: ), Chris@76: ), Chris@76: ), Chris@76: 'form' => array( Chris@76: 'href' => $scripturl . '?action=admin;area=ban;sa=browse;entity=' . $context['selected_entity'], Chris@76: 'include_start' => true, Chris@76: 'include_sort' => true, Chris@76: ), Chris@76: 'additional_rows' => array( Chris@76: array( Chris@76: 'position' => 'above_column_headers', Chris@76: 'value' => '' . ($context['selected_entity'] == 'ip' ? '> ' : '') . $txt['ip'] . ' | ' . ($context['selected_entity'] == 'hostname' ? '> ' : '') . $txt['hostname'] . ' | ' . ($context['selected_entity'] == 'email' ? '> ' : '') . $txt['email'] . ' | ' . ($context['selected_entity'] == 'member' ? '> ' : '') . $txt['username'] . '', Chris@76: ), Chris@76: array( Chris@76: 'position' => 'below_table_data', Chris@76: 'value' => '', Chris@76: 'style' => 'text-align: right;', Chris@76: ), Chris@76: ), Chris@76: ); Chris@76: Chris@76: // Specific data for the first column depending on the selected entity. Chris@76: if ($context['selected_entity'] === 'ip') Chris@76: { Chris@76: $listOptions['columns']['banned_entity']['data'] = array( Chris@76: 'function' => create_function('$rowData', ' Chris@76: return range2ip(array( Chris@76: $rowData[\'ip_low1\'], Chris@76: $rowData[\'ip_low2\'], Chris@76: $rowData[\'ip_low3\'], Chris@76: $rowData[\'ip_low4\'] Chris@76: ), array( Chris@76: $rowData[\'ip_high1\'], Chris@76: $rowData[\'ip_high2\'], Chris@76: $rowData[\'ip_high3\'], Chris@76: $rowData[\'ip_high4\'] Chris@76: )); Chris@76: '), Chris@76: ); Chris@76: $listOptions['columns']['banned_entity']['sort'] = array( Chris@76: 'default' => 'bi.ip_low1, bi.ip_high1, bi.ip_low2, bi.ip_high2, bi.ip_low3, bi.ip_high3, bi.ip_low4, bi.ip_high4', Chris@76: 'reverse' => 'bi.ip_low1 DESC, bi.ip_high1 DESC, bi.ip_low2 DESC, bi.ip_high2 DESC, bi.ip_low3 DESC, bi.ip_high3 DESC, bi.ip_low4 DESC, bi.ip_high4 DESC', Chris@76: ); Chris@76: } Chris@76: elseif ($context['selected_entity'] === 'hostname') Chris@76: { Chris@76: $listOptions['columns']['banned_entity']['data'] = array( Chris@76: 'function' => create_function('$rowData', ' Chris@76: global $smcFunc; Chris@76: return strtr($smcFunc[\'htmlspecialchars\']($rowData[\'hostname\']), array(\'%\' => \'*\')); Chris@76: '), Chris@76: ); Chris@76: $listOptions['columns']['banned_entity']['sort'] = array( Chris@76: 'default' => 'bi.hostname', Chris@76: 'reverse' => 'bi.hostname DESC', Chris@76: ); Chris@76: } Chris@76: elseif ($context['selected_entity'] === 'email') Chris@76: { Chris@76: $listOptions['columns']['banned_entity']['data'] = array( Chris@76: 'function' => create_function('$rowData', ' Chris@76: global $smcFunc; Chris@76: return strtr($smcFunc[\'htmlspecialchars\']($rowData[\'email_address\']), array(\'%\' => \'*\')); Chris@76: '), Chris@76: ); Chris@76: $listOptions['columns']['banned_entity']['sort'] = array( Chris@76: 'default' => 'bi.email_address', Chris@76: 'reverse' => 'bi.email_address DESC', Chris@76: ); Chris@76: } Chris@76: elseif ($context['selected_entity'] === 'member') Chris@76: { Chris@76: $listOptions['columns']['banned_entity']['data'] = array( Chris@76: 'sprintf' => array( Chris@76: 'format' => '%2$s', Chris@76: 'params' => array( Chris@76: 'id_member' => false, Chris@76: 'real_name' => false, Chris@76: ), Chris@76: ), Chris@76: ); Chris@76: $listOptions['columns']['banned_entity']['sort'] = array( Chris@76: 'default' => 'mem.real_name', Chris@76: 'reverse' => 'mem.real_name DESC', Chris@76: ); Chris@76: } Chris@76: Chris@76: // Create the list. Chris@76: require_once($sourcedir . '/Subs-List.php'); Chris@76: createList($listOptions); Chris@76: Chris@76: // The list is the only thing to show, so make it the default sub template. Chris@76: $context['sub_template'] = 'show_list'; Chris@76: $context['default_list'] = 'ban_trigger_list'; Chris@76: } Chris@76: Chris@76: function list_getBanTriggers($start, $items_per_page, $sort, $trigger_type) Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: $where = array( Chris@76: 'ip' => 'bi.ip_low1 > 0', Chris@76: 'hostname' => 'bi.hostname != {string:blank_string}', Chris@76: 'email' => 'bi.email_address != {string:blank_string}', Chris@76: ); Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT Chris@76: bi.id_ban, bi.ip_low1, bi.ip_high1, bi.ip_low2, bi.ip_high2, bi.ip_low3, bi.ip_high3, bi.ip_low4, bi.ip_high4, bi.hostname, bi.email_address, bi.hits, Chris@76: bg.id_ban_group, bg.name' . ($trigger_type === 'member' ? ', Chris@76: mem.id_member, mem.real_name' : '') . ' Chris@76: FROM {db_prefix}ban_items AS bi Chris@76: INNER JOIN {db_prefix}ban_groups AS bg ON (bg.id_ban_group = bi.id_ban_group)' . ($trigger_type === 'member' ? ' Chris@76: INNER JOIN {db_prefix}members AS mem ON (mem.id_member = bi.id_member)' : ' Chris@76: WHERE ' . $where[$trigger_type]) . ' Chris@76: ORDER BY ' . $sort . ' Chris@76: LIMIT ' . $start . ', ' . $items_per_page, Chris@76: array( Chris@76: 'blank_string' => '', Chris@76: ) Chris@76: ); Chris@76: $ban_triggers = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $ban_triggers[] = $row; Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: return $ban_triggers; Chris@76: } Chris@76: Chris@76: function list_getNumBanTriggers($trigger_type) Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: $where = array( Chris@76: 'ip' => 'bi.ip_low1 > 0', Chris@76: 'hostname' => 'bi.hostname != {string:blank_string}', Chris@76: 'email' => 'bi.email_address != {string:blank_string}', Chris@76: ); Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT COUNT(*) Chris@76: FROM {db_prefix}ban_items AS bi' . ($trigger_type === 'member' ? ' Chris@76: INNER JOIN {db_prefix}members AS mem ON (mem.id_member = bi.id_member)' : ' Chris@76: WHERE ' . $where[$trigger_type]), Chris@76: array( Chris@76: 'blank_string' => '', Chris@76: ) Chris@76: ); Chris@76: list ($num_triggers) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: return $num_triggers; Chris@76: } Chris@76: Chris@76: function BanLog() Chris@76: { Chris@76: global $scripturl, $context, $smcFunc, $sourcedir, $txt; Chris@76: global $context; Chris@76: Chris@76: // Delete one or more entries. Chris@76: if (!empty($_POST['removeAll']) || (!empty($_POST['removeSelected']) && !empty($_POST['remove']))) Chris@76: { Chris@76: checkSession(); Chris@76: Chris@76: // 'Delete all entries' button was pressed. Chris@76: if (!empty($_POST['removeAll'])) Chris@76: $smcFunc['db_query']('truncate_table', ' Chris@76: TRUNCATE {db_prefix}log_banned', Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: Chris@76: // 'Delte selection' button was pressed. Chris@76: else Chris@76: { Chris@76: // Make sure every entry is integer. Chris@76: foreach ($_POST['remove'] as $index => $log_id) Chris@76: $_POST['remove'][$index] = (int) $log_id; Chris@76: Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}log_banned Chris@76: WHERE id_ban_log IN ({array_int:ban_list})', Chris@76: array( Chris@76: 'ban_list' => $_POST['remove'], Chris@76: ) Chris@76: ); Chris@76: } Chris@76: } Chris@76: Chris@76: $listOptions = array( Chris@76: 'id' => 'ban_log', Chris@76: 'items_per_page' => 30, Chris@76: 'base_href' => $context['admin_area'] == 'ban' ? $scripturl . '?action=admin;area=ban;sa=log' : $scripturl . '?action=admin;area=logs;sa=banlog', Chris@76: 'default_sort_col' => 'date', Chris@76: 'get_items' => array( Chris@76: 'function' => 'list_getBanLogEntries', Chris@76: ), Chris@76: 'get_count' => array( Chris@76: 'function' => 'list_getNumBanLogEntries', Chris@76: ), Chris@76: 'no_items_label' => $txt['ban_log_no_entries'], Chris@76: 'columns' => array( Chris@76: 'ip' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['ban_log_ip'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'sprintf' => array( Chris@76: 'format' => '%1$s', Chris@76: 'params' => array( Chris@76: 'ip' => false, Chris@76: ), Chris@76: ), Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'lb.ip', Chris@76: 'reverse' => 'lb.ip DESC', Chris@76: ), Chris@76: ), Chris@76: 'email' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['ban_log_email'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'db_htmlsafe' => 'email', Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'lb.email = \'\', lb.email', Chris@76: 'reverse' => 'lb.email != \'\', lb.email DESC', Chris@76: ), Chris@76: ), Chris@76: 'member' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['ban_log_member'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'sprintf' => array( Chris@76: 'format' => '%2$s', Chris@76: 'params' => array( Chris@76: 'id_member' => false, Chris@76: 'real_name' => false, Chris@76: ), Chris@76: ), Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'IFNULL(mem.real_name, 1=1), mem.real_name', Chris@76: 'reverse' => 'IFNULL(mem.real_name, 1=1) DESC, mem.real_name DESC', Chris@76: ), Chris@76: ), Chris@76: 'date' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['ban_log_date'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'function' => create_function('$rowData', ' Chris@76: return timeformat($rowData[\'log_time\']); Chris@76: '), Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'lb.log_time DESC', Chris@76: 'reverse' => 'lb.log_time', Chris@76: ), Chris@76: ), Chris@76: 'check' => array( Chris@76: 'header' => array( Chris@76: 'value' => '', Chris@76: ), Chris@76: 'data' => array( Chris@76: 'sprintf' => array( Chris@76: 'format' => '', Chris@76: 'params' => array( Chris@76: 'id_ban_log' => false, Chris@76: ), Chris@76: ), Chris@76: 'style' => 'text-align: center', Chris@76: ), Chris@76: ), Chris@76: ), Chris@76: 'form' => array( Chris@76: 'href' => $context['admin_area'] == 'ban' ? $scripturl . '?action=admin;area=ban;sa=log' : $scripturl . '?action=admin;area=logs;sa=banlog', Chris@76: 'include_start' => true, Chris@76: 'include_sort' => true, Chris@76: ), Chris@76: 'additional_rows' => array( Chris@76: array( Chris@76: 'position' => 'below_table_data', Chris@76: 'value' => ' Chris@76: Chris@76: ', Chris@76: 'style' => 'text-align: right;', Chris@76: ), Chris@76: ), Chris@76: ); Chris@76: Chris@76: require_once($sourcedir . '/Subs-List.php'); Chris@76: createList($listOptions); Chris@76: Chris@76: $context['page_title'] = $txt['ban_log']; Chris@76: $context['sub_template'] = 'show_list'; Chris@76: $context['default_list'] = 'ban_log'; Chris@76: } Chris@76: Chris@76: function list_getBanLogEntries($start, $items_per_page, $sort) Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT lb.id_ban_log, lb.id_member, IFNULL(lb.ip, {string:dash}) AS ip, IFNULL(lb.email, {string:dash}) AS email, lb.log_time, IFNULL(mem.real_name, {string:blank_string}) AS real_name Chris@76: FROM {db_prefix}log_banned AS lb Chris@76: LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lb.id_member) Chris@76: ORDER BY ' . $sort . ' Chris@76: LIMIT ' . $start . ', ' . $items_per_page, Chris@76: array( Chris@76: 'blank_string' => '', Chris@76: 'dash' => '-', Chris@76: ) Chris@76: ); Chris@76: $log_entries = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $log_entries[] = $row; Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: return $log_entries; Chris@76: } Chris@76: Chris@76: function list_getNumBanLogEntries() Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT COUNT(*) Chris@76: FROM {db_prefix}log_banned AS lb', Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: list ($num_entries) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: return $num_entries; Chris@76: } Chris@76: Chris@76: function range2ip($low, $high) Chris@76: { Chris@76: if (count($low) != 4 || count($high) != 4) Chris@76: return ''; Chris@76: Chris@76: $ip = array(); Chris@76: for ($i = 0; $i < 4; $i++) Chris@76: { Chris@76: if ($low[$i] == $high[$i]) Chris@76: $ip[$i] = $low[$i]; Chris@76: elseif ($low[$i] == '0' && $high[$i] == '255') Chris@76: $ip[$i] = '*'; Chris@76: else Chris@76: $ip[$i] = $low[$i] . '-' . $high[$i]; Chris@76: } Chris@76: Chris@76: // Pretending is fun... the IP can't be this, so use it for 'unknown'. Chris@76: if ($ip == array(255, 255, 255, 255)) Chris@76: return 'unknown'; Chris@76: Chris@76: return implode('.', $ip); Chris@76: } Chris@76: Chris@76: function checkExistingTriggerIP($ip_array, $fullip = '') Chris@76: { Chris@76: global $smcFunc, $scripturl; Chris@76: Chris@76: if (count($ip_array) == 4) Chris@76: $values = array( Chris@76: 'ip_low1' => $ip_array[0]['low'], Chris@76: 'ip_high1' => $ip_array[0]['high'], Chris@76: 'ip_low2' => $ip_array[1]['low'], Chris@76: 'ip_high2' => $ip_array[1]['high'], Chris@76: 'ip_low3' => $ip_array[2]['low'], Chris@76: 'ip_high3' => $ip_array[2]['high'], Chris@76: 'ip_low4' => $ip_array[3]['low'], Chris@76: 'ip_high4' => $ip_array[3]['high'], Chris@76: ); Chris@76: else Chris@76: return false; Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT bg.id_ban_group, bg.name Chris@76: FROM {db_prefix}ban_groups AS bg Chris@76: INNER JOIN {db_prefix}ban_items AS bi ON Chris@76: (bi.id_ban_group = bg.id_ban_group) Chris@76: AND ip_low1 = {int:ip_low1} AND ip_high1 = {int:ip_high1} Chris@76: AND ip_low2 = {int:ip_low2} AND ip_high2 = {int:ip_high2} Chris@76: AND ip_low3 = {int:ip_low3} AND ip_high3 = {int:ip_high3} Chris@76: AND ip_low4 = {int:ip_low4} AND ip_high4 = {int:ip_high4} Chris@76: LIMIT 1', Chris@76: $values Chris@76: ); Chris@76: if ($smcFunc['db_num_rows']($request) != 0) Chris@76: { Chris@76: list ($error_id_ban, $error_ban_name) = $smcFunc['db_fetch_row']($request); Chris@76: fatal_lang_error('ban_trigger_already_exists', false, array( Chris@76: $fullip, Chris@76: '' . $error_ban_name . '', Chris@76: )); Chris@76: } Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: return $values; Chris@76: } Chris@76: Chris@76: function updateBanMembers() Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: $updates = array(); Chris@76: $allMembers = array(); Chris@76: $newMembers = array(); Chris@76: Chris@76: // Start by getting all active bans - it's quicker doing this in parts... Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT bi.id_member, bi.email_address Chris@76: FROM {db_prefix}ban_items AS bi Chris@76: INNER JOIN {db_prefix}ban_groups AS bg ON (bg.id_ban_group = bi.id_ban_group) Chris@76: WHERE (bi.id_member > {int:no_member} OR bi.email_address != {string:blank_string}) Chris@76: AND bg.cannot_access = {int:cannot_access_on} Chris@76: AND (bg.expire_time IS NULL OR bg.expire_time > {int:current_time})', Chris@76: array( Chris@76: 'no_member' => 0, Chris@76: 'cannot_access_on' => 1, Chris@76: 'current_time' => time(), Chris@76: 'blank_string' => '', Chris@76: ) Chris@76: ); Chris@76: $memberIDs = array(); Chris@76: $memberEmails = array(); Chris@76: $memberEmailWild = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: { Chris@76: if ($row['id_member']) Chris@76: $memberIDs[$row['id_member']] = $row['id_member']; Chris@76: if ($row['email_address']) Chris@76: { Chris@76: // Does it have a wildcard - if so we can't do a IN on it. Chris@76: if (strpos($row['email_address'], '%') !== false) Chris@76: $memberEmailWild[$row['email_address']] = $row['email_address']; Chris@76: else Chris@76: $memberEmails[$row['email_address']] = $row['email_address']; Chris@76: } Chris@76: } Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // Build up the query. Chris@76: $queryPart = array(); Chris@76: $queryValues = array(); Chris@76: if (!empty($memberIDs)) Chris@76: { Chris@76: $queryPart[] = 'mem.id_member IN ({array_string:member_ids})'; Chris@76: $queryValues['member_ids'] = $memberIDs; Chris@76: } Chris@76: if (!empty($memberEmails)) Chris@76: { Chris@76: $queryPart[] = 'mem.email_address IN ({array_string:member_emails})'; Chris@76: $queryValues['member_emails'] = $memberEmails; Chris@76: } Chris@76: $count = 0; Chris@76: foreach ($memberEmailWild as $email) Chris@76: { Chris@76: $queryPart[] = 'mem.email_address LIKE {string:wild_' . $count . '}'; Chris@76: $queryValues['wild_' . $count++] = $email; Chris@76: } Chris@76: Chris@76: // Find all banned members. Chris@76: if (!empty($queryPart)) Chris@76: { Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT mem.id_member, mem.is_activated Chris@76: FROM {db_prefix}members AS mem Chris@76: WHERE ' . implode( ' OR ', $queryPart), Chris@76: $queryValues Chris@76: ); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: { Chris@76: if (!in_array($row['id_member'], $allMembers)) Chris@76: { Chris@76: $allMembers[] = $row['id_member']; Chris@76: // Do they need an update? Chris@76: if ($row['is_activated'] < 10) Chris@76: { Chris@76: $updates[($row['is_activated'] + 10)][] = $row['id_member']; Chris@76: $newMembers[] = $row['id_member']; Chris@76: } Chris@76: } Chris@76: } Chris@76: $smcFunc['db_free_result']($request); Chris@76: } Chris@76: Chris@76: // We welcome our new members in the realm of the banned. Chris@76: if (!empty($newMembers)) Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}log_online Chris@76: WHERE id_member IN ({array_int:new_banned_members})', Chris@76: array( Chris@76: 'new_banned_members' => $newMembers, Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Find members that are wrongfully marked as banned. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT mem.id_member, mem.is_activated - 10 AS new_value Chris@76: FROM {db_prefix}members AS mem Chris@76: LEFT JOIN {db_prefix}ban_items AS bi ON (bi.id_member = mem.id_member OR mem.email_address LIKE bi.email_address) Chris@76: LEFT JOIN {db_prefix}ban_groups AS bg ON (bg.id_ban_group = bi.id_ban_group AND bg.cannot_access = {int:cannot_access_activated} AND (bg.expire_time IS NULL OR bg.expire_time > {int:current_time})) Chris@76: WHERE (bi.id_ban IS NULL OR bg.id_ban_group IS NULL) Chris@76: AND mem.is_activated >= {int:ban_flag}', Chris@76: array( Chris@76: 'cannot_access_activated' => 1, Chris@76: 'current_time' => time(), Chris@76: 'ban_flag' => 10, Chris@76: ) Chris@76: ); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: { Chris@76: // Don't do this twice! Chris@76: if (!in_array($row['id_member'], $allMembers)) Chris@76: { Chris@76: $updates[$row['new_value']][] = $row['id_member']; Chris@76: $allMembers[] = $row['id_member']; Chris@76: } Chris@76: } Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: if (!empty($updates)) Chris@76: foreach ($updates as $newStatus => $members) Chris@76: updateMemberData($members, array('is_activated' => $newStatus)); Chris@76: Chris@76: // Update the latest member and our total members as banning may change them. Chris@76: updateStats('member'); Chris@76: } Chris@76: Chris@76: ?>