/** * @param type $message the message: this must run before bb codes are parsed, * because user tags are translated to bb codes. * @return type int - an array of member ids that were tagged in the message. * the array contains unique ids only. */ function handleUserTags(&$message) { global $user_info, $modSettings, $context; $users_found = array(); if (!isset($context['can_tag_users']) || !$context['can_tag_users'] || isset($_REQUEST['allowtags']) && $_REQUEST['allowtags'] || empty($modSettings['enableUserTagging']) || 0 == $modSettings['maxTagsPerPost']) { return $users_found; } $pat = '~@@([\\s\\w,;-_\\[\\]\\{\\}\\\\/\\+\\.\\~\\$\\!]+):~u'; $matches = array(); $querynames = array(); $searchnames = array(); $displaynames = array(); /* * maximum number of unique tagged users a single message can have. defaults to 10, but never more than * 20 which should be waaaaaay enough anyway and we don't want to abuse this feature. */ $max_unique_tags = empty($modSettings['maxTagsPerPost']) ? 10 : min(array(20, $modSettings['maxTagsPerPost'])); /* * collect all @mentions and build an array of unique, lowercased * names to use in the db query. */ if (preg_match_all($pat, $message, $matches, PREG_SET_ORDER)) { foreach ($matches as $match) { $names = explode(',', trim($match[1])); foreach ($names as $name) { $querynames[] = CommonAPI::strtolower(trim($name)); } } } else { return $users_found; } // nothing to see here, sir... $querynames = array_slice(array_unique($querynames), 0, $max_unique_tags); $result = smf_db_query('SELECT id_member, real_name FROM {db_prefix}members WHERE LOWER(real_name) IN({array_string:names})', array('names' => array_unique($querynames))); while ($row = mysql_fetch_assoc($result)) { $searchnames[$row['id_member']] = CommonAPI::strtolower($row['real_name']); // this is for the lookup $displaynames[$row['id_member']] = $row['real_name']; // ... and this for pretty-formatting the output } mysql_free_result($result); reset($matches); /* * look at our matches again and build the formatted result(s). Filter out any names * that couldn't be found in the db query (mis-spelled, non-existing or whatever... simply ignore them). */ foreach ($matches as $match) { $bbc_results = array(); $names = explode(',', trim($match[1])); foreach ($names as $name) { $id = array_search(CommonAPI::strtolower(trim($name)), $searchnames); if ((int) $id > 0 && $id != $user_info['id']) { // trying to be funny and mention yourself? troll alert... :) $bbc_results[] = '[user id=' . $id . ']' . $displaynames[$id] . '[/user]'; $users_found[] = $id; } } $bbc_result = count($bbc_results) ? '@' . implode(', ', $bbc_results) . ':' : ''; $message = str_replace($match[0], $bbc_result, $message); } return array_unique($users_found); }
function loadProfileFields($force_reload = false) { global $context, $profile_fields, $txt, $scripturl, $modSettings, $user_info, $old_profile, $smcFunc, $cur_profile, $language; // Don't load this twice! if (!empty($profile_fields) && !$force_reload) { return; } /* This horrific array defines all the profile fields in the whole world! In general each "field" has one array - the key of which is the database column name associated with said field. Each item can have the following attributes: string $type: The type of field this is - valid types are: - callback: This is a field which has its own callback mechanism for templating. - check: A simple checkbox. - hidden: This doesn't have any visual aspects but may have some validity. - password: A password box. - select: A select box. - text: A string of some description. string $label: The label for this item - default will be $txt[$key] if this isn't set. string $subtext: The subtext (Small label) for this item. int $size: Optional size for a text area. array $input_attr: An array of text strings to be added to the input box for this item. string $value: The value of the item. If not set $cur_profile[$key] is assumed. string $permission: Permission required for this item (Excluded _any/_own subfix which is applied automatically). function $input_validate: A runtime function which validates the element before going to the database. It is passed the relevant $_POST element if it exists and should be treated like a reference. Return types: - true: Element can be stored. - false: Skip this element. - a text string: An error occured - this is the error message. function $preload: A function that is used to load data required for this element to be displayed. Must return true to be displayed at all. string $cast_type: If set casts the element to a certain type. Valid types (bool, int, float). string $save_key: If the index of this element isn't the database column name it can be overriden with this string. bool $is_dummy: If set then nothing is acted upon for this element. bool $enabled: A test to determine whether this is even available - if not is unset. string $link_with: Key which links this field to an overall set. Note that all elements that have a custom input_validate must ensure they set the value of $cur_profile correct to enable the changes to be displayed correctly on submit of the form. */ $profile_fields = array('avatar_choice' => array('type' => 'callback_template', 'callback_name' => 'profile/avatar_select', 'preload' => 'profileLoadAvatarData', 'input_validate' => 'profileSaveAvatarData', 'save_key' => 'avatar'), 'bday1' => array('type' => 'callback_template', 'callback_name' => 'profile/birthdate_select', 'permission' => 'profile_extra', 'preload' => function () { global $cur_profile, $context; // Split up the birthdate.... list($uyear, $umonth, $uday) = explode('-', empty($cur_profile['birthdate']) || $cur_profile['birthdate'] == '0001-01-01' ? '0000-00-00' : $cur_profile['birthdate']); $context['member']['birth_date'] = array('year' => $uyear == '0004' ? '0000' : $uyear, 'month' => $umonth, 'day' => $uday); return true; }, 'input_validate' => function (&$value) { global $profile_vars, $cur_profile; if (isset($_POST['bday2'], $_POST['bday3']) && $value > 0 && $_POST['bday2'] > 0) { // Set to blank? if ((int) $_POST['bday3'] == 1 && (int) $_POST['bday2'] == 1 && (int) $value == 1) { $value = '0001-01-01'; } else { $value = checkdate($value, $_POST['bday2'], $_POST['bday3'] < 4 ? 4 : $_POST['bday3']) ? sprintf('%04d-%02d-%02d', $_POST['bday3'] < 4 ? 4 : $_POST['bday3'], $_POST['bday1'], $_POST['bday2']) : '0001-01-01'; } } else { $value = '0001-01-01'; } $profile_vars['birthdate'] = $value; $cur_profile['birthdate'] = $value; return false; }), 'birthdate' => array('type' => 'hidden', 'permission' => 'profile_extra', 'input_validate' => function (&$value) { global $cur_profile; // !!! Should we check for this year and tell them they made a mistake :P? (based on coppa at least?) if (preg_match('/(\\d{4})[\\-\\., ](\\d{2})[\\-\\., ](\\d{2})/', $value, $dates) === 1) { $value = checkdate($dates[2], $dates[3], $dates[1] < 4 ? 4 : $dates[1]) ? sprintf('%04d-%02d-%02d', $dates[1] < 4 ? 4 : $dates[1], $dates[2], $dates[3]) : '0001-01-01'; return true; } else { $value = empty($cur_profile['birthdate']) ? '0001-01-01' : $cur_profile['birthdate']; return false; } }), 'date_registered' => array('type' => 'text', '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, 'permission' => 'moderate_forum', 'input_validate' => function (&$value) { global $txt, $user_info, $modSettings, $cur_profile, $context; // Bad date! Go try again - please? if (($value = strtotime($value)) === -1) { $value = $cur_profile['date_registered']; return $txt['invalid_registration'] . ' ' . strftime('%d %b %Y ' . (strpos($user_info['time_format'], '%H') !== false ? '%I:%M:%S %p' : '%H:%M:%S'), forum_time(false)); } elseif ($value != $txt['not_applicable'] && $value != strtotime(strftime('%Y-%m-%d', $cur_profile['date_registered'] + ($user_info['time_offset'] + $modSettings['time_offset']) * 3600))) { $value = $value - ($user_info['time_offset'] + $modSettings['time_offset']) * 3600; } else { $value = $cur_profile['date_registered']; } return true; }), 'email_address' => array('type' => 'text', 'label' => $txt['email'], 'subtext' => $txt['valid_email'], 'log_change' => true, 'permission' => 'profile_identity', 'input_validate' => function (&$value) { global $context, $old_profile, $context, $profile_vars, $sourcedir, $modSettings; if (strtolower($value) == strtolower($old_profile['email_address'])) { return false; } $isValid = profileValidateEmail($value, $context['id_member']); // Do they need to revalidate? If so schedule the function! if ($isValid === true && !empty($modSettings['send_validation_onChange']) && !allowedTo('moderate_forum')) { require_once $sourcedir . '/lib/Subs-Members.php'; $profile_vars['validation_code'] = generateValidationCode(); $profile_vars['is_activated'] = 2; $context['profile_execute_on_save'][] = 'profileSendActivation'; unset($context['profile_execute_on_save']['reload_user']); } 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, 'label' => $txt['allow_user_email'], 'permission' => 'profile_identity', 'input_validate' => function (&$value) { $value = $value == 0 ? 1 : 0; return true; }), 'id_group' => array('type' => 'callback_template', 'callback_name' => 'profile/group_manage', 'permission' => 'manage_membergroups', 'preload' => 'profileLoadGroups', 'log_change' => true, 'input_validate' => 'profileSaveGroups'), 'id_theme' => array('type' => 'callback_template', 'callback_name' => 'profile/theme_pick', 'permission' => 'profile_extra', 'enabled' => $modSettings['theme_allow'] || allowedTo('admin_forum'), 'preload' => function () { global $context, $cur_profile, $txt; $request = smf_db_query('SELECT value FROM {db_prefix}themes WHERE id_theme = {int:id_theme} AND variable = {string:variable} LIMIT 1', array('id_theme' => $cur_profile['id_theme'], 'variable' => 'name')); list($name) = mysql_fetch_row($request); mysql_free_result($request); $context['member']['theme'] = array('id' => $cur_profile['id_theme'], 'name' => empty($cur_profile['id_theme']) ? $txt['theme_forum_default'] : $name); return true; }, 'input_validate' => function (&$value) { $value = (int) $value; return true; }), 'karma_good' => array('type' => 'callback_template', 'callback_name' => 'profile/reputation_display', 'permission' => 'admin_forum', 'input_validate' => function (&$value) { global $profile_vars, $cur_profile; $value = (int) $value; if (isset($_POST['karma_bad'])) { $profile_vars['karma_bad'] = $_POST['karma_bad'] != '' ? (int) $_POST['karma_bad'] : 0; $cur_profile['karma_bad'] = $_POST['karma_bad'] != '' ? (int) $_POST['karma_bad'] : 0; } return true; }, 'preload' => function () { global $context, $cur_profile; //$context['member']['karma']['good'] = $cur_profile['karma_good']; //$context['member']['karma']['bad'] = $cur_profile['karma_bad']; return true; }, 'enabled' => !empty($modSettings['karmaMode'])), 'lngfile' => array('type' => 'select', 'options' => 'return $context[\'profile_languages\'];', 'label' => $txt['preferred_language'], 'permission' => 'profile_identity', 'preload' => 'profileLoadLanguages', 'enabled' => !empty($modSettings['userLanguage']), 'value' => empty($cur_profile['lngfile']) ? $language : $cur_profile['lngfile'], 'input_validate' => function (&$value) { global $context, $cur_profile; // Load the languages. profileLoadLanguages(); if (isset($context['profile_languages'][$value])) { if ($context['user']['is_owner']) { $_SESSION['language'] = $value; } return true; } else { $value = $cur_profile['lngfile']; return false; } }), 'location' => array('type' => 'text', 'label' => $txt['location'], 'log_change' => true, 'size' => 50, 'permission' => 'profile_extra'), 'member_name' => array('type' => allowedTo('admin_forum') && isset($_GET['changeusername']) ? 'text' : 'label', 'label' => $txt['username'], 'subtext' => allowedTo('admin_forum') && !isset($_GET['changeusername']) ? '(<a href="' . $scripturl . '?action=profile;u=' . $context['id_member'] . ';area=account;changeusername" style="font-style: italic;">' . $txt['username_change'] . '</a>)' : '', 'log_change' => true, 'permission' => 'profile_identity', 'prehtml' => allowedTo('admin_forum') && isset($_GET['changeusername']) ? '<div class="alert">' . $txt['username_warning'] . '</div>' : '', 'input_validate' => function (&$value) { global $sourcedir, $context, $user_info, $cur_profile; if (allowedTo('admin_forum')) { // We\'ll need this... require_once $sourcedir . '/lib/Subs-Auth.php'; // Maybe they are trying to change their password as well? $resetPassword = true; if (isset($_POST['passwrd1']) && $_POST['passwrd1'] != '' && isset($_POST['passwrd2']) && $_POST['passwrd1'] == $_POST['passwrd2'] && validatePassword($_POST['passwrd1'], $value, array($cur_profile['real_name'], $user_info['username'], $user_info['name'], $user_info['email'])) == null) { $resetPassword = false; } // Do the reset... this will send them an email too. if ($resetPassword) { resetPassword($context['id_member'], $value); } elseif ($value !== null) { validateUsername($context['id_member'], $value); updateMemberData($context['id_member'], array('member_name' => $value)); } } return false; }), 'passwrd1' => array('type' => 'password', 'label' => $txt['choose_pass'], 'subtext' => $txt['password_strength'], 'size' => 20, 'value' => '', 'enabled' => empty($cur_profile['openid_uri']), 'permission' => 'profile_identity', 'save_key' => 'passwd', 'input_validate' => function (&$value) { global $sourcedir, $user_info, $smcFunc, $cur_profile; // If we didn\'t try it then ignore it! if ($value == '') { return false; } // Do the two entries for the password even match? if (!isset($_POST['passwrd2']) || $value != $_POST['passwrd2']) { return 'bad_new_password'; } // Let\'s get the validation function into play... require_once $sourcedir . '/lib/Subs-Auth.php'; $passwordErrors = validatePassword($value, $cur_profile['member_name'], array($cur_profile['real_name'], $user_info['username'], $user_info['name'], $user_info['email'])); // Were there errors? if ($passwordErrors != null) { return 'password_' . $passwordErrors; } // Set up the new password variable... ready for storage. $value = sha1(strtolower($cur_profile['member_name']) . un_htmlspecialchars($value)); return true; }), 'passwrd2' => array('type' => 'password', 'label' => $txt['verify_pass'], 'enabled' => empty($cur_profile['openid_uri']), 'size' => 20, 'value' => '', 'permission' => 'profile_identity', 'is_dummy' => true), 'personal_text' => array('type' => 'text', 'label' => $txt['personal_text'], 'log_change' => true, 'input_attr' => array('maxlength="50"'), 'size' => 50, 'permission' => 'profile_extra'), 'pm_prefs' => array('type' => 'callback_template', 'callback_name' => 'pm/settings', 'permission' => 'pm_read', 'preload' => function () { global $context, $cur_profile; $context['display_mode'] = $cur_profile['pm_prefs'] & 3; $context['send_email'] = $cur_profile['pm_email_notify']; $context['receive_from'] = !empty($cur_profile['pm_receive_from']) ? $cur_profile['pm_receive_from'] : 0; return true; }, 'input_validate' => function (&$value) { global $cur_profile, $profile_vars; // Simple validate and apply the two "sub settings" $value = max(min($value, 2), 0); $cur_profile['pm_email_notify'] = $profile_vars['pm_email_notify'] = max(min((int) $_POST['pm_email_notify'], 2), 0); $cur_profile['pm_receive_from'] = $profile_vars['pm_receive_from'] = max(min((int) $_POST['pm_receive_from'], 4), 0); return true; }), 'posts' => array('type' => 'int', 'label' => $txt['profile_posts'], 'log_change' => true, 'size' => 7, 'permission' => 'moderate_forum', 'input_validate' => function (&$value) { $value = $value != '' ? strtr($value, array(',' => '', '.' => '', ' ' => '')) : 0; return true; }), 'real_name' => array('type' => !empty($modSettings['allow_editDisplayName']) || allowedTo('moderate_forum') ? 'text' : 'label', 'label' => $txt['name'], 'subtext' => $txt['display_name_desc'], 'log_change' => true, 'input_attr' => array('maxlength="60"'), 'permission' => 'profile_identity', 'enabled' => !empty($modSettings['allow_editDisplayName']) || allowedTo('moderate_forum'), 'input_validate' => function (&$value) { global $context, $smcFunc, $sourcedir, $cur_profile; $value = trim(preg_replace('~[\\s]~' . ($context['utf8'] ? 'u' : ''), ' ', $value)); if (trim($value) == '') { return 'no_name'; } elseif (CommonAPI::strlen($value) > 60) { return 'name_too_long'; } elseif ($cur_profile['real_name'] != $value) { require_once $sourcedir . '/lib/Subs-Members.php'; if (isReservedName($value, $context['id_member'])) { return 'name_taken'; } } return true; }), 'secret_question' => array('type' => 'text', 'label' => $txt['secret_question'], 'subtext' => $txt['secret_desc'], 'size' => 50, 'permission' => 'profile_identity'), 'secret_answer' => array('type' => 'text', 'label' => $txt['secret_answer'], 'subtext' => $txt['secret_desc2'], 'size' => 20, 'postinput' => '<span class="smalltext" style="margin-left: 4ex;"><a href="' . $scripturl . '?action=helpadmin;help=secret_why_blank" onclick="return reqWin(this.href);">' . $txt['secret_why_blank'] . '</a></span>', 'value' => '', 'permission' => 'profile_identity', 'input_validate' => function (&$value) { $value = $value != '' ? md5($value) : ''; return true; }), 'signature' => array('type' => 'callback_template', 'callback_name' => allowedTo('profile_signature') ? 'profile/signature_modify' : 'profile/signature_cannot_modify', 'permission' => 'profile_extra', 'enabled' => substr($modSettings['signature_settings'], 0, 1) == 1, 'preload' => 'profileLoadSignatureData', 'input_validate' => 'profileValidateSignature'), 'show_online' => array('type' => 'check', 'label' => $txt['show_online'], 'permission' => 'profile_identity', 'enabled' => !empty($modSettings['allow_hideOnline']) || allowedTo('moderate_forum')), 'smiley_set' => array('type' => 'callback_template', 'callback_name' => 'profile/smiley_pick', 'enabled' => !empty($modSettings['smiley_sets_enable']), 'permission' => 'profile_extra', 'preload' => function () { global $modSettings, $context, $txt, $cur_profile; $context['member']['smiley_set']['id'] = empty($cur_profile['smiley_set']) ? '' : $cur_profile['smiley_set']; $context['smiley_sets'] = explode(',', 'none,,' . $modSettings['smiley_sets_known']); $set_names = explode("\n", $txt['smileys_none'] . "\n" . $txt['smileys_forum_board_default'] . "\n" . $modSettings['smiley_sets_names']); foreach ($context['smiley_sets'] as $i => $set) { $context['smiley_sets'][$i] = array('id' => htmlspecialchars($set), 'name' => htmlspecialchars($set_names[$i]), 'selected' => $set == $context['member']['smiley_set']['id']); if ($context['smiley_sets'][$i]['selected']) { $context['member']['smiley_set']['name'] = $set_names[$i]; } } return true; }, 'input_validate' => function (&$value) { global $modSettings; $smiley_sets = explode(',', $modSettings['smiley_sets_known']); if (!in_array($value, $smiley_sets) && $value != 'none') { $value = ''; } return true; }), 'theme_settings' => array('type' => 'callback_template', 'callback_name' => 'profile/theme_settings', 'permission' => 'profile_extra', 'is_dummy' => true, 'preload' => function () { loadLanguage('Settings'); return true; }), 'time_format' => array('type' => 'callback_template', 'callback_name' => 'profile/timeformat_modify', 'permission' => 'profile_extra', 'preload' => function () { global $context, $user_info, $txt, $cur_profile, $modSettings; $context['easy_timeformats'] = array(array('format' => '', 'title' => $txt['timeformat_default']), array('format' => '%B %d, %Y, %I:%M:%S %p', 'title' => $txt['timeformat_easy1']), array('format' => '%B %d, %Y, %H:%M:%S', 'title' => $txt['timeformat_easy2']), array('format' => '%Y-%m-%d, %H:%M:%S', 'title' => $txt['timeformat_easy3']), array('format' => '%d %B %Y, %H:%M:%S', 'title' => $txt['timeformat_easy4']), array('format' => '%d-%m-%Y, %H:%M:%S', 'title' => $txt['timeformat_easy5'])); $context['member']['time_format'] = $cur_profile['time_format']; $context['current_forum_time'] = strftime($modSettings['time_format'], forum_time(false)) . ' ' . date_default_timezone_get(); $context['current_forum_time_js'] = strftime('%Y,' . ((int) strftime('%m', time() + $modSettings['time_offset'] * 3600) - 1) . ',%d,%H,%M,%S', time() + $modSettings['time_offset'] * 3600); $context['current_forum_time_hour'] = (int) strftime('%H', forum_time(false)); return true; }), 'time_offset' => array('type' => 'callback_template', 'callback_name' => 'profile/timeoffset_modify', 'permission' => 'profile_extra', 'preload' => function () { global $context, $cur_profile; $context['member']['time_offset'] = $cur_profile['time_offset']; return true; }, 'input_validate' => function (&$value) { // Validate the time_offset... $value = (double) strtr($value, ',', '.'); if ($value < -23.5 || $value > 23.5) { return 'bad_offset'; } return true; }), 'usertitle' => array('type' => 'text', 'label' => $txt['custom_title'], 'log_change' => true, 'size' => 50, 'permission' => 'profile_title', 'input_attr' => array('maxlength="50"'), 'enabled' => !empty($modSettings['titlesEnable']))); $disabled_fields = !empty($modSettings['disabled_profile_fields']) ? explode(',', $modSettings['disabled_profile_fields']) : array(); // For each of the above let's take out the bits which don't apply - to save memory and security! foreach ($profile_fields as $key => $field) { // Do we have permission to do this? if (isset($field['permission']) && !allowedTo($context['user']['is_owner'] ? array($field['permission'] . '_own', $field['permission'] . '_any') : $field['permission'] . '_any') && !allowedTo($field['permission'])) { unset($profile_fields[$key]); } // Is it enabled? if (isset($field['enabled']) && !$field['enabled']) { unset($profile_fields[$key]); } // Is it specifically disabled? if (in_array($key, $disabled_fields) || isset($field['link_with']) && in_array($field['link_with'], $disabled_fields)) { unset($profile_fields[$key]); } } }
/** * This function is behind the screen for adding new bans and modifying existing ones. * Adding new bans: * - is accesssed by ?action=admin;area=ban;sa=add. * - uses the ban_edit sub template of the ManageBans template. * Modifying existing bans: * - is accesssed by ?action=admin;area=ban;sa=edit;bg=x * - uses the ban_edit sub template of the ManageBans template. * - shows a list of ban triggers for the specified ban. * - handles submitted forms that add, modify or remove ban triggers. * * @todo insane number of writing to superglobals here... */ function BanEdit() { global $txt, $modSettings, $context, $ban_request, $scripturl; $_REQUEST['bg'] = empty($_REQUEST['bg']) ? 0 : (int) $_REQUEST['bg']; // Adding or editing a ban trigger? if (!empty($_POST['add_new_trigger']) || !empty($_POST['edit_trigger'])) { checkSession(); //validateToken('admin-bet'); $newBan = !empty($_POST['add_new_trigger']); $values = array('id_ban_group' => $_REQUEST['bg'], 'hostname' => '', 'email_address' => '', 'id_member' => 0, 'ip_low1' => 0, 'ip_high1' => 0, 'ip_low2' => 0, 'ip_high2' => 0, 'ip_low3' => 0, 'ip_high3' => 0, 'ip_low4' => 0, 'ip_high4' => 0, 'ip_low5' => 0, 'ip_high5' => 0, 'ip_low6' => 0, 'ip_high6' => 0, 'ip_low7' => 0, 'ip_high7' => 0, 'ip_low8' => 0, 'ip_high8' => 0); // Preset all values that are required. if ($newBan) { $insertKeys = array('id_ban_group' => 'int', 'hostname' => 'string', 'email_address' => 'string', 'id_member' => 'int', 'ip_low1' => 'int', 'ip_high1' => 'int', 'ip_low2' => 'int', 'ip_high2' => 'int', 'ip_low3' => 'int', 'ip_high3' => 'int', 'ip_low4' => 'int', 'ip_high4' => 'int', 'ip_low5' => 'int', 'ip_high5' => 'int', 'ip_low6' => 'int', 'ip_high6' => 'int', 'ip_low7' => 'int', 'ip_high7' => 'int', 'ip_low8' => 'int', 'ip_high8' => 'int'); } else { $updateString = ' hostname = {string:hostname}, email_address = {string:email_address}, id_member = {int:id_member}, ip_low1 = {int:ip_low1}, ip_high1 = {int:ip_high1}, ip_low2 = {int:ip_low2}, ip_high2 = {int:ip_high2}, ip_low3 = {int:ip_low3}, ip_high3 = {int:ip_high3}, ip_low4 = {int:ip_low4}, ip_high4 = {int:ip_high4}, ip_low5 = {int:ip_low5}, ip_high5 = {int:ip_high5}, ip_low6 = {int:ip_low6}, ip_high6 = {int:ip_high6}, ip_low7 = {int:ip_low7}, ip_high7 = {int:ip_high7}, ip_low8 = {int:ip_low8}, ip_high8 = {int:ip_high8}'; } if ($_POST['bantype'] == 'ip_ban') { $ip = trim($_POST['ip']); $ip_parts = ip2range($ip); $ip_check = checkExistingTriggerIP($ip_parts, $ip); if (!$ip_check) { fatal_lang_error('invalid_ip', false); } $values = array_merge($values, $ip_check); $modlogInfo['ip_range'] = $_POST['ip']; } elseif ($_POST['bantype'] == 'hostname_ban') { if (preg_match('/[^\\w.\\-*]/', $_POST['hostname']) == 1) { fatal_lang_error('invalid_hostname', false); } // Replace the * wildcard by a MySQL compatible wildcard %. $_POST['hostname'] = str_replace('*', '%', $_POST['hostname']); $values['hostname'] = $_POST['hostname']; $modlogInfo['hostname'] = $_POST['hostname']; } elseif ($_POST['bantype'] == 'email_ban') { if (preg_match('/[^\\w.\\-\\+*@]/', $_POST['email']) == 1) { fatal_lang_error('invalid_email', false); } $_POST['email'] = strtolower(str_replace('*', '%', $_POST['email'])); // Check the user is not banning an admin. $request = smf_db_query(' SELECT id_member FROM {db_prefix}members WHERE (id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups) != 0) AND email_address LIKE {string:email} LIMIT 1', array('admin_group' => 1, 'email' => $_POST['email'])); if (mysql_num_rows($request) != 0) { fatal_lang_error('no_ban_admin', 'critical'); } mysql_free_result($request); $values['email_address'] = $_POST['email']; $modlogInfo['email'] = $_POST['email']; } elseif ($_POST['bantype'] == 'user_ban') { $_POST['user'] = preg_replace('~&#(\\d{4,5}|[2-9]\\d{2,4}|1[2-9]\\d);~', '&#$1;', CommonAPI::htmlspecialchars($_POST['user'], ENT_QUOTES)); $request = smf_db_query(' SELECT id_member, (id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups) != 0) AS isAdmin FROM {db_prefix}members WHERE member_name = {string:user_name} OR real_name = {string:user_name} LIMIT 1', array('admin_group' => 1, 'user_name' => $_POST['user'])); if (mysql_num_rows($request) == 0) { fatal_lang_error('invalid_username', false); } list($memberid, $isAdmin) = mysql_fetch_row($request); mysql_free_result($request); if ($isAdmin && $isAdmin != 'f') { fatal_lang_error('no_ban_admin', 'critical'); } $values['id_member'] = $memberid; $modlogInfo['member'] = $memberid; } else { fatal_lang_error('no_bantype_selected', false); } if ($newBan) { smf_db_insert('', '{db_prefix}ban_items', $insertKeys, $values, array('id_ban')); } else { smf_db_query(' UPDATE {db_prefix}ban_items SET ' . $updateString . ' WHERE id_ban = {int:ban_item} AND id_ban_group = {int:id_ban_group}', array_merge($values, array('ban_item' => (int) $_REQUEST['bi']))); } // Log the addion of the ban entry into the moderation log. logAction('ban', $modlogInfo + array('new' => $newBan, 'type' => $_POST['bantype'])); // Register the last modified date. updateSettings(array('banLastUpdated' => time())); // Update the member table to represent the new ban situation. updateBanMembers(); } elseif (!empty($_POST['remove_selection']) && !empty($_POST['ban_items']) && is_array($_POST['ban_items'])) { checkSession(); //validateToken('admin-bet'); // Making sure every deleted ban item is an integer. foreach ($_POST['ban_items'] as $key => $value) { $_POST['ban_items'][$key] = (int) $value; } smf_db_query(' DELETE FROM {db_prefix}ban_items WHERE id_ban IN ({array_int:ban_list}) AND id_ban_group = {int:ban_group}', array('ban_list' => $_POST['ban_items'], 'ban_group' => $_REQUEST['bg'])); // It changed, let the settings and the member table know. updateSettings(array('banLastUpdated' => time())); updateBanMembers(); } elseif (!empty($_POST['modify_ban']) || !empty($_POST['add_ban'])) { checkSession(); //validateToken('admin-bet'); $addBan = !empty($_POST['add_ban']); if (empty($_POST['ban_name'])) { fatal_lang_error('ban_name_empty', false); } // Let's not allow HTML in ban names, it's more evil than beneficial. $_POST['ban_name'] = CommonAPI::htmlspecialchars($_POST['ban_name'], ENT_QUOTES); // Check whether a ban with this name already exists. $request = smf_db_query(' SELECT id_ban_group FROM {db_prefix}ban_groups WHERE name = {string:new_ban_name}' . ($addBan ? '' : ' AND id_ban_group != {int:ban_group}') . ' LIMIT 1', array('ban_group' => $_REQUEST['bg'], 'new_ban_name' => $_POST['ban_name'])); if (mysql_num_rows($request) == 1) { fatal_lang_error('ban_name_exists', false, array($_POST['ban_name'])); } mysql_free_result($request); $_POST['reason'] = CommonAPI::htmlspecialchars($_POST['reason'], ENT_QUOTES); $_POST['notes'] = CommonAPI::htmlspecialchars($_POST['notes'], ENT_QUOTES); $_POST['notes'] = str_replace(array("\r", "\n", ' '), array('', '<br />', ' '), $_POST['notes']); $_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')); $_POST['full_ban'] = empty($_POST['full_ban']) ? '0' : '1'; $_POST['cannot_post'] = !empty($_POST['full_ban']) || empty($_POST['cannot_post']) ? '0' : '1'; $_POST['cannot_register'] = !empty($_POST['full_ban']) || empty($_POST['cannot_register']) ? '0' : '1'; $_POST['cannot_login'] = !empty($_POST['full_ban']) || empty($_POST['cannot_login']) ? '0' : '1'; if ($addBan) { // Adding some ban triggers? if ($addBan && !empty($_POST['ban_suggestion']) && is_array($_POST['ban_suggestion'])) { $ban_triggers = array(); $ban_logs = array(); if (in_array('main_ip', $_POST['ban_suggestion']) && !empty($_POST['main_ip'])) { $ip = trim($_POST['main_ip']); $ip_parts = ip2range($ip); if (!checkExistingTriggerIP($ip_parts, $ip)) { fatal_lang_error('invalid_ip', false); } $ban_triggers[] = array($ip_parts[0]['low'], $ip_parts[0]['high'], $ip_parts[1]['low'], $ip_parts[1]['high'], $ip_parts[2]['low'], $ip_parts[2]['high'], $ip_parts[3]['low'], $ip_parts[3]['high'], $ip_parts[4]['low'], $ip_parts[4]['high'], $ip_parts[5]['low'], $ip_parts[5]['high'], $ip_parts[6]['low'], $ip_parts[6]['high'], $ip_parts[7]['low'], $ip_parts[7]['high'], '', '', 0); $ban_logs[] = array('ip_range' => $_POST['main_ip']); } if (in_array('hostname', $_POST['ban_suggestion']) && !empty($_POST['hostname'])) { if (preg_match('/[^\\w.\\-*]/', $_POST['hostname']) == 1) { fatal_lang_error('invalid_hostname', false); } // Replace the * wildcard by a MySQL wildcard %. $_POST['hostname'] = str_replace('*', '%', $_POST['hostname']); $ban_triggers[] = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, substr($_POST['hostname'], 0, 255), '', 0); $ban_logs[] = array('hostname' => $_POST['hostname']); } if (in_array('email', $_POST['ban_suggestion']) && !empty($_POST['email'])) { if (preg_match('/[^\\w.\\-\\+*@]/', $_POST['email']) == 1) { fatal_lang_error('invalid_email', false); } $_POST['email'] = strtolower(str_replace('*', '%', $_POST['email'])); $ban_triggers[] = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', substr($_POST['email'], 0, 255), 0); $ban_logs[] = array('email' => $_POST['email']); } if (in_array('user', $_POST['ban_suggestion']) && (!empty($_POST['bannedUser']) || !empty($_POST['user']))) { // We got a username, let's find its ID. if (empty($_POST['bannedUser'])) { $_POST['user'] = preg_replace('~&#(\\d{4,5}|[2-9]\\d{2,4}|1[2-9]\\d);~', '&#$1;', CommonAPI::htmlspecialchars($_POST['user'], ENT_QUOTES)); $request = smf_db_query(' SELECT id_member, (id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups) != 0) AS isAdmin FROM {db_prefix}members WHERE member_name = {string:username} OR real_name = {string:username} LIMIT 1', array('admin_group' => 1, 'username' => $_POST['user'])); if (mysql_num_rows($request) == 0) { fatal_lang_error('invalid_username', false); } list($_POST['bannedUser'], $isAdmin) = mysql_fetch_row($request); mysql_free_result($request); if ($isAdmin && $isAdmin != 'f') { fatal_lang_error('no_ban_admin', 'critical'); } } $ban_triggers[] = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', (int) $_POST['bannedUser']); $ban_logs[] = array('member' => $_POST['bannedUser']); } if (!empty($_POST['ban_suggestion']['ips']) && is_array($_POST['ban_suggestion']['ips'])) { $_POST['ban_suggestion']['ips'] = array_unique($_POST['ban_suggestion']['ips']); // Don't add the main IP again. if (in_array('main_ip', $_POST['ban_suggestion'])) { $_POST['ban_suggestion']['ips'] = array_diff($_POST['ban_suggestion']['ips'], array($_POST['main_ip'])); } foreach ($_POST['ban_suggestion']['ips'] as $ip) { $ip_parts = ip2range($ip); // They should be alright, but just to be sure... if (count($ip_parts) != 4 || count($ip_parts) != 8) { fatal_lang_error('invalid_ip', false); } $ban_triggers[] = array($ip_parts[0]['low'], $ip_parts[0]['high'], $ip_parts[1]['low'], $ip_parts[1]['high'], $ip_parts[2]['low'], $ip_parts[2]['high'], $ip_parts[3]['low'], $ip_parts[3]['high'], $ip_parts[4]['low'], $ip_parts[4]['high'], $ip_parts[5]['low'], $ip_parts[5]['high'], $ip_parts[6]['low'], $ip_parts[6]['high'], $ip_parts[7]['low'], $ip_parts[7]['high'], '', '', 0); $ban_logs[] = array('ip_range' => $ip); } } } // Yes yes, we're ready to add now. smf_db_insert('', '{db_prefix}ban_groups', array('name' => 'string-20', 'ban_time' => 'int', 'expire_time' => 'raw', 'cannot_access' => 'int', 'cannot_register' => 'int', 'cannot_post' => 'int', 'cannot_login' => 'int', 'reason' => 'string-255', 'notes' => 'string-65534'), array($_POST['ban_name'], time(), $_POST['expiration'], $_POST['full_ban'], $_POST['cannot_register'], $_POST['cannot_post'], $_POST['cannot_login'], $_POST['reason'], $_POST['notes']), array('id_ban_group')); $_REQUEST['bg'] = smf_db_insert_id('{db_prefix}ban_groups', 'id_ban_group'); // Now that the ban group is added, add some triggers as well. if (!empty($ban_triggers) && !empty($_REQUEST['bg'])) { // Put in the ban group ID. foreach ($ban_triggers as $k => $trigger) { array_unshift($ban_triggers[$k], $_REQUEST['bg']); } // Log what we are doing! foreach ($ban_logs as $log_details) { logAction('ban', $log_details + array('new' => 1)); } smf_db_insert('', '{db_prefix}ban_items', array('id_ban_group' => 'int', 'ip_low1' => 'int', 'ip_high1' => 'int', 'ip_low2' => 'int', 'ip_high2' => 'int', 'ip_low3' => 'int', 'ip_high3' => 'int', 'ip_low4' => 'int', 'ip_high4' => 'int', 'ip_low5' => 'int', 'ip_high5' => 'int', 'ip_low6' => 'int', 'ip_high6' => 'int', 'ip_low7' => 'int', 'ip_high7' => 'int', 'ip_low8' => 'int', 'ip_high8' => 'int', 'hostname' => 'string-255', 'email_address' => 'string-255', 'id_member' => 'int'), $ban_triggers, array('id_ban')); } } else { smf_db_query(' UPDATE {db_prefix}ban_groups SET name = {string:ban_name}, reason = {string:reason}, notes = {string:notes}, expire_time = {raw:expiration}, cannot_access = {int:cannot_access}, cannot_post = {int:cannot_post}, cannot_register = {int:cannot_register}, cannot_login = {int:cannot_login} WHERE id_ban_group = {int:id_ban_group}', array('expiration' => $_POST['expiration'], 'cannot_access' => $_POST['full_ban'], 'cannot_post' => $_POST['cannot_post'], 'cannot_register' => $_POST['cannot_register'], 'cannot_login' => $_POST['cannot_login'], 'id_ban_group' => $_REQUEST['bg'], 'ban_name' => $_POST['ban_name'], 'reason' => $_POST['reason'], 'notes' => $_POST['notes'])); } // No more caching, we have something new here. updateSettings(array('banLastUpdated' => time())); updateBanMembers(); } // If we're editing an existing ban, get it from the database. if (!empty($_REQUEST['bg'])) { $context['ban_items'] = array(); $request = smf_db_query(' SELECT bi.id_ban, bi.hostname, bi.email_address, bi.id_member, bi.hits, bi.ip_low1, bi.ip_high1, bi.ip_low2, bi.ip_high2, bi.ip_low3, bi.ip_high3, bi.ip_low4, bi.ip_high4, bi.ip_low5, bi.ip_high5, bi.ip_low6, bi.ip_high6, bi.ip_low7, bi.ip_high7, bi.ip_low8, bi.ip_high8, 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, IFNULL(mem.id_member, 0) AS id_member, mem.member_name, mem.real_name FROM {db_prefix}ban_groups AS bg LEFT JOIN {db_prefix}ban_items AS bi ON (bi.id_ban_group = bg.id_ban_group) LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = bi.id_member) WHERE bg.id_ban_group = {int:current_ban}', array('current_ban' => $_REQUEST['bg'])); if (mysql_num_rows($request) == 0) { fatal_lang_error('ban_not_found', false); } while ($row = mysql_fetch_assoc($request)) { if (!isset($context['ban'])) { $context['ban'] = array('id' => $row['id_ban_group'], 'name' => $row['name'], 'expiration' => array('status' => $row['expire_time'] === null ? 'never' : ($row['expire_time'] < time() ? 'expired' : 'still_active_but_we_re_counting_the_days'), 'days' => $row['expire_time'] > time() ? floor(($row['expire_time'] - time()) / 86400) : 0), 'reason' => $row['reason'], 'notes' => $row['notes'], 'cannot' => array('access' => !empty($row['cannot_access']), 'post' => !empty($row['cannot_post']), 'register' => !empty($row['cannot_register']), 'login' => !empty($row['cannot_login'])), 'is_new' => false); } if (!empty($row['id_ban'])) { $context['ban_items'][$row['id_ban']] = array('id' => $row['id_ban'], 'hits' => $row['hits']); if (!empty($row['ip_high1'])) { $context['ban_items'][$row['id_ban']]['type'] = 'ip'; $context['ban_items'][$row['id_ban']]['ip'] = range2ip(array($row['ip_low1'], $row['ip_low2'], $row['ip_low3'], $row['ip_low4'], $row['ip_low5'], $row['ip_low6'], $row['ip_low7'], $row['ip_low8']), array($row['ip_high1'], $row['ip_high2'], $row['ip_high3'], $row['ip_high4'], $row['ip_high5'], $row['ip_high6'], $row['ip_high7'], $row['ip_high8'])); } elseif (!empty($row['hostname'])) { $context['ban_items'][$row['id_ban']]['type'] = 'hostname'; $context['ban_items'][$row['id_ban']]['hostname'] = str_replace('%', '*', $row['hostname']); } elseif (!empty($row['email_address'])) { $context['ban_items'][$row['id_ban']]['type'] = 'email'; $context['ban_items'][$row['id_ban']]['email'] = str_replace('%', '*', $row['email_address']); } elseif (!empty($row['id_member'])) { $context['ban_items'][$row['id_ban']]['type'] = 'user'; $context['ban_items'][$row['id_ban']]['user'] = array('id' => $row['id_member'], 'name' => $row['real_name'], 'href' => $scripturl . '?action=profile;u=' . $row['id_member'], 'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>'); } else { unset($context['ban_items'][$row['id_ban']]); smf_db_query(' DELETE FROM {db_prefix}ban_items WHERE id_ban = {int:current_ban}', array('current_ban' => $row['id_ban'])); } } } mysql_free_result($request); } else { $context['ban'] = array('id' => 0, 'name' => '', 'expiration' => array('status' => 'never', 'days' => 0), 'reason' => '', 'notes' => '', 'ban_days' => 0, 'cannot' => array('access' => true, 'post' => false, 'register' => false, 'login' => false), 'is_new' => true); $context['ban_suggestions'] = array('main_ip' => '', 'hostname' => '', 'email' => '', 'member' => array('id' => 0)); // Overwrite some of the default form values if a user ID was given. if (!empty($_REQUEST['u'])) { $request = smf_db_query(' SELECT id_member, real_name, member_ip, email_address FROM {db_prefix}members WHERE id_member = {int:current_user} LIMIT 1', array('current_user' => (int) $_REQUEST['u'])); if (mysql_num_rows($request) > 0) { list($context['ban_suggestions']['member']['id'], $context['ban_suggestions']['member']['name'], $context['ban_suggestions']['main_ip'], $context['ban_suggestions']['email']) = mysql_fetch_row($request); } mysql_free_result($request); if (!empty($context['ban_suggestions']['member']['id'])) { $context['ban_suggestions']['href'] = $scripturl . '?action=profile;u=' . $context['ban_suggestions']['member']['id']; $context['ban_suggestions']['member']['link'] = '<a href="' . $context['ban_suggestions']['href'] . '">' . $context['ban_suggestions']['member']['name'] . '</a>'; // Default the ban name to the name of the banned member. $context['ban']['name'] = $context['ban_suggestions']['member']['name']; // Would be nice if we could also ban the hostname. if (preg_match('/^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/', $context['ban_suggestions']['main_ip']) == 1 && empty($modSettings['disableHostnameLookup'])) { $context['ban_suggestions']['hostname'] = host_from_ip($context['ban_suggestions']['main_ip']); } // Find some additional IP's used by this member. $context['ban_suggestions']['message_ips'] = array(); $request = smf_db_query(' SELECT DISTINCT poster_ip FROM {db_prefix}messages WHERE id_member = {int:current_user} AND poster_ip RLIKE {string:poster_ip_regex} ORDER BY poster_ip', array('current_user' => (int) $_REQUEST['u'], 'poster_ip_regex' => '^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$')); while ($row = mysql_fetch_assoc($request)) { $context['ban_suggestions']['message_ips'][] = $row['poster_ip']; } mysql_free_result($request); $context['ban_suggestions']['error_ips'] = array(); $request = smf_db_query(' SELECT DISTINCT ip FROM {db_prefix}log_errors WHERE id_member = {int:current_user} AND ip RLIKE {string:poster_ip_regex} ORDER BY ip', array('current_user' => (int) $_REQUEST['u'], 'poster_ip_regex' => '^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$')); while ($row = mysql_fetch_assoc($request)) { $context['ban_suggestions']['error_ips'][] = $row['ip']; } mysql_free_result($request); // Borrowing a few language strings from profile. loadLanguage('Profile'); } } } // Template needs this to show errors using javascript loadLanguage('Errors'); // If we're in wireless mode remove the admin template layer and use a special template. if (WIRELESS && WIRELESS_PROTOCOL != 'wap') { $context['sub_template'] = WIRELESS_PROTOCOL . '_ban_edit'; foreach ($context['template_layers'] as $k => $v) { if (strpos($v, 'generic_menu') === 0) { unset($context['template_layers'][$k]); } } } else { $context['sub_template'] = 'ban_edit'; } //createToken('admin-bet'); }
... ] } */ } } // for test // set timezone date_default_timezone_set('UTC'); // global variable BASEDIR define('BASEDIR', __DIR__); include BASEDIR . '/Common/Loader.php'; // using PSR-0 coding standard spl_autoload_register('\\Common\\Loader::autoload'); // check user post data $check = new CommonAPI(); // $check->getFiles(); $check->check(); //print_r($check->params); //echo "hello"; // connect database try { // generate database handle $connect = Oracle::getInstance()->connect(); } catch (Exception $e) { throw new Exception("Database connection error: " . mysql_error()); } // test data // new object $ts = new SQL(); /*
/** * Cleans a string of everything but alphanumeric characters * * @param string $string A string to clean * @return string A cleaned up string */ function _cleanString($string) { // Decode the entities first $string = html_entity_decode($string, ENT_QUOTES, 'UTF-8'); // Lowercase string $string = CommonAPI::strtolower($string); // Fix numbers so they search easier (phone numbers, SSN, dates, etc) $string = preg_replace('~([[:digit:]]+)\\pP+(?=[[:digit:]])~u', '', $string); // Last but not least, strip everything out that's not alphanumeric $string = preg_replace('~[^\\pL\\pN]+~u', ' ', $string); return $string; }