public function validateUsernameHandle($username) { global $sourcedir, $smcFunc, $context, $txt; // Clean it up like mother would. $username = preg_replace('~[\\t\\n\\r \\x0B\\0' . ($context['utf8'] ? $context['server']['complex_preg_chars'] ? '\\x{A0}\\x{AD}\\x{2000}-\\x{200F}\\x{201F}\\x{202F}\\x{3000}\\x{FEFF}' : " -‟ ‟ " : '\\x00-\\x08\\x0B\\x0C\\x0E-\\x19\\xA0') . ']+~' . ($context['utf8'] ? 'u' : ''), ' ', $username); if ($smcFunc['strlen']($username) > 25) { $username = $smcFunc['htmltrim']($smcFunc['substr']($username, 0, 25)); } // Only these characters are permitted. if (preg_match('~[<>&"\'=\\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $username)) != 0 || $username == '_' || $username == '|' || strpos($username, '[code') !== false || strpos($username, '[/code') !== false) { return false; } if (stristr($username, $txt['guest_title']) !== false) { return false; } if (trim($username) == '') { return false; } else { require_once $sourcedir . '/Subs-Members.php'; return isReservedName($username, 0, false, false) ? false : true; } }
/** * Actually register the member. * @todo split this function in two functions: * - a function that handles action=register2, which needs no parameter; * - a function that processes the case of OpenID verification. * * @param bool $verifiedOpenID = false */ public function action_register2($verifiedOpenID = false) { global $txt, $modSettings, $context, $user_info; // Start collecting together any errors. $reg_errors = Error_Context::context('register', 0); // We can't validate the token and the session with OpenID enabled. if (!$verifiedOpenID) { checkSession(); if (!validateToken('register', 'post', true, false)) { $reg_errors->addError('token_verification'); } } // Did we save some open ID fields? if ($verifiedOpenID && !empty($context['openid_save_fields'])) { foreach ($context['openid_save_fields'] as $id => $value) { $_POST[$id] = $value; } } // You can't register if it's disabled. if (!empty($modSettings['registration_method']) && $modSettings['registration_method'] == 3) { fatal_lang_error('registration_disabled', false); } // If we're using an agreement checkbox, did they check it? if (!empty($modSettings['checkboxAgreement']) && !empty($_POST['checkbox_agreement'])) { $_SESSION['registration_agreed'] = true; } // Things we don't do for people who have already confirmed their OpenID allegances via register. if (!$verifiedOpenID) { // Well, if you don't agree, you can't register. if (!empty($modSettings['requireAgreement']) && empty($_SESSION['registration_agreed'])) { redirectexit(); } // Make sure they came from *somewhere*, have a session. if (!isset($_SESSION['old_url'])) { redirectexit('action=register'); } // If we don't require an agreement, we need a extra check for coppa. if (empty($modSettings['requireAgreement']) && !empty($modSettings['coppaAge'])) { $_SESSION['skip_coppa'] = !empty($_POST['accept_agreement']); } // Are they under age, and under age users are banned? if (!empty($modSettings['coppaAge']) && empty($modSettings['coppaType']) && empty($_SESSION['skip_coppa'])) { loadLanguage('Login'); fatal_lang_error('under_age_registration_prohibited', false, array($modSettings['coppaAge'])); } // Check the time gate for miscreants. First make sure they came from somewhere that actually set it up. if (empty($_SESSION['register']['timenow']) || empty($_SESSION['register']['limit'])) { redirectexit('action=register'); } // Failing that, check the time limit for exessive speed. if (time() - $_SESSION['register']['timenow'] < $_SESSION['register']['limit']) { loadLanguage('Login'); $reg_errors->addError('too_quickly'); } // Check whether the visual verification code was entered correctly. if (!empty($modSettings['reg_verification'])) { require_once SUBSDIR . '/VerificationControls.class.php'; $verificationOptions = array('id' => 'register'); $context['visual_verification'] = create_control_verification($verificationOptions, true); if (is_array($context['visual_verification'])) { foreach ($context['visual_verification'] as $error) { $reg_errors->addError($error); } } } } foreach ($_POST as $key => $value) { if (!is_array($_POST[$key])) { $_POST[$key] = htmltrim__recursive(str_replace(array("\n", "\r"), '', $_POST[$key])); } } // Collect all extra registration fields someone might have filled in. $possible_strings = array('birthdate', 'time_format', 'buddy_list', 'pm_ignore_list', 'smiley_set', 'personal_text', 'avatar', 'lngfile', 'location', 'secret_question', 'secret_answer', 'website_url', 'website_title'); $possible_ints = array('pm_email_notify', 'notify_types', 'id_theme', 'gender'); $possible_floats = array('time_offset'); $possible_bools = array('notify_announcements', 'notify_regularity', 'notify_send_body', 'hide_email', 'show_online'); if (isset($_POST['secret_answer']) && $_POST['secret_answer'] != '') { $_POST['secret_answer'] = md5($_POST['secret_answer']); } // Needed for isReservedName() and registerMember(). require_once SUBSDIR . '/Members.subs.php'; // Validation... even if we're not a mall. if (isset($_POST['real_name']) && (!empty($modSettings['allow_editDisplayName']) || allowedTo('moderate_forum'))) { $_POST['real_name'] = trim(preg_replace('~[\\t\\n\\r \\x0B\\0\\x{A0}\\x{AD}\\x{2000}-\\x{200F}\\x{201F}\\x{202F}\\x{3000}\\x{FEFF}]+~u', ' ', $_POST['real_name'])); if (trim($_POST['real_name']) != '' && !isReservedName($_POST['real_name']) && Util::strlen($_POST['real_name']) < 60) { $possible_strings[] = 'real_name'; } } // Handle a string as a birthdate... if (isset($_POST['birthdate']) && $_POST['birthdate'] != '') { $_POST['birthdate'] = strftime('%Y-%m-%d', strtotime($_POST['birthdate'])); } elseif (!empty($_POST['bday1']) && !empty($_POST['bday2'])) { $_POST['birthdate'] = sprintf('%04d-%02d-%02d', empty($_POST['bday3']) ? 0 : (int) $_POST['bday3'], (int) $_POST['bday1'], (int) $_POST['bday2']); } // By default assume email is hidden, only show it if we tell it to. $_POST['hide_email'] = !empty($_POST['allow_email']) ? 0 : 1; // Validate the passed language file. if (isset($_POST['lngfile']) && !empty($modSettings['userLanguage'])) { // Do we have any languages? $context['languages'] = getLanguages(); // Did we find it? if (isset($context['languages'][$_POST['lngfile']])) { $_SESSION['language'] = $_POST['lngfile']; } else { unset($_POST['lngfile']); } } else { unset($_POST['lngfile']); } // Some of these fields we may not want. if (!empty($modSettings['registration_fields'])) { // But we might want some of them if the admin asks for them. $standard_fields = array('location', 'gender'); $reg_fields = explode(',', $modSettings['registration_fields']); $exclude_fields = array_diff($standard_fields, $reg_fields); // Website is a little different if (!in_array('website', $reg_fields)) { $exclude_fields = array_merge($exclude_fields, array('website_url', 'website_title')); } // We used to accept signature on registration but it's being abused by spammers these days, so no more. $exclude_fields[] = 'signature'; } else { $exclude_fields = array('signature', 'location', 'gender', 'website_url', 'website_title'); } $possible_strings = array_diff($possible_strings, $exclude_fields); $possible_ints = array_diff($possible_ints, $exclude_fields); $possible_floats = array_diff($possible_floats, $exclude_fields); $possible_bools = array_diff($possible_bools, $exclude_fields); // Set the options needed for registration. $regOptions = array('interface' => 'guest', 'username' => !empty($_POST['user']) ? $_POST['user'] : '', 'email' => !empty($_POST['email']) ? $_POST['email'] : '', 'password' => !empty($_POST['passwrd1']) ? $_POST['passwrd1'] : '', 'password_check' => !empty($_POST['passwrd2']) ? $_POST['passwrd2'] : '', 'openid' => !empty($_POST['openid_identifier']) ? $_POST['openid_identifier'] : '', 'auth_method' => !empty($_POST['authenticate']) ? $_POST['authenticate'] : '', 'check_reserved_name' => true, 'check_password_strength' => true, 'check_email_ban' => true, 'send_welcome_email' => !empty($modSettings['send_welcomeEmail']), 'require' => !empty($modSettings['coppaAge']) && !$verifiedOpenID && empty($_SESSION['skip_coppa']) ? 'coppa' : (empty($modSettings['registration_method']) ? 'nothing' : ($modSettings['registration_method'] == 1 ? 'activation' : 'approval')), 'extra_register_vars' => array(), 'theme_vars' => array()); // Include the additional options that might have been filled in. foreach ($possible_strings as $var) { if (isset($_POST[$var])) { $regOptions['extra_register_vars'][$var] = Util::htmlspecialchars($_POST[$var], ENT_QUOTES); } } foreach ($possible_ints as $var) { if (isset($_POST[$var])) { $regOptions['extra_register_vars'][$var] = (int) $_POST[$var]; } } foreach ($possible_floats as $var) { if (isset($_POST[$var])) { $regOptions['extra_register_vars'][$var] = (double) $_POST[$var]; } } foreach ($possible_bools as $var) { if (isset($_POST[$var])) { $regOptions['extra_register_vars'][$var] = empty($_POST[$var]) ? 0 : 1; } } // Registration options are always default options... if (isset($_POST['default_options'])) { $_POST['options'] = isset($_POST['options']) ? $_POST['options'] + $_POST['default_options'] : $_POST['default_options']; } $regOptions['theme_vars'] = isset($_POST['options']) && is_array($_POST['options']) ? $_POST['options'] : array(); // Make sure they are clean, dammit! $regOptions['theme_vars'] = htmlspecialchars__recursive($regOptions['theme_vars']); // Check whether we have fields that simply MUST be displayed? require_once SUBSDIR . '/Profile.subs.php'; loadCustomFields(0, 'register'); foreach ($context['custom_fields'] as $row) { // Don't allow overriding of the theme variables. if (isset($regOptions['theme_vars'][$row['colname']])) { unset($regOptions['theme_vars'][$row['colname']]); } // Prepare the value! $value = isset($_POST['customfield'][$row['colname']]) ? trim($_POST['customfield'][$row['colname']]) : ''; // We only care for text fields as the others are valid to be empty. if (!in_array($row['type'], array('check', 'select', 'radio'))) { // Is it too long? if ($row['field_length'] && $row['field_length'] < Util::strlen($value)) { $reg_errors->addError(array('custom_field_too_long', array($row['name'], $row['field_length']))); } // Any masks to apply? if ($row['type'] == 'text' && !empty($row['mask']) && $row['mask'] != 'none') { // @todo We never error on this - just ignore it at the moment... if ($row['mask'] == 'email' && !isValidEmail($value)) { $reg_errors->addError(array('custom_field_invalid_email', array($row['name']))); } elseif ($row['mask'] == 'number' && preg_match('~[^\\d]~', $value)) { $reg_errors->addError(array('custom_field_not_number', array($row['name']))); } elseif (substr($row['mask'], 0, 5) == 'regex' && trim($value) !== '' && preg_match(substr($row['mask'], 5), $value) === 0) { $reg_errors->addError(array('custom_field_inproper_format', array($row['name']))); } } } // Is this required but not there? if (trim($value) == '' && $row['show_reg'] > 1) { $reg_errors->addError(array('custom_field_empty', array($row['name']))); } } // Lets check for other errors before trying to register the member. if ($reg_errors->hasErrors()) { $_REQUEST['step'] = 2; // If they've filled in some details but made an error then they need less time to finish $_SESSION['register']['limit'] = 4; return $this->action_register(); } // If they're wanting to use OpenID we need to validate them first. if (empty($_SESSION['openid']['verified']) && !empty($_POST['authenticate']) && $_POST['authenticate'] == 'openid') { // What do we need to save? $save_variables = array(); foreach ($_POST as $k => $v) { if (!in_array($k, array('sc', 'sesc', $context['session_var'], 'passwrd1', 'passwrd2', 'regSubmit'))) { $save_variables[$k] = $v; } } require_once SUBSDIR . '/OpenID.subs.php'; $openID = new OpenID(); $openID->validate($_POST['openid_identifier'], false, $save_variables); } elseif ($verifiedOpenID || (!empty($_POST['openid_identifier']) || !empty($_SESSION['openid']['openid_uri'])) && $_POST['authenticate'] == 'openid') { $regOptions['username'] = !empty($_POST['user']) && trim($_POST['user']) != '' ? $_POST['user'] : $_SESSION['openid']['nickname']; $regOptions['email'] = !empty($_POST['email']) && trim($_POST['email']) != '' ? $_POST['email'] : $_SESSION['openid']['email']; $regOptions['auth_method'] = 'openid'; $regOptions['openid'] = !empty($_SESSION['openid']['openid_uri']) ? $_SESSION['openid']['openid_uri'] : (!empty($_POST['openid_identifier']) ? $_POST['openid_identifier'] : ''); } // Registration needs to know your IP $req = request(); $regOptions['ip'] = $user_info['ip']; $regOptions['ip2'] = $req->ban_ip(); $memberID = registerMember($regOptions, 'register'); // If there are "important" errors and you are not an admin: log the first error // Otherwise grab all of them and don't log anything if ($reg_errors->hasErrors(1) && !$user_info['is_admin']) { foreach ($reg_errors->prepareErrors(1) as $error) { fatal_error($error, 'general'); } } // Was there actually an error of some kind dear boy? if ($reg_errors->hasErrors()) { $_REQUEST['step'] = 2; return $this->action_register(); } // Do our spam protection now. spamProtection('register'); // We'll do custom fields after as then we get to use the helper function! if (!empty($_POST['customfield'])) { require_once SUBSDIR . '/Profile.subs.php'; makeCustomFieldChanges($memberID, 'register'); } // If COPPA has been selected then things get complicated, setup the template. if (!empty($modSettings['coppaAge']) && empty($_SESSION['skip_coppa'])) { redirectexit('action=coppa;member=' . $memberID); } elseif (!empty($modSettings['registration_method'])) { loadTemplate('Register'); $context += array('page_title' => $txt['register'], 'title' => $txt['registration_successful'], 'sub_template' => 'after', 'description' => $modSettings['registration_method'] == 2 ? $txt['approval_after_registration'] : $txt['activate_after_registration']); } else { call_integration_hook('integrate_activate', array($regOptions['username'])); setLoginCookie(60 * $modSettings['cookieTime'], $memberID, hash('sha256', Util::strtolower($regOptions['username']) . $regOptions['password'] . $regOptions['register_vars']['password_salt'])); redirectexit('action=auth;sa=check;member=' . $memberID, $context['server']['needs_login_fix']); } }
function validateUsername($memID, $username) { global $sourcedir, $txt; // No name?! How can you register with no name? if ($username == '') { fatal_lang_error('need_username', false); } // Only these characters are permitted. if (in_array($username, array('_', '|')) || preg_match('~[<>&"\'=\\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $username)) != 0 || strpos($username, '[code') !== false || strpos($username, '[/code') !== false) { fatal_lang_error('error_invalid_characters_username', false); } if (stristr($username, $txt['guest_title']) !== false) { fatal_lang_error('username_reserved', true, array($txt['guest_title'])); } require_once $sourcedir . '/Subs-Members.php'; if (isReservedName($username, $memID, false)) { fatal_error('(' . htmlspecialchars($username) . ') ' . $txt['name_in_use'], false); } return null; }
function RegisterCheckUsername() { global $sourcedir, $context, $txt; // This is XML! loadTemplate('Xml'); $context['sub_template'] = 'check_username'; $context['checked_username'] = isset($_GET['username']) ? $_GET['username'] : ''; $context['valid_username'] = true; // Clean it up like mother would. $context['checked_username'] = preg_replace('~[\\t\\n\\r\\x0B\\0' . ($context['server']['complex_preg_chars'] ? '\\x{A0}' : "Â ") . ']+~u', ' ', $context['checked_username']); if (commonAPI::strlen($context['checked_username']) > 25) { $context['checked_username'] = commonAPI::htmltrim(commonAPI::substr($context['checked_username'], 0, 25)); } // Only these characters are permitted. if (preg_match('~[<>&"\'=\\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $context['checked_username'])) != 0 || $context['checked_username'] == '_' || $context['checked_username'] == '|' || strpos($context['checked_username'], '[code') !== false || strpos($context['checked_username'], '[/code') !== false) { $context['valid_username'] = false; } if (stristr($context['checked_username'], $txt['guest_title']) !== false) { $context['valid_username'] = false; } if (trim($context['checked_username']) == '') { $context['valid_username'] = false; } else { require_once $sourcedir . '/lib/Subs-Members.php'; $context['valid_username'] &= isReservedName($context['checked_username'], 0, false, false) ? 0 : 1; } }
function Post2() { global $board, $topic, $txt, $modSettings, $sourcedir, $context; global $user_info, $board_info, $options, $smcFunc; // Sneaking off, are we? if (empty($_POST) && empty($topic)) { redirectexit('action=post;board=' . $board . '.0'); } elseif (empty($_POST) && !empty($topic)) { redirectexit('action=post;topic=' . $topic . '.0'); } // No need! $context['robot_no_index'] = true; // If we came from WYSIWYG then turn it back into BBC regardless. if (!empty($_REQUEST['message_mode']) && isset($_REQUEST['message'])) { require_once $sourcedir . '/Subs-Editor.php'; $_REQUEST['message'] = html_to_bbc($_REQUEST['message']); // We need to unhtml it now as it gets done shortly. $_REQUEST['message'] = un_htmlspecialchars($_REQUEST['message']); // We need this for everything else. $_POST['message'] = $_REQUEST['message']; } // Previewing? Go back to start. if (isset($_REQUEST['preview'])) { return Post(); } // Prevent double submission of this form. checkSubmitOnce('check'); // No errors as yet. $post_errors = array(); // If the session has timed out, let the user re-submit their form. if (checkSession('post', '', false) != '') { $post_errors[] = 'session_timeout'; } // Wrong verification code? if (!$user_info['is_admin'] && !$user_info['is_mod'] && !empty($modSettings['posts_require_captcha']) && ($user_info['posts'] < $modSettings['posts_require_captcha'] || $user_info['is_guest'] && $modSettings['posts_require_captcha'] == -1)) { require_once $sourcedir . '/Subs-Editor.php'; $verificationOptions = array('id' => 'post'); $context['require_verification'] = create_control_verification($verificationOptions, true); if (is_array($context['require_verification'])) { $post_errors = array_merge($post_errors, $context['require_verification']); } } require_once $sourcedir . '/Subs-Post.php'; loadLanguage('Post'); // If this isn't a new topic load the topic info that we need. if (!empty($topic)) { $request = $smcFunc['db_query']('', ' SELECT locked, is_sticky, id_poll, approved, id_first_msg, id_last_msg, id_member_started, id_board FROM {db_prefix}topics WHERE id_topic = {int:current_topic} LIMIT 1', array('current_topic' => $topic)); $topic_info = $smcFunc['db_fetch_assoc']($request); $smcFunc['db_free_result']($request); // Though the topic should be there, it might have vanished. if (!is_array($topic_info)) { fatal_lang_error('topic_doesnt_exist'); } // Did this topic suddenly move? Just checking... if ($topic_info['id_board'] != $board) { fatal_lang_error('not_a_topic'); } } // Replying to a topic? if (!empty($topic) && !isset($_REQUEST['msg'])) { // Don't allow a post if it's locked. if ($topic_info['locked'] != 0 && !allowedTo('moderate_board')) { fatal_lang_error('topic_locked', false); } // Sorry, multiple polls aren't allowed... yet. You should stop giving me ideas :P. if (isset($_REQUEST['poll']) && $topic_info['id_poll'] > 0) { unset($_REQUEST['poll']); } // Do the permissions and approval stuff... $becomesApproved = true; if ($topic_info['id_member_started'] != $user_info['id']) { if ($modSettings['postmod_active'] && allowedTo('post_unapproved_replies_any') && !allowedTo('post_reply_any')) { $becomesApproved = false; } else { isAllowedTo('post_reply_any'); } } elseif (!allowedTo('post_reply_any')) { if ($modSettings['postmod_active'] && allowedTo('post_unapproved_replies_own') && !allowedTo('post_reply_own')) { $becomesApproved = false; } else { isAllowedTo('post_reply_own'); } } if (isset($_POST['lock'])) { // Nothing is changed to the lock. if (empty($topic_info['locked']) && empty($_POST['lock']) || !empty($_POST['lock']) && !empty($topic_info['locked'])) { unset($_POST['lock']); } elseif (!allowedTo(array('lock_any', 'lock_own')) || !allowedTo('lock_any') && $user_info['id'] != $topic_info['id_member_started']) { unset($_POST['lock']); } elseif (!allowedTo('lock_any')) { // You cannot override a moderator lock. if ($topic_info['locked'] == 1) { unset($_POST['lock']); } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 2; } } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 1; } } // So you wanna (un)sticky this...let's see. if (isset($_POST['sticky']) && (empty($modSettings['enableStickyTopics']) || $_POST['sticky'] == $topic_info['is_sticky'] || !allowedTo('make_sticky'))) { unset($_POST['sticky']); } // If the number of replies has changed, if the setting is enabled, go back to Post() - which handles the error. if (empty($options['no_new_reply_warning']) && isset($_POST['last_msg']) && $topic_info['id_last_msg'] > $_POST['last_msg']) { $_REQUEST['preview'] = true; return Post(); } $posterIsGuest = $user_info['is_guest']; } elseif (empty($topic)) { // Now don't be silly, new topics will get their own id_msg soon enough. unset($_REQUEST['msg'], $_POST['msg'], $_GET['msg']); // Do like, the permissions, for safety and stuff... $becomesApproved = true; if ($modSettings['postmod_active'] && !allowedTo('post_new') && allowedTo('post_unapproved_topics')) { $becomesApproved = false; } else { isAllowedTo('post_new'); } if (isset($_POST['lock'])) { // New topics are by default not locked. if (empty($_POST['lock'])) { unset($_POST['lock']); } elseif (!allowedTo(array('lock_any', 'lock_own'))) { unset($_POST['lock']); } else { $_POST['lock'] = allowedTo('lock_any') ? 1 : 2; } } if (isset($_POST['sticky']) && (empty($modSettings['enableStickyTopics']) || empty($_POST['sticky']) || !allowedTo('make_sticky'))) { unset($_POST['sticky']); } $posterIsGuest = $user_info['is_guest']; } elseif (isset($_REQUEST['msg']) && !empty($topic)) { $_REQUEST['msg'] = (int) $_REQUEST['msg']; $request = $smcFunc['db_query']('', ' SELECT id_member, poster_name, poster_email, poster_time, approved FROM {db_prefix}messages WHERE id_msg = {int:id_msg} LIMIT 1', array('id_msg' => $_REQUEST['msg'])); if ($smcFunc['db_num_rows']($request) == 0) { fatal_lang_error('cant_find_messages', false); } $row = $smcFunc['db_fetch_assoc']($request); $smcFunc['db_free_result']($request); if (!empty($topic_info['locked']) && !allowedTo('moderate_board')) { fatal_lang_error('topic_locked', false); } if (isset($_POST['lock'])) { // Nothing changes to the lock status. if (empty($_POST['lock']) && empty($topic_info['locked']) || !empty($_POST['lock']) && !empty($topic_info['locked'])) { unset($_POST['lock']); } elseif (!allowedTo(array('lock_any', 'lock_own')) || !allowedTo('lock_any') && $user_info['id'] != $topic_info['id_member_started']) { unset($_POST['lock']); } elseif (!allowedTo('lock_any')) { // You're not allowed to break a moderator's lock. if ($topic_info['locked'] == 1) { unset($_POST['lock']); } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 2; } } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 1; } } // Change the sticky status of this topic? if (isset($_POST['sticky']) && (!allowedTo('make_sticky') || $_POST['sticky'] == $topic_info['is_sticky'])) { unset($_POST['sticky']); } if ($row['id_member'] == $user_info['id'] && !allowedTo('modify_any')) { if ((!$modSettings['postmod_active'] || $row['approved']) && !empty($modSettings['edit_disable_time']) && $row['poster_time'] + ($modSettings['edit_disable_time'] + 5) * 60 < time()) { fatal_lang_error('modify_post_time_passed', false); } elseif ($topic_info['id_member_started'] == $user_info['id'] && !allowedTo('modify_own')) { isAllowedTo('modify_replies'); } else { isAllowedTo('modify_own'); } } elseif ($topic_info['id_member_started'] == $user_info['id'] && !allowedTo('modify_any')) { isAllowedTo('modify_replies'); // If you're modifying a reply, I say it better be logged... $moderationAction = true; } else { isAllowedTo('modify_any'); // Log it, assuming you're not modifying your own post. if ($row['id_member'] != $user_info['id']) { $moderationAction = true; } } $posterIsGuest = empty($row['id_member']); // Can they approve it? $can_approve = allowedTo('approve_posts'); $becomesApproved = $modSettings['postmod_active'] ? $can_approve && !$row['approved'] ? !empty($_REQUEST['approve']) ? 1 : 0 : $row['approved'] : 1; $approve_has_changed = $row['approved'] != $becomesApproved; if (!allowedTo('moderate_forum') || !$posterIsGuest) { $_POST['guestname'] = $row['poster_name']; $_POST['email'] = $row['poster_email']; } } // If the poster is a guest evaluate the legality of name and email. if ($posterIsGuest) { $_POST['guestname'] = !isset($_POST['guestname']) ? '' : trim($_POST['guestname']); $_POST['email'] = !isset($_POST['email']) ? '' : trim($_POST['email']); if ($_POST['guestname'] == '' || $_POST['guestname'] == '_') { $post_errors[] = 'no_name'; } if ($smcFunc['strlen']($_POST['guestname']) > 25) { $post_errors[] = 'long_name'; } if (empty($modSettings['guest_post_no_email'])) { // Only check if they changed it! if (!isset($row) || $row['poster_email'] != $_POST['email']) { if (!allowedTo('moderate_forum') && (!isset($_POST['email']) || $_POST['email'] == '')) { $post_errors[] = 'no_email'; } if (!allowedTo('moderate_forum') && preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', $_POST['email']) == 0) { $post_errors[] = 'bad_email'; } } // Now make sure this email address is not banned from posting. isBannedEmail($_POST['email'], 'cannot_post', sprintf($txt['you_are_post_banned'], $txt['guest_title'])); } // In case they are making multiple posts this visit, help them along by storing their name. if (empty($post_errors)) { $_SESSION['guest_name'] = $_POST['guestname']; $_SESSION['guest_email'] = $_POST['email']; } } // Check the subject and message. if (!isset($_POST['subject']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['subject'])) === '') { $post_errors[] = 'no_subject'; } if (!isset($_POST['message']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['message']), ENT_QUOTES) === '') { $post_errors[] = 'no_message'; } elseif (!empty($modSettings['max_messageLength']) && $smcFunc['strlen']($_POST['message']) > $modSettings['max_messageLength']) { $post_errors[] = 'long_message'; } else { // Prepare the message a bit for some additional testing. $_POST['message'] = $smcFunc['htmlspecialchars']($_POST['message'], ENT_QUOTES); // Preparse code. (Zef) if ($user_info['is_guest']) { $user_info['name'] = $_POST['guestname']; } preparsecode($_POST['message']); // Let's see if there's still some content left without the tags. if ($smcFunc['htmltrim'](strip_tags(parse_bbc($_POST['message'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['message'], '[html]') === false)) { $post_errors[] = 'no_message'; } } if (isset($_POST['calendar']) && !isset($_REQUEST['deleteevent']) && $smcFunc['htmltrim']($_POST['evtitle']) === '') { $post_errors[] = 'no_event'; } // You are not! if (isset($_POST['message']) && strtolower($_POST['message']) == 'i am the administrator.' && !$user_info['is_admin']) { fatal_error('Knave! Masquerader! Charlatan!', false); } // Validate the poll... if (isset($_REQUEST['poll']) && $modSettings['pollMode'] == '1') { if (!empty($topic) && !isset($_REQUEST['msg'])) { fatal_lang_error('no_access', false); } // This is a new topic... so it's a new poll. if (empty($topic)) { isAllowedTo('poll_post'); } elseif ($user_info['id'] == $topic_info['id_member_started'] && !allowedTo('poll_add_any')) { isAllowedTo('poll_add_own'); } else { isAllowedTo('poll_add_any'); } if (!isset($_POST['question']) || trim($_POST['question']) == '') { $post_errors[] = 'no_question'; } $_POST['options'] = empty($_POST['options']) ? array() : htmltrim__recursive($_POST['options']); // Get rid of empty ones. foreach ($_POST['options'] as $k => $option) { if ($option == '') { unset($_POST['options'][$k], $_POST['options'][$k]); } } // What are you going to vote between with one choice?!? if (count($_POST['options']) < 2) { $post_errors[] = 'poll_few'; } } if ($posterIsGuest) { // If user is a guest, make sure the chosen name isn't taken. require_once $sourcedir . '/Subs-Members.php'; if (isReservedName($_POST['guestname'], 0, true, false) && (!isset($row['poster_name']) || $_POST['guestname'] != $row['poster_name'])) { $post_errors[] = 'bad_name'; } } elseif (!isset($_REQUEST['msg'])) { $_POST['guestname'] = $user_info['username']; $_POST['email'] = $user_info['email']; } // Any mistakes? if (!empty($post_errors)) { loadLanguage('Errors'); // Previewing. $_REQUEST['preview'] = true; $context['post_error'] = array('messages' => array()); foreach ($post_errors as $post_error) { $context['post_error'][$post_error] = true; if ($post_error == 'long_message') { $txt['error_' . $post_error] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']); } $context['post_error']['messages'][] = $txt['error_' . $post_error]; } return Post(); } // Make sure the user isn't spamming the board. if (!isset($_REQUEST['msg'])) { spamProtection('post'); } // At about this point, we're posting and that's that. ignore_user_abort(true); @set_time_limit(300); // Add special html entities to the subject, name, and email. $_POST['subject'] = strtr($smcFunc['htmlspecialchars']($_POST['subject']), array("\r" => '', "\n" => '', "\t" => '')); $_POST['guestname'] = htmlspecialchars($_POST['guestname']); $_POST['email'] = htmlspecialchars($_POST['email']); // At this point, we want to make sure the subject isn't too long. if ($smcFunc['strlen']($_POST['subject']) > 100) { $_POST['subject'] = $smcFunc['substr']($_POST['subject'], 0, 100); } // Make the poll... if (isset($_REQUEST['poll'])) { // Make sure that the user has not entered a ridiculous number of options.. if (empty($_POST['poll_max_votes']) || $_POST['poll_max_votes'] <= 0) { $_POST['poll_max_votes'] = 1; } elseif ($_POST['poll_max_votes'] > count($_POST['options'])) { $_POST['poll_max_votes'] = count($_POST['options']); } else { $_POST['poll_max_votes'] = (int) $_POST['poll_max_votes']; } $_POST['poll_expire'] = (int) $_POST['poll_expire']; $_POST['poll_expire'] = $_POST['poll_expire'] > 9999 ? 9999 : ($_POST['poll_expire'] < 0 ? 0 : $_POST['poll_expire']); // Just set it to zero if it's not there.. if (!isset($_POST['poll_hide'])) { $_POST['poll_hide'] = 0; } else { $_POST['poll_hide'] = (int) $_POST['poll_hide']; } $_POST['poll_change_vote'] = isset($_POST['poll_change_vote']) ? 1 : 0; $_POST['poll_guest_vote'] = isset($_POST['poll_guest_vote']) ? 1 : 0; // Make sure guests are actually allowed to vote generally. if ($_POST['poll_guest_vote']) { require_once $sourcedir . '/Subs-Members.php'; $allowedVoteGroups = groupsAllowedTo('poll_vote', $board); if (!in_array(-1, $allowedVoteGroups['allowed'])) { $_POST['poll_guest_vote'] = 0; } } // If the user tries to set the poll too far in advance, don't let them. if (!empty($_POST['poll_expire']) && $_POST['poll_expire'] < 1) { fatal_lang_error('poll_range_error', false); } elseif (empty($_POST['poll_expire']) && $_POST['poll_hide'] == 2) { $_POST['poll_hide'] = 1; } // Clean up the question and answers. $_POST['question'] = htmlspecialchars($_POST['question']); $_POST['question'] = $smcFunc['truncate']($_POST['question'], 255); $_POST['question'] = preg_replace('~&#(\\d{4,5}|[2-9]\\d{2,4}|1[2-9]\\d);~', '&#$1;', $_POST['question']); $_POST['options'] = htmlspecialchars__recursive($_POST['options']); } // Check if they are trying to delete any current attachments.... if (isset($_REQUEST['msg'], $_POST['attach_del']) && (allowedTo('post_attachment') || $modSettings['postmod_active'] && allowedTo('post_unapproved_attachments'))) { $del_temp = array(); foreach ($_POST['attach_del'] as $i => $dummy) { $del_temp[$i] = (int) $dummy; } require_once $sourcedir . '/ManageAttachments.php'; $attachmentQuery = array('attachment_type' => 0, 'id_msg' => (int) $_REQUEST['msg'], 'not_id_attach' => $del_temp); removeAttachments($attachmentQuery); } // ...or attach a new file... if (isset($_FILES['attachment']['name']) || !empty($_SESSION['temp_attachments']) && empty($_POST['from_qr'])) { // Verify they can post them! if (!$modSettings['postmod_active'] || !allowedTo('post_unapproved_attachments')) { isAllowedTo('post_attachment'); } // Make sure we're uploading to the right place. if (!empty($modSettings['currentAttachmentUploadDir'])) { if (!is_array($modSettings['attachmentUploadDir'])) { $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']); } // The current directory, of course! $current_attach_dir = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']]; } else { $current_attach_dir = $modSettings['attachmentUploadDir']; } // If this isn't a new post, check the current attachments. if (isset($_REQUEST['msg'])) { $request = $smcFunc['db_query']('', ' SELECT COUNT(*), SUM(size) FROM {db_prefix}attachments WHERE id_msg = {int:id_msg} AND attachment_type = {int:attachment_type}', array('id_msg' => (int) $_REQUEST['msg'], 'attachment_type' => 0)); list($quantity, $total_size) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); } else { $quantity = 0; $total_size = 0; } if (!empty($_SESSION['temp_attachments'])) { foreach ($_SESSION['temp_attachments'] as $attachID => $name) { if (preg_match('~^post_tmp_' . $user_info['id'] . '_\\d+$~', $attachID) == 0) { continue; } if (!empty($_POST['attach_del']) && !in_array($attachID, $_POST['attach_del'])) { unset($_SESSION['temp_attachments'][$attachID]); @unlink($current_attach_dir . '/' . $attachID); continue; } $_FILES['attachment']['tmp_name'][] = $attachID; $_FILES['attachment']['name'][] = $name; $_FILES['attachment']['size'][] = filesize($current_attach_dir . '/' . $attachID); list($_FILES['attachment']['width'][], $_FILES['attachment']['height'][]) = @getimagesize($current_attach_dir . '/' . $attachID); unset($_SESSION['temp_attachments'][$attachID]); } } if (!isset($_FILES['attachment']['name'])) { $_FILES['attachment']['tmp_name'] = array(); } $attachIDs = array(); foreach ($_FILES['attachment']['tmp_name'] as $n => $dummy) { if ($_FILES['attachment']['name'][$n] == '') { continue; } // Have we reached the maximum number of files we are allowed? $quantity++; if (!empty($modSettings['attachmentNumPerPostLimit']) && $quantity > $modSettings['attachmentNumPerPostLimit']) { checkSubmitOnce('free'); fatal_lang_error('attachments_limit_per_post', false, array($modSettings['attachmentNumPerPostLimit'])); } // Check the total upload size for this post... $total_size += $_FILES['attachment']['size'][$n]; if (!empty($modSettings['attachmentPostLimit']) && $total_size > $modSettings['attachmentPostLimit'] * 1024) { checkSubmitOnce('free'); fatal_lang_error('file_too_big', false, array($modSettings['attachmentPostLimit'])); } $attachmentOptions = array('post' => isset($_REQUEST['msg']) ? $_REQUEST['msg'] : 0, 'poster' => $user_info['id'], 'name' => $_FILES['attachment']['name'][$n], 'tmp_name' => $_FILES['attachment']['tmp_name'][$n], 'size' => $_FILES['attachment']['size'][$n], 'approved' => !$modSettings['postmod_active'] || allowedTo('post_attachment')); if (createAttachment($attachmentOptions)) { $attachIDs[] = $attachmentOptions['id']; if (!empty($attachmentOptions['thumb'])) { $attachIDs[] = $attachmentOptions['thumb']; } } else { if (in_array('could_not_upload', $attachmentOptions['errors'])) { checkSubmitOnce('free'); fatal_lang_error('attach_timeout', 'critical'); } if (in_array('too_large', $attachmentOptions['errors'])) { checkSubmitOnce('free'); fatal_lang_error('file_too_big', false, array($modSettings['attachmentSizeLimit'])); } if (in_array('bad_extension', $attachmentOptions['errors'])) { checkSubmitOnce('free'); fatal_error($attachmentOptions['name'] . '.<br />' . $txt['cant_upload_type'] . ' ' . $modSettings['attachmentExtensions'] . '.', false); } if (in_array('directory_full', $attachmentOptions['errors'])) { checkSubmitOnce('free'); fatal_lang_error('ran_out_of_space', 'critical'); } if (in_array('bad_filename', $attachmentOptions['errors'])) { checkSubmitOnce('free'); fatal_error(basename($attachmentOptions['name']) . '.<br />' . $txt['restricted_filename'] . '.', 'critical'); } if (in_array('taken_filename', $attachmentOptions['errors'])) { checkSubmitOnce('free'); fatal_lang_error('filename_exists'); } if (in_array('bad_attachment', $attachmentOptions['errors'])) { checkSubmitOnce('free'); fatal_lang_error('bad_attachment'); } } } } // Make the poll... if (isset($_REQUEST['poll'])) { // Create the poll. $smcFunc['db_insert']('', '{db_prefix}polls', array('question' => 'string-255', 'hide_results' => 'int', 'max_votes' => 'int', 'expire_time' => 'int', 'id_member' => 'int', 'poster_name' => 'string-255', 'change_vote' => 'int', 'guest_vote' => 'int'), array($_POST['question'], $_POST['poll_hide'], $_POST['poll_max_votes'], empty($_POST['poll_expire']) ? 0 : time() + $_POST['poll_expire'] * 3600 * 24, $user_info['id'], $_POST['guestname'], $_POST['poll_change_vote'], $_POST['poll_guest_vote']), array('id_poll')); $id_poll = $smcFunc['db_insert_id']('{db_prefix}polls', 'id_poll'); // Create each answer choice. $i = 0; $pollOptions = array(); foreach ($_POST['options'] as $option) { $pollOptions[] = array($id_poll, $i, $option); $i++; } $smcFunc['db_insert']('insert', '{db_prefix}poll_choices', array('id_poll' => 'int', 'id_choice' => 'int', 'label' => 'string-255'), $pollOptions, array('id_poll', 'id_choice')); } else { $id_poll = 0; } // Creating a new topic? $newTopic = empty($_REQUEST['msg']) && empty($topic); $_POST['icon'] = !empty($attachIDs) && $_POST['icon'] == 'xx' ? 'clip' : $_POST['icon']; // Collect all parameters for the creation or modification of a post. $msgOptions = array('id' => empty($_REQUEST['msg']) ? 0 : (int) $_REQUEST['msg'], 'subject' => $_POST['subject'], 'body' => $_POST['message'], 'icon' => preg_replace('~[\\./\\\\*:"\'<>]~', '', $_POST['icon']), 'smileys_enabled' => !isset($_POST['ns']), 'attachments' => empty($attachIDs) ? array() : $attachIDs, 'approved' => $becomesApproved); $topicOptions = array('id' => empty($topic) ? 0 : $topic, 'board' => $board, 'poll' => isset($_REQUEST['poll']) ? $id_poll : null, 'lock_mode' => isset($_POST['lock']) ? (int) $_POST['lock'] : null, 'sticky_mode' => isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics']) ? (int) $_POST['sticky'] : null, 'mark_as_read' => true, 'is_approved' => !$modSettings['postmod_active'] || empty($topic) || !empty($board_info['cur_topic_approved'])); $posterOptions = array('id' => $user_info['id'], 'name' => $_POST['guestname'], 'email' => $_POST['email'], 'update_post_count' => !$user_info['is_guest'] && !isset($_REQUEST['msg']) && $board_info['posts_count']); // This is an already existing message. Edit it. if (!empty($_REQUEST['msg'])) { // Have admins allowed people to hide their screwups? if (time() - $row['poster_time'] > $modSettings['edit_wait_time'] || $user_info['id'] != $row['id_member']) { $msgOptions['modify_time'] = time(); $msgOptions['modify_name'] = $user_info['name']; } // This will save some time... if (empty($approve_has_changed)) { unset($msgOptions['approved']); } modifyPost($msgOptions, $topicOptions, $posterOptions); } else { createPost($msgOptions, $topicOptions, $posterOptions); if (isset($topicOptions['id'])) { $topic = $topicOptions['id']; } } // Editing or posting an event? if (isset($_POST['calendar']) && (!isset($_REQUEST['eventid']) || $_REQUEST['eventid'] == -1)) { require_once $sourcedir . '/Subs-Calendar.php'; // Make sure they can link an event to this post. canLinkEvent(); // Insert the event. $eventOptions = array('board' => $board, 'topic' => $topic, 'title' => $_POST['evtitle'], 'member' => $user_info['id'], 'start_date' => sprintf('%04d-%02d-%02d', $_POST['year'], $_POST['month'], $_POST['day']), 'span' => isset($_POST['span']) && $_POST['span'] > 0 ? min((int) $modSettings['cal_maxspan'], (int) $_POST['span'] - 1) : 0); insertEvent($eventOptions); } elseif (isset($_POST['calendar'])) { $_REQUEST['eventid'] = (int) $_REQUEST['eventid']; // Validate the post... require_once $sourcedir . '/Subs-Calendar.php'; validateEventPost(); // If you're not allowed to edit any events, you have to be the poster. if (!allowedTo('calendar_edit_any')) { // Get the event's poster. $request = $smcFunc['db_query']('', ' SELECT id_member FROM {db_prefix}calendar WHERE id_event = {int:id_event}', array('id_event' => $_REQUEST['eventid'])); $row2 = $smcFunc['db_fetch_assoc']($request); $smcFunc['db_free_result']($request); // Silly hacker, Trix are for kids. ...probably trademarked somewhere, this is FAIR USE! (parody...) isAllowedTo('calendar_edit_' . ($row2['id_member'] == $user_info['id'] ? 'own' : 'any')); } // Delete it? if (isset($_REQUEST['deleteevent'])) { $smcFunc['db_query']('', ' DELETE FROM {db_prefix}calendar WHERE id_event = {int:id_event}', array('id_event' => $_REQUEST['eventid'])); } else { $span = !empty($modSettings['cal_allowspan']) && !empty($_REQUEST['span']) ? min((int) $modSettings['cal_maxspan'], (int) $_REQUEST['span'] - 1) : 0; $start_time = mktime(0, 0, 0, (int) $_REQUEST['month'], (int) $_REQUEST['day'], (int) $_REQUEST['year']); $smcFunc['db_query']('', ' UPDATE {db_prefix}calendar SET end_date = {date:end_date}, start_date = {date:start_date}, title = {string:title} WHERE id_event = {int:id_event}', array('end_date' => strftime('%Y-%m-%d', $start_time + $span * 86400), 'start_date' => strftime('%Y-%m-%d', $start_time), 'id_event' => $_REQUEST['eventid'], 'title' => $smcFunc['htmlspecialchars']($_REQUEST['evtitle'], ENT_QUOTES))); } updateSettings(array('calendar_updated' => time())); } // Marking read should be done even for editing messages.... // Mark all the parents read. (since you just posted and they will be unread.) if (!$user_info['is_guest'] && !empty($board_info['parent_boards'])) { $smcFunc['db_query']('', ' UPDATE {db_prefix}log_boards SET id_msg = {int:id_msg} WHERE id_member = {int:current_member} AND id_board IN ({array_int:board_list})', array('current_member' => $user_info['id'], 'board_list' => array_keys($board_info['parent_boards']), 'id_msg' => $modSettings['maxMsgID'])); } // Turn notification on or off. (note this just blows smoke if it's already on or off.) if (!empty($_POST['notify']) && allowedTo('mark_any_notify')) { $smcFunc['db_insert']('ignore', '{db_prefix}log_notify', array('id_member' => 'int', 'id_topic' => 'int', 'id_board' => 'int'), array($user_info['id'], $topic, 0), array('id_member', 'id_topic', 'id_board')); } elseif (!$newTopic) { $smcFunc['db_query']('', ' DELETE FROM {db_prefix}log_notify WHERE id_member = {int:current_member} AND id_topic = {int:current_topic}', array('current_member' => $user_info['id'], 'current_topic' => $topic)); } // Log an act of moderation - modifying. if (!empty($moderationAction)) { logAction('modify', array('topic' => $topic, 'message' => (int) $_REQUEST['msg'], 'member' => $row['id_member'], 'board' => $board)); } if (isset($_POST['lock']) && $_POST['lock'] != 2) { logAction('lock', array('topic' => $topicOptions['id'], 'board' => $topicOptions['board'])); } if (isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics'])) { logAction('sticky', array('topic' => $topicOptions['id'], 'board' => $topicOptions['board'])); } // Notify any members who have notification turned on for this topic - only do this if it's going to be approved(!) if ($becomesApproved) { if ($newTopic) { $notifyData = array('body' => $_POST['message'], 'subject' => $_POST['subject'], 'name' => $user_info['name'], 'poster' => $user_info['id'], 'msg' => $msgOptions['id'], 'board' => $board, 'topic' => $topic); notifyMembersBoard($notifyData); } elseif (empty($_REQUEST['msg'])) { // Only send it to everyone if the topic is approved, otherwise just to the topic starter if they want it. if ($topic_info['approved']) { sendNotifications($topic, 'reply'); } else { sendNotifications($topic, 'reply', array(), $topic_info['id_member_started']); } } } // Returning to the topic? if (!empty($_REQUEST['goback'])) { // Mark the board as read.... because it might get confusing otherwise. $smcFunc['db_query']('', ' UPDATE {db_prefix}log_boards SET id_msg = {int:maxMsgID} WHERE id_member = {int:current_member} AND id_board = {int:current_board}', array('current_board' => $board, 'current_member' => $user_info['id'], 'maxMsgID' => $modSettings['maxMsgID'])); } if ($board_info['num_topics'] == 0) { cache_put_data('board-' . $board, null, 120); } if (!empty($_POST['announce_topic'])) { redirectexit('action=announce;sa=selectgroup;topic=' . $topic . (!empty($_POST['move']) && allowedTo('move_any') ? ';move' : '') . (empty($_REQUEST['goback']) ? '' : ';goback')); } if (!empty($_POST['move']) && allowedTo('move_any')) { redirectexit('action=movetopic;topic=' . $topic . '.0' . (empty($_REQUEST['goback']) ? '' : ';goback')); } // Return to post if the mod is on. if (isset($_REQUEST['msg']) && !empty($_REQUEST['goback'])) { redirectexit('topic=' . $topic . '.msg' . $_REQUEST['msg'] . '#msg' . $_REQUEST['msg'], $context['browser']['is_ie']); } elseif (!empty($_REQUEST['goback'])) { redirectexit('topic=' . $topic . '.new#new', $context['browser']['is_ie']); } else { redirectexit('board=' . $board . '.0'); } }
function ArcadeSave_Guest() { global $scripturl, $txt, $db_prefix, $modSettings, $context, $func, $sourcedir, $smcFunc; if (!isset($_REQUEST['name']) && !isset($_SESSION['playerName'])) { $context['arcade']['submit'] = 'askname'; return ArcadeHighscore(); } elseif (isset($_REQUEST['name']) || isset($_SESSION['playerName'])) { $_REQUEST['game'] = $_SESSION['save_score'][0]['id']; if (isset($_REQUEST['name'])) { require_once $sourcedir . '/Subs-Members.php'; checkSession('post'); $name = htmlspecialchars($_REQUEST['name']); if (isReservedName($name, 0, true, false)) { $context['arcade']['submit'] = 'askname'; $context['arcade']['error'] = 'bad_name'; return ArcadeHighscore(); } $_SESSION['playerName'] = $name; $_SESSION['save_score'][1]['name'] = $name; } SaveScore($_SESSION['save_score'][0], $_SESSION['save_score'][1], $_SESSION['save_score'][2]); unset($_SESSION['save_score']); redirectexit('action=arcade;sa=highscore;game=' . $_REQUEST['game']); } }
function Post2() { global $board, $topic, $txt, $db_prefix, $modSettings, $sourcedir, $context; global $ID_MEMBER, $user_info, $board_info, $options, $func; // Previewing? Go back to start. if (isset($_REQUEST['preview'])) { return Post(); } // Prevent double submission of this form. checkSubmitOnce('check'); // No errors as yet. $post_errors = array(); // If the session has timed out, let the user re-submit their form. if (checkSession('post', '', false) != '') { $post_errors[] = 'session_timeout'; } require_once $sourcedir . '/Subs-Post.php'; loadLanguage('Post'); // Replying to a topic? if (!empty($topic) && !isset($_REQUEST['msg'])) { $request = db_query("\n\t\t\tSELECT t.locked, t.isSticky, t.ID_POLL, t.numReplies, m.ID_MEMBER\n\t\t\tFROM ({$db_prefix}topics AS t, {$db_prefix}messages AS m)\n\t\t\tWHERE t.ID_TOPIC = {$topic}\n\t\t\t\tAND m.ID_MSG = t.ID_FIRST_MSG\n\t\t\tLIMIT 1", __FILE__, __LINE__); list($tmplocked, $tmpstickied, $pollID, $numReplies, $ID_MEMBER_POSTER) = mysql_fetch_row($request); mysql_free_result($request); // Don't allow a post if it's locked. if ($tmplocked != 0 && !allowedTo('moderate_board')) { fatal_lang_error(90, false); } // Sorry, multiple polls aren't allowed... yet. You should stop giving me ideas :P. if (isset($_REQUEST['poll']) && $pollID > 0) { unset($_REQUEST['poll']); } if ($ID_MEMBER_POSTER != $ID_MEMBER) { isAllowedTo('post_reply_any'); } elseif (!allowedTo('post_reply_any')) { isAllowedTo('post_reply_own'); } if (isset($_POST['lock'])) { // Nothing is changed to the lock. if (empty($tmplocked) && empty($_POST['lock']) || !empty($_POST['lock']) && !empty($tmplocked)) { unset($_POST['lock']); } elseif (!allowedTo(array('lock_any', 'lock_own')) || !allowedTo('lock_any') && $ID_MEMBER != $ID_MEMBER_POSTER) { unset($_POST['lock']); } elseif (!allowedTo('lock_any')) { // You cannot override a moderator lock. if ($tmplocked == 1) { unset($_POST['lock']); } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 2; } } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 1; } } // So you wanna (un)sticky this...let's see. if (isset($_POST['sticky']) && (empty($modSettings['enableStickyTopics']) || $_POST['sticky'] == $tmpstickied || !allowedTo('make_sticky'))) { unset($_POST['sticky']); } // If the number of replies has changed, if the setting is enabled, go back to Post() - which handles the error. $newReplies = isset($_POST['num_replies']) && $numReplies > $_POST['num_replies'] ? $numReplies - $_POST['num_replies'] : 0; if (empty($options['no_new_reply_warning']) && !empty($newReplies)) { $_REQUEST['preview'] = true; return Post(); } $posterIsGuest = $user_info['is_guest']; } elseif (empty($topic)) { if (!isset($_REQUEST['poll']) || $modSettings['pollMode'] != '1') { isAllowedTo('post_new'); } if (isset($_POST['lock'])) { // New topics are by default not locked. if (empty($_POST['lock'])) { unset($_POST['lock']); } elseif (!allowedTo(array('lock_any', 'lock_own'))) { unset($_POST['lock']); } else { $_POST['lock'] = allowedTo('lock_any') ? 1 : 2; } } if (isset($_POST['sticky']) && (empty($modSettings['enableStickyTopics']) || empty($_POST['sticky']) || !allowedTo('make_sticky'))) { unset($_POST['sticky']); } $posterIsGuest = $user_info['is_guest']; } elseif (isset($_REQUEST['msg']) && !empty($topic)) { $_REQUEST['msg'] = (int) $_REQUEST['msg']; $request = db_query("\n\t\t\tSELECT\n\t\t\t\tm.ID_MEMBER, m.posterName, m.posterEmail, m.posterTime, \n\t\t\t\tt.ID_FIRST_MSG, t.locked, t.isSticky, t.ID_MEMBER_STARTED AS ID_MEMBER_POSTER\n\t\t\tFROM ({$db_prefix}messages AS m, {$db_prefix}topics AS t)\n\t\t\tWHERE m.ID_MSG = {$_REQUEST['msg']}\n\t\t\t\tAND t.ID_TOPIC = {$topic}\n\t\t\tLIMIT 1", __FILE__, __LINE__); if (mysql_num_rows($request) == 0) { fatal_lang_error('smf272', false); } $row = mysql_fetch_assoc($request); mysql_free_result($request); if (!empty($row['locked']) && !allowedTo('moderate_board')) { fatal_lang_error(90, false); } if (isset($_POST['lock'])) { // Nothing changes to the lock status. if (empty($_POST['lock']) && empty($row['locked']) || !empty($_POST['lock']) && !empty($row['locked'])) { unset($_POST['lock']); } elseif (!allowedTo(array('lock_any', 'lock_own')) || !allowedTo('lock_any') && $ID_MEMBER != $row['ID_MEMBER_POSTER']) { unset($_POST['lock']); } elseif (!allowedTo('lock_any')) { // You're not allowed to break a moderator's lock. if ($row['locked'] == 1) { unset($_POST['lock']); } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 2; } } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 1; } } // Change the sticky status of this topic? if (isset($_POST['sticky']) && (!allowedTo('make_sticky') || $_POST['sticky'] == $row['isSticky'])) { unset($_POST['sticky']); } if ($row['ID_MEMBER'] == $ID_MEMBER && !allowedTo('modify_any')) { if (!empty($modSettings['edit_disable_time']) && $row['posterTime'] + ($modSettings['edit_disable_time'] + 5) * 60 < time()) { fatal_lang_error('modify_post_time_passed', false); } elseif ($row['ID_MEMBER_POSTER'] == $ID_MEMBER && !allowedTo('modify_own')) { isAllowedTo('modify_replies'); } else { isAllowedTo('modify_own'); } } elseif ($row['ID_MEMBER_POSTER'] == $ID_MEMBER && !allowedTo('modify_any')) { isAllowedTo('modify_replies'); // If you're modifying a reply, I say it better be logged... $moderationAction = true; } else { isAllowedTo('modify_any'); // Log it, assuming you're not modifying your own post. if ($row['ID_MEMBER'] != $ID_MEMBER) { $moderationAction = true; } } $posterIsGuest = empty($row['ID_MEMBER']); if (!allowedTo('moderate_forum') || !$posterIsGuest) { $_POST['guestname'] = addslashes($row['posterName']); $_POST['email'] = addslashes($row['posterEmail']); } } // If the poster is a guest evaluate the legality of name and email. if ($posterIsGuest) { $_POST['guestname'] = !isset($_POST['guestname']) ? '' : trim($_POST['guestname']); $_POST['email'] = !isset($_POST['email']) ? '' : trim($_POST['email']); if ($_POST['guestname'] == '' || $_POST['guestname'] == '_') { $post_errors[] = 'no_name'; } if ($func['strlen']($_POST['guestname']) > 25) { $post_errors[] = 'long_name'; } if (empty($modSettings['guest_post_no_email'])) { // Only check if they changed it! if (!isset($row) || $row['posterEmail'] != $_POST['email']) { if (!allowedTo('moderate_forum') && (!isset($_POST['email']) || $_POST['email'] == '')) { $post_errors[] = 'no_email'; } if (!allowedTo('moderate_forum') && preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', stripslashes($_POST['email'])) == 0) { $post_errors[] = 'bad_email'; } } // Now make sure this email address is not banned from posting. isBannedEmail($_POST['email'], 'cannot_post', sprintf($txt['you_are_post_banned'], $txt[28])); } } // Check the subject and message. if (!isset($_POST['subject']) || $func['htmltrim']($_POST['subject']) === '') { $post_errors[] = 'no_subject'; } if (!isset($_POST['message']) || $func['htmltrim']($_POST['message']) === '') { $post_errors[] = 'no_message'; } elseif (!empty($modSettings['max_messageLength']) && $func['strlen']($_POST['message']) > $modSettings['max_messageLength']) { $post_errors[] = 'long_message'; } else { // Prepare the message a bit for some additional testing. $_POST['message'] = $func['htmlspecialchars']($_POST['message'], ENT_QUOTES); // Preparse code. (Zef) if ($user_info['is_guest']) { $user_info['name'] = $_POST['guestname']; } preparsecode($_POST['message']); // Let's see if there's still some content left without the tags. if ($func['htmltrim'](strip_tags(parse_bbc($_POST['message'], false), '<img>')) === '') { $post_errors[] = 'no_message'; } } if (isset($_POST['calendar']) && !isset($_REQUEST['deleteevent']) && $func['htmltrim']($_POST['evtitle']) === '') { $post_errors[] = 'no_event'; } // You are not! if (isset($_POST['message']) && strtolower($_POST['message']) == 'i am the administrator.' && !$user_info['is_admin']) { fatal_error('Knave! Masquerader! Charlatan!', false); } // Validate the poll... if (isset($_REQUEST['poll']) && $modSettings['pollMode'] == '1') { if (!empty($topic) && !isset($_REQUEST['msg'])) { fatal_lang_error(1, false); } // This is a new topic... so it's a new poll. if (empty($topic)) { isAllowedTo('poll_post'); } elseif ($ID_MEMBER == $row['ID_MEMBER_POSTER'] && !allowedTo('poll_add_any')) { isAllowedTo('poll_add_own'); } else { isAllowedTo('poll_add_any'); } if (!isset($_POST['question']) || trim($_POST['question']) == '') { $post_errors[] = 'no_question'; } $_POST['options'] = empty($_POST['options']) ? array() : htmltrim__recursive($_POST['options']); // Get rid of empty ones. foreach ($_POST['options'] as $k => $option) { if ($option == '') { unset($_POST['options'][$k], $_POST['options'][$k]); } } // What are you going to vote between with one choice?!? if (count($_POST['options']) < 2) { $post_errors[] = 'poll_few'; } } if ($posterIsGuest) { // If user is a guest, make sure the chosen name isn't taken. require_once $sourcedir . '/Subs-Members.php'; if (isReservedName($_POST['guestname'], 0, true, false) && (!isset($row['posterName']) || $_POST['guestname'] != $row['posterName'])) { $post_errors[] = 'bad_name'; } } elseif (!isset($_REQUEST['msg'])) { $_POST['guestname'] = addslashes($user_info['username']); $_POST['email'] = addslashes($user_info['email']); } // Any mistakes? if (!empty($post_errors)) { loadLanguage('Errors'); // Previewing. $_REQUEST['preview'] = true; $context['post_error'] = array('messages' => array()); foreach ($post_errors as $post_error) { $context['post_error'][$post_error] = true; $context['post_error']['messages'][] = $txt['error_' . $post_error]; } return Post(); } // Make sure the user isn't spamming the board. if (!isset($_REQUEST['msg'])) { spamProtection('spam'); } // At about this point, we're posting and that's that. ignore_user_abort(true); @set_time_limit(300); // Add special html entities to the subject, name, and email. $_POST['subject'] = strtr($func['htmlspecialchars']($_POST['subject']), array("\r" => '', "\n" => '', "\t" => '')); $_POST['guestname'] = htmlspecialchars($_POST['guestname']); $_POST['email'] = htmlspecialchars($_POST['email']); // At this point, we want to make sure the subject isn't too long. if ($func['strlen']($_POST['subject']) > 100) { $_POST['subject'] = addslashes($func['substr'](stripslashes($_POST['subject']), 0, 100)); } // Make the poll... if (isset($_REQUEST['poll'])) { // Make sure that the user has not entered a ridiculous number of options.. if (empty($_POST['poll_max_votes']) || $_POST['poll_max_votes'] <= 0) { $_POST['poll_max_votes'] = 1; } elseif ($_POST['poll_max_votes'] > count($_POST['options'])) { $_POST['poll_max_votes'] = count($_POST['options']); } else { $_POST['poll_max_votes'] = (int) $_POST['poll_max_votes']; } // Just set it to zero if it's not there.. if (!isset($_POST['poll_hide'])) { $_POST['poll_hide'] = 0; } else { $_POST['poll_hide'] = (int) $_POST['poll_hide']; } $_POST['poll_change_vote'] = isset($_POST['poll_change_vote']) ? 1 : 0; // If the user tries to set the poll too far in advance, don't let them. if (!empty($_POST['poll_expire']) && $_POST['poll_expire'] < 1) { fatal_lang_error('poll_range_error', false); } elseif (empty($_POST['poll_expire']) && $_POST['poll_hide'] == 2) { $_POST['poll_hide'] = 1; } // Clean up the question and answers. $_POST['question'] = $func['htmlspecialchars']($_POST['question']); $_POST['options'] = htmlspecialchars__recursive($_POST['options']); } // Check if they are trying to delete any current attachments.... if (isset($_REQUEST['msg'], $_POST['attach_del']) && allowedTo('post_attachment')) { $del_temp = array(); foreach ($_POST['attach_del'] as $i => $dummy) { $del_temp[$i] = (int) $dummy; } require_once $sourcedir . '/ManageAttachments.php'; removeAttachments('a.attachmentType = 0 AND a.ID_MSG = ' . (int) $_REQUEST['msg'] . ' AND a.ID_ATTACH NOT IN (' . implode(', ', $del_temp) . ')'); } // ...or attach a new file... if (isset($_FILES['attachment']['name']) || !empty($_SESSION['temp_attachments'])) { isAllowedTo('post_attachment'); // If this isn't a new post, check the current attachments. if (isset($_REQUEST['msg'])) { $request = db_query("\n\t\t\t\tSELECT COUNT(*), SUM(size)\n\t\t\t\tFROM {$db_prefix}attachments\n\t\t\t\tWHERE ID_MSG = " . (int) $_REQUEST['msg'] . "\n\t\t\t\t\tAND attachmentType = 0", __FILE__, __LINE__); list($quantity, $total_size) = mysql_fetch_row($request); mysql_free_result($request); } else { $quantity = 0; $total_size = 0; } if (!empty($_SESSION['temp_attachments'])) { foreach ($_SESSION['temp_attachments'] as $attachID => $name) { if (preg_match('~^post_tmp_' . $ID_MEMBER . '_\\d+$~', $attachID) == 0) { continue; } if (!empty($_POST['attach_del']) && !in_array($attachID, $_POST['attach_del'])) { unset($_SESSION['temp_attachments'][$attachID]); @unlink($modSettings['attachmentUploadDir'] . '/' . $attachID); continue; } $_FILES['attachment']['tmp_name'][] = $attachID; $_FILES['attachment']['name'][] = addslashes($name); $_FILES['attachment']['size'][] = filesize($modSettings['attachmentUploadDir'] . '/' . $attachID); list($_FILES['attachment']['width'][], $_FILES['attachment']['height'][]) = @getimagesize($modSettings['attachmentUploadDir'] . '/' . $attachID); unset($_SESSION['temp_attachments'][$attachID]); } } if (!isset($_FILES['attachment']['name'])) { $_FILES['attachment']['tmp_name'] = array(); } $attachIDs = array(); foreach ($_FILES['attachment']['tmp_name'] as $n => $dummy) { if ($_FILES['attachment']['name'][$n] == '') { continue; } // Have we reached the maximum number of files we are allowed? $quantity++; if (!empty($modSettings['attachmentNumPerPostLimit']) && $quantity > $modSettings['attachmentNumPerPostLimit']) { fatal_lang_error('attachments_limit_per_post', false, array($modSettings['attachmentNumPerPostLimit'])); } // Check the total upload size for this post... $total_size += $_FILES['attachment']['size'][$n]; if (!empty($modSettings['attachmentPostLimit']) && $total_size > $modSettings['attachmentPostLimit'] * 1024) { fatal_lang_error('smf122', false, array($modSettings['attachmentPostLimit'])); } $attachmentOptions = array('post' => isset($_REQUEST['msg']) ? $_REQUEST['msg'] : 0, 'poster' => $ID_MEMBER, 'name' => $_FILES['attachment']['name'][$n], 'tmp_name' => $_FILES['attachment']['tmp_name'][$n], 'size' => $_FILES['attachment']['size'][$n]); if (createAttachment($attachmentOptions)) { $attachIDs[] = $attachmentOptions['id']; if (!empty($attachmentOptions['thumb'])) { $attachIDs[] = $attachmentOptions['thumb']; } } else { if (in_array('could_not_upload', $attachmentOptions['errors'])) { fatal_lang_error('smf124'); } if (in_array('too_large', $attachmentOptions['errors'])) { fatal_lang_error('smf122', false, array($modSettings['attachmentSizeLimit'])); } if (in_array('bad_extension', $attachmentOptions['errors'])) { fatal_error($attachmentOptions['name'] . '.<br />' . $txt['smf123'] . ' ' . $modSettings['attachmentExtensions'] . '.', false); } if (in_array('directory_full', $attachmentOptions['errors'])) { fatal_lang_error('smf126'); } if (in_array('bad_filename', $attachmentOptions['errors'])) { fatal_error(basename($attachmentOptions['name']) . '.<br />' . $txt['smf130b'] . '.'); } if (in_array('taken_filename', $attachmentOptions['errors'])) { fatal_lang_error('smf125'); } } } } // Make the poll... if (isset($_REQUEST['poll'])) { // Create the poll. db_query("\n\t\t\tINSERT INTO {$db_prefix}polls\n\t\t\t\t(question, hideResults, maxVotes, expireTime, ID_MEMBER, posterName, changeVote)\n\t\t\tVALUES (SUBSTRING('{$_POST['question']}', 1, 255), {$_POST['poll_hide']}, {$_POST['poll_max_votes']},\n\t\t\t\t" . (empty($_POST['poll_expire']) ? '0' : time() + $_POST['poll_expire'] * 3600 * 24) . ", {$ID_MEMBER}, SUBSTRING('{$_POST['guestname']}', 1, 255), {$_POST['poll_change_vote']})", __FILE__, __LINE__); $ID_POLL = db_insert_id(); // Create each answer choice. $i = 0; $setString = ''; foreach ($_POST['options'] as $option) { $setString .= "\n\t\t\t\t\t({$ID_POLL}, {$i}, SUBSTRING('{$option}', 1, 255)),"; $i++; } db_query("\n\t\t\tINSERT INTO {$db_prefix}poll_choices\n\t\t\t\t(ID_POLL, ID_CHOICE, label)\n\t\t\tVALUES" . substr($setString, 0, -1), __FILE__, __LINE__); } else { $ID_POLL = 0; } // Creating a new topic? $newTopic = empty($_REQUEST['msg']) && empty($topic); // Collect all parameters for the creation or modification of a post. $msgOptions = array('id' => empty($_REQUEST['msg']) ? 0 : (int) $_REQUEST['msg'], 'subject' => $_POST['subject'], 'body' => $_POST['message'], 'icon' => preg_replace('~[\\./\\\\*\':"<>]~', '', $_POST['icon']), 'smileys_enabled' => !isset($_POST['ns']), 'attachments' => empty($attachIDs) ? array() : $attachIDs); $topicOptions = array('id' => empty($topic) ? 0 : $topic, 'board' => $board, 'poll' => isset($_REQUEST['poll']) ? $ID_POLL : null, 'lock_mode' => isset($_POST['lock']) ? (int) $_POST['lock'] : null, 'sticky_mode' => isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics']) ? (int) $_POST['sticky'] : null, 'mark_as_read' => true); $posterOptions = array('id' => $ID_MEMBER, 'name' => $_POST['guestname'], 'email' => $_POST['email'], 'update_post_count' => !$user_info['is_guest'] && !isset($_REQUEST['msg']) && $board_info['posts_count']); // This is an already existing message. Edit it. if (!empty($_REQUEST['msg'])) { // Have admins allowed people to hide their screwups? if (time() - $row['posterTime'] > $modSettings['edit_wait_time'] || $ID_MEMBER != $row['ID_MEMBER']) { $msgOptions['modify_time'] = time(); $msgOptions['modify_name'] = addslashes($user_info['name']); } modifyPost($msgOptions, $topicOptions, $posterOptions); } else { createPost($msgOptions, $topicOptions, $posterOptions); if (isset($topicOptions['id'])) { $topic = $topicOptions['id']; } } // Editing or posting an event? if (isset($_POST['calendar']) && (!isset($_REQUEST['eventid']) || $_REQUEST['eventid'] == -1)) { require_once $sourcedir . '/Calendar.php'; calendarCanLink(); calendarInsertEvent($board, $topic, $_POST['evtitle'], $ID_MEMBER, $_POST['month'], $_POST['day'], $_POST['year'], isset($_POST['span']) ? $_POST['span'] : null); } elseif (isset($_POST['calendar'])) { $_REQUEST['eventid'] = (int) $_REQUEST['eventid']; // Validate the post... require_once $sourcedir . '/Subs-Post.php'; calendarValidatePost(); // If you're not allowed to edit any events, you have to be the poster. if (!allowedTo('calendar_edit_any')) { // Get the event's poster. $request = db_query("\n\t\t\t\tSELECT ID_MEMBER\n\t\t\t\tFROM {$db_prefix}calendar\n\t\t\t\tWHERE ID_EVENT = {$_REQUEST['eventid']}", __FILE__, __LINE__); $row2 = mysql_fetch_assoc($request); mysql_free_result($request); // Silly hacker, Trix are for kids. ...probably trademarked somewhere, this is FAIR USE! (parody...) isAllowedTo('calendar_edit_' . ($row2['ID_MEMBER'] == $ID_MEMBER ? 'own' : 'any')); } // Delete it? if (isset($_REQUEST['deleteevent'])) { db_query("\n\t\t\t\tDELETE FROM {$db_prefix}calendar\n\t\t\t\tWHERE ID_EVENT = {$_REQUEST['eventid']}\n\t\t\t\tLIMIT 1", __FILE__, __LINE__); } else { $span = !empty($modSettings['cal_allowspan']) && !empty($_REQUEST['span']) ? min((int) $modSettings['cal_maxspan'], (int) $_REQUEST['span'] - 1) : 0; $start_time = mktime(0, 0, 0, (int) $_REQUEST['month'], (int) $_REQUEST['day'], (int) $_REQUEST['year']); db_query("\n\t\t\t\tUPDATE {$db_prefix}calendar\n\t\t\t\tSET endDate = '" . strftime('%Y-%m-%d', $start_time + $span * 86400) . "',\n\t\t\t\t\tstartDate = '" . strftime('%Y-%m-%d', $start_time) . "',\n\t\t\t\t\ttitle = '" . $func['htmlspecialchars']($_REQUEST['evtitle'], ENT_QUOTES) . "'\n\t\t\t\tWHERE ID_EVENT = {$_REQUEST['eventid']}\n\t\t\t\tLIMIT 1", __FILE__, __LINE__); } updateStats('calendar'); } // Marking read should be done even for editing messages.... if (!$user_info['is_guest']) { // Mark all the parents read. (since you just posted and they will be unread.) if (!empty($board_info['parent_boards'])) { db_query("\n\t\t\t\tUPDATE {$db_prefix}log_boards\n\t\t\t\tSET ID_MSG = {$modSettings['maxMsgID']}\n\t\t\t\tWHERE ID_MEMBER = {$ID_MEMBER}\n\t\t\t\t\tAND ID_BOARD IN (" . implode(',', array_keys($board_info['parent_boards'])) . ")", __FILE__, __LINE__); } } // Turn notification on or off. (note this just blows smoke if it's already on or off.) if (!empty($_POST['notify'])) { if (allowedTo('mark_any_notify')) { db_query("\n\t\t\t\tINSERT IGNORE INTO {$db_prefix}log_notify\n\t\t\t\t\t(ID_MEMBER, ID_TOPIC, ID_BOARD)\n\t\t\t\tVALUES ({$ID_MEMBER}, {$topic}, 0)", __FILE__, __LINE__); } } elseif (!$newTopic) { db_query("\n\t\t\tDELETE FROM {$db_prefix}log_notify\n\t\t\tWHERE ID_MEMBER = {$ID_MEMBER}\n\t\t\t\tAND ID_TOPIC = {$topic}\n\t\t\tLIMIT 1", __FILE__, __LINE__); } // Log an act of moderation - modifying. if (!empty($moderationAction)) { logAction('modify', array('topic' => $topic, 'message' => (int) $_REQUEST['msg'], 'member' => $row['ID_MEMBER'])); } if (isset($_POST['lock']) && $_POST['lock'] != 2) { logAction('lock', array('topic' => $topicOptions['id'])); } if (isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics'])) { logAction('sticky', array('topic' => $topicOptions['id'])); } // Notify any members who have notification turned on for this topic. if ($newTopic) { notifyMembersBoard(); } elseif (empty($_REQUEST['msg'])) { sendNotifications($topic, 'reply'); } // Returning to the topic? if (!empty($_REQUEST['goback'])) { // Mark the board as read.... because it might get confusing otherwise. db_query("\n\t\t\tUPDATE {$db_prefix}log_boards\n\t\t\tSET ID_MSG = {$modSettings['maxMsgID']}\n\t\t\tWHERE ID_MEMBER = {$ID_MEMBER}\n\t\t\t\tAND ID_BOARD = {$board}", __FILE__, __LINE__); } if (!empty($_POST['announce_topic'])) { redirectexit('action=announce;sa=selectgroup;topic=' . $topic . (!empty($_POST['move']) && allowedTo('move_any') ? ';move' : '') . (empty($_REQUEST['goback']) ? '' : ';goback')); } if (!empty($_POST['move']) && allowedTo('move_any')) { redirectexit('action=movetopic;topic=' . $topic . '.0' . (empty($_REQUEST['goback']) ? '' : ';goback')); } // Return to post if the mod is on. if (isset($_REQUEST['msg']) && !empty($_REQUEST['goback'])) { redirectexit('topic=' . $topic . '.msg' . $_REQUEST['msg'] . '#msg' . $_REQUEST['msg'], $context['browser']['is_ie']); } elseif (!empty($_REQUEST['goback'])) { redirectexit('topic=' . $topic . '.new#new', $context['browser']['is_ie']); } else { redirectexit('board=' . $board . '.0'); } }
function registerMember(&$regOptions) { global $scripturl, $txt, $modSettings, $db_prefix, $context, $sourcedir; global $user_info, $options, $settings, $func; loadLanguage('Login'); // We'll need some external functions. require_once $sourcedir . '/Subs-Auth.php'; require_once $sourcedir . '/Subs-Post.php'; // Registration from the admin center, let them sweat a little more. if ($regOptions['interface'] == 'admin') { is_not_guest(); isAllowedTo('moderate_forum'); } elseif ($regOptions['interface'] == 'guest') { spamProtection('register'); // You cannot register twice... if (empty($user_info['is_guest'])) { redirectexit(); } // Make sure they didn't just register with this session. if (!empty($_SESSION['just_registered']) && empty($modSettings['disableRegisterCheck'])) { fatal_lang_error('register_only_once', false); } } // No name?! How can you register with no name? if (empty($regOptions['username'])) { fatal_lang_error(37, false); } // Spaces and other odd characters are evil... $regOptions['username'] = preg_replace('~[\\t\\n\\r\\x0B\\0' . ($context['utf8'] ? $context['server']['complex_preg_chars'] ? '\\x{A0}' : pack('C*', 0xc2, 0xa0) : '\\xA0') . ']+~' . ($context['utf8'] ? 'u' : ''), ' ', $regOptions['username']); // Don't use too long a name. if ($func['strlen']($regOptions['username']) > 25) { $regOptions['username'] = $func['htmltrim']($func['substr']($regOptions['username'], 0, 25)); } // Only these characters are permitted. if (preg_match('~[<>&"\'=\\\\]~', $regOptions['username']) != 0 || $regOptions['username'] == '_' || $regOptions['username'] == '|' || strpos($regOptions['username'], '[code') !== false || strpos($regOptions['username'], '[/code') !== false) { fatal_lang_error(240, false); } if (stristr($regOptions['username'], $txt[28]) !== false) { fatal_lang_error(244, true, array($txt[28])); } // !!! Separate the sprintf? if (empty($regOptions['email']) || preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', stripslashes($regOptions['email'])) === 0 || strlen(stripslashes($regOptions['email'])) > 255) { fatal_error(sprintf($txt[500], $regOptions['username']), false); } if (!empty($regOptions['check_reserved_name']) && isReservedName($regOptions['username'], 0, false)) { if ($regOptions['password'] == 'chocolate cake') { fatal_error('Sorry, I don\'t take bribes... you\'ll need to come up with a different name.', false); } fatal_error('(' . htmlspecialchars($regOptions['username']) . ') ' . $txt[473], false); } // Generate a validation code if it's supposed to be emailed. $validation_code = ''; if ($regOptions['require'] == 'activation') { $validation_code = generateValidationCode(); } // If you haven't put in a password generated one. if ($regOptions['interface'] == 'admin' && $regOptions['password'] == '') { mt_srand(time() + 1277); $regOptions['password'] = generateValidationCode(); $regOptions['password_check'] = $regOptions['password']; } elseif ($regOptions['password'] != $regOptions['password_check']) { fatal_lang_error(213, false); } // That's kind of easy to guess... if ($regOptions['password'] == '') { fatal_lang_error(91, false); } // Now perform hard password validation as required. if (!empty($regOptions['check_password_strength'])) { $passwordError = validatePassword($regOptions['password'], $regOptions['username'], array($regOptions['email'])); // Password isn't legal? if ($passwordError != null) { fatal_lang_error('profile_error_password_' . $passwordError, false); } } // You may not be allowed to register this email. if (!empty($regOptions['check_email_ban'])) { isBannedEmail($regOptions['email'], 'cannot_register', $txt['ban_register_prohibited']); } // Check if the email address is in use. $request = db_query("\n\t\tSELECT ID_MEMBER\n\t\tFROM {$db_prefix}members\n\t\tWHERE emailAddress = '{$regOptions['email']}'\n\t\t\tOR emailAddress = '{$regOptions['username']}'\n\t\tLIMIT 1", __FILE__, __LINE__); // !!! Separate the sprintf? if (mysql_num_rows($request) != 0) { fatal_error(sprintf($txt[730], htmlspecialchars($regOptions['email'])), false); } mysql_free_result($request); // Some of these might be overwritten. (the lower ones that are in the arrays below.) $regOptions['register_vars'] = array('memberName' => "'{$regOptions['username']}'", 'emailAddress' => "'{$regOptions['email']}'", 'passwd' => '\'' . sha1(strtolower($regOptions['username']) . $regOptions['password']) . '\'', 'passwordSalt' => '\'' . substr(md5(mt_rand()), 0, 4) . '\'', 'posts' => 0, 'dateRegistered' => time(), 'memberIP' => "'{$user_info['ip']}'", 'memberIP2' => "'{$_SERVER['BAN_CHECK_IP']}'", 'validation_code' => "'{$validation_code}'", 'realName' => "'{$regOptions['username']}'", 'personalText' => '\'' . addslashes($modSettings['default_personalText']) . '\'', 'pm_email_notify' => 1, 'ID_THEME' => 0, 'ID_POST_GROUP' => 4, 'lngfile' => "''", 'buddy_list' => "''", 'pm_ignore_list' => "''", 'messageLabels' => "''", 'personalText' => "''", 'websiteTitle' => "''", 'websiteUrl' => "''", 'location' => "''", 'ICQ' => "''", 'AIM' => "''", 'YIM' => "''", 'MSN' => "''", 'timeFormat' => "''", 'signature' => "''", 'avatar' => "''", 'usertitle' => "''", 'secretQuestion' => "''", 'secretAnswer' => "''", 'additionalGroups' => "''", 'smileySet' => "''"); // Setup the activation status on this new account so it is correct - firstly is it an under age account? if ($regOptions['require'] == 'coppa') { $regOptions['register_vars']['is_activated'] = 5; // !!! This should be changed. To what should be it be changed?? $regOptions['register_vars']['validation_code'] = "''"; } elseif ($regOptions['require'] == 'nothing') { $regOptions['register_vars']['is_activated'] = 1; } elseif ($regOptions['require'] == 'activation') { $regOptions['register_vars']['is_activated'] = 0; } else { $regOptions['register_vars']['is_activated'] = 3; } if (isset($regOptions['memberGroup'])) { // Make sure the ID_GROUP will be valid, if this is an administator. $regOptions['register_vars']['ID_GROUP'] = $regOptions['memberGroup'] == 1 && !allowedTo('admin_forum') ? 0 : $regOptions['memberGroup']; // Check if this group is assignable. $unassignableGroups = array(-1, 3); $request = db_query("\n\t\t\tSELECT ID_GROUP\n\t\t\tFROM {$db_prefix}membergroups\n\t\t\tWHERE minPosts != -1", __FILE__, __LINE__); while ($row = mysql_fetch_assoc($request)) { $unassignableGroups[] = $row['ID_GROUP']; } mysql_free_result($request); if (in_array($regOptions['register_vars']['ID_GROUP'], $unassignableGroups)) { $regOptions['register_vars']['ID_GROUP'] = 0; } } // Integrate optional member settings to be set. if (!empty($regOptions['extra_register_vars'])) { foreach ($regOptions['extra_register_vars'] as $var => $value) { $regOptions['register_vars'][$var] = $value; } } // Integrate optional user theme options to be set. $theme_vars = array(); if (!empty($regOptions['theme_vars'])) { foreach ($regOptions['theme_vars'] as $var => $value) { $theme_vars[$var] = $value; } } // Call an optional function to validate the users' input. if (isset($modSettings['integrate_register']) && function_exists($modSettings['integrate_register'])) { $modSettings['integrate_register']($regOptions, $theme_vars); } // Register them into the database. db_query("\n\t\tINSERT INTO {$db_prefix}members\n\t\t\t(" . implode(', ', array_keys($regOptions['register_vars'])) . ")\n\t\tVALUES (" . implode(', ', $regOptions['register_vars']) . ')', __FILE__, __LINE__); $memberID = db_insert_id(); // Grab their real name and send emails using it. $realName = substr($regOptions['register_vars']['realName'], 1, -1); // Update the number of members and latest member's info - and pass the name, but remove the 's. updateStats('member', $memberID, $realName); // Theme variables too? if (!empty($theme_vars)) { $setString = ''; foreach ($theme_vars as $var => $val) { $setString .= "\n\t\t\t\t({$memberID}, SUBSTRING('{$var}', 1, 255), SUBSTRING('{$val}', 1, 65534)),"; } db_query("\n\t\t\tINSERT INTO {$db_prefix}themes\n\t\t\t\t(ID_MEMBER, variable, value)\n\t\t\tVALUES " . substr($setString, 0, -1), __FILE__, __LINE__); } // If it's enabled, increase the registrations for today. trackStats(array('registers' => '+')); // Administrative registrations are a bit different... if ($regOptions['interface'] == 'admin') { if ($regOptions['require'] == 'activation') { $email_message = 'register_activate_message'; } elseif (!empty($regOptions['send_welcome_email'])) { $email_message = 'register_immediate_message'; } if (isset($email_message)) { sendmail($regOptions['email'], $txt['register_subject'], sprintf($txt[$email_message], $realName, $regOptions['username'], $regOptions['password'], $validation_code, $scripturl . '?action=activate;u=' . $memberID . ';code=' . $validation_code)); } // All admins are finished here. return $memberID; } // Can post straight away - welcome them to your fantastic community... if ($regOptions['require'] == 'nothing') { if (!empty($regOptions['send_welcome_email'])) { sendmail($regOptions['email'], $txt['register_subject'], sprintf($txt['register_immediate_message'], $realName, $regOptions['username'], $regOptions['password'])); } // Send admin their notification. adminNotify('standard', $memberID, $regOptions['username']); } elseif ($regOptions['require'] == 'activation' || $regOptions['require'] == 'coppa') { sendmail($regOptions['email'], $txt['register_subject'], sprintf($txt['register_activate_message'], $realName, $regOptions['username'], $regOptions['password'], $validation_code, $scripturl . '?action=activate;u=' . $memberID . ';code=' . $validation_code)); } else { sendmail($regOptions['email'], $txt['register_subject'], sprintf($txt['register_pending_message'], $realName, $regOptions['username'], $regOptions['password'])); // Admin gets informed here... adminNotify('approval', $memberID, $regOptions['username']); } // Okay, they're for sure registered... make sure the session is aware of this for security. (Just married :P!) $_SESSION['just_registered'] = 1; return $memberID; }
function resetPassword($memID, $username = null) { global $db_prefix, $scripturl, $context, $txt, $sourcedir, $modSettings; // Language... and a required file. loadLanguage('Login'); require_once $sourcedir . '/Subs-Post.php'; // Get some important details. $request = db_query("\n\t\tSELECT memberName, emailAddress\n\t\tFROM {$db_prefix}members\n\t\tWHERE ID_MEMBER = {$memID}", __FILE__, __LINE__); list($user, $email) = mysql_fetch_row($request); mysql_free_result($request); if ($username !== null) { $old_user = $user; $user = trim($username); } // Generate a random password. require_once $sourcedir . '/Subs-Members.php'; $newPassword = generateValidationCode(); $newPassword_sha1 = sha1(strtolower($user) . $newPassword); // Do some checks on the username if needed. if ($username !== null) { // No name?! How can you register with no name? if ($user == '') { fatal_lang_error(37, false); } // Only these characters are permitted. if (in_array($user, array('_', '|')) || preg_match('~[<>&"\'=\\\\]~', $user) != 0 || strpos($user, '[code') !== false || strpos($user, '[/code') !== false) { fatal_lang_error(240, false); } if (stristr($user, $txt[28]) !== false) { fatal_lang_error(244, true, array($txt[28])); } require_once $sourcedir . '/Subs-Members.php'; if (isReservedName($user, $memID, false)) { fatal_error('(' . htmlspecialchars($user) . ') ' . $txt[473], false); } // Update the database... updateMemberData($memID, array('memberName' => '\'' . $user . '\'', 'passwd' => '\'' . $newPassword_sha1 . '\'')); } else { updateMemberData($memID, array('passwd' => '\'' . $newPassword_sha1 . '\'')); } if (isset($modSettings['integrate_reset_pass']) && function_exists($modSettings['integrate_reset_pass'])) { call_user_func($modSettings['integrate_reset_pass'], $old_user, $user, $newPassword); } // Send them the email informing them of the change - then we're done! sendmail($email, $txt['change_password'], "{$txt['hello_member']} {$user}!\n\n" . "{$txt['change_password_1']} {$context['forum_name']} {$txt['change_password_2']}\n\n" . "{$txt['719']}{$user}, {$txt['492']} {$newPassword}\n\n" . "{$txt['701']}\n" . "{$scripturl}?action=profile\n\n" . $txt[130]); }
function Register2() { global $scripturl, $txt, $modSettings, $db_prefix, $context, $sourcedir; global $user_info, $options, $settings, $func; // Well, if you don't agree, you can't register. if (!empty($modSettings['requireAgreement']) && (empty($_POST['regagree']) || $_POST['regagree'] == 'no')) { redirectexit(); } // Make sure they came from *somewhere*, have a session. if (!isset($_SESSION['old_url'])) { redirectexit('action=register'); } // You can't register if it's disabled. if (!empty($modSettings['registration_method']) && $modSettings['registration_method'] == 3) { fatal_lang_error('registration_disabled', false); } foreach ($_POST as $key => $value) { if (!is_array($_POST[$key])) { $_POST[$key] = htmltrim__recursive(str_replace(array("\n", "\r"), '', $_POST[$key])); } } // Did they answer the verification questions correctly? if (!empty($modSettings['anti_spam_ver_enable'])) { if (!empty($modSettings['anti_spam_ver_ques_1']) && strcmp(strtolower($modSettings['anti_spam_ver_ans_1']), isset($_POST['anti_spam_ver_resp_1']) ? strtolower($_POST['anti_spam_ver_resp_1']) : '') || !empty($modSettings['anti_spam_ver_ques_2']) && strcmp(strtolower($modSettings['anti_spam_ver_ans_2']), isset($_POST['anti_spam_ver_resp_2']) ? strtolower($_POST['anti_spam_ver_resp_2']) : '') || !empty($modSettings['anti_spam_ver_ques_3']) && strcmp(strtolower($modSettings['anti_spam_ver_ans_3']), isset($_POST['anti_spam_ver_resp_3']) ? strtolower($_POST['anti_spam_ver_resp_3']) : '') || !empty($modSettings['anti_spam_ver_ques_4']) && strcmp(strtolower($modSettings['anti_spam_ver_ans_4']), isset($_POST['anti_spam_ver_resp_4']) ? strtolower($_POST['anti_spam_ver_resp_4']) : '') || !empty($modSettings['anti_spam_ver_ques_5']) && strcmp(strtolower($modSettings['anti_spam_ver_ans_5']), isset($_POST['anti_spam_ver_resp_5']) ? strtolower($_POST['anti_spam_ver_resp_5']) : '')) { fatal_lang_error('anti_spam_ver_failed', false); } } // Are they under age, and under age users are banned? if (!empty($modSettings['coppaAge']) && empty($modSettings['coppaType']) && !isset($_POST['skip_coppa'])) { // !!! This should be put in Errors, imho. loadLanguage('Login'); fatal_lang_error('under_age_registration_prohibited', false, array($modSettings['coppaAge'])); } // Check whether the visual verification code was entered correctly. if ((empty($modSettings['disable_visual_verification']) || $modSettings['disable_visual_verification'] != 1) && (empty($_REQUEST['visual_verification_code']) || strtoupper($_REQUEST['visual_verification_code']) !== $_SESSION['visual_verification_code'])) { $_SESSION['visual_errors'] = isset($_SESSION['visual_errors']) ? $_SESSION['visual_errors'] + 1 : 1; if ($_SESSION['visual_errors'] > 3 && isset($_SESSION['visual_verification_code'])) { unset($_SESSION['visual_verification_code']); } fatal_lang_error('visual_verification_failed', false); } elseif (isset($_SESSION['visual_errors'])) { unset($_SESSION['visual_errors']); } // Collect all extra registration fields someone might have filled in. $possible_strings = array('websiteUrl', 'websiteTitle', 'AIM', 'YIM', 'location', 'birthdate', 'timeFormat', 'buddy_list', 'pm_ignore_list', 'smileySet', 'signature', 'personalText', 'avatar', 'lngfile', 'secretQuestion', 'secretAnswer'); $possible_ints = array('pm_email_notify', 'notifyTypes', 'ICQ', 'gender', 'ID_THEME'); $possible_floats = array('timeOffset'); $possible_bools = array('notifyAnnouncements', 'notifyOnce', 'notifySendBody', 'hideEmail', 'showOnline'); if (isset($_POST['secretAnswer']) && $_POST['secretAnswer'] != '') { $_POST['secretAnswer'] = md5($_POST['secretAnswer']); } // Needed for isReservedName() and registerMember(). require_once $sourcedir . '/Subs-Members.php'; // Validation... even if we're not a mall. if (isset($_POST['realName']) && (!empty($modSettings['allow_editDisplayName']) || allowedTo('moderate_forum'))) { $_POST['realName'] = trim(preg_replace('~[\\s]~' . ($context['utf8'] ? 'u' : ''), ' ', $_POST['realName'])); if (trim($_POST['realName']) != '' && !isReservedName($_POST['realName']) && $func['strlen']($_POST['realName']) <= 60) { $possible_strings[] = 'realName'; } } if (isset($_POST['MSN']) && preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', $_POST['MSN']) != 0) { $profile_strings[] = 'MSN'; } // Handle a string as a birthdate... if (isset($_POST['birthdate']) && $_POST['birthdate'] != '') { $_POST['birthdate'] = strftime('%Y-%m-%d', strtotime($_POST['birthdate'])); } elseif (!empty($_POST['bday1']) && !empty($_POST['bday2'])) { $_POST['birthdate'] = sprintf('%04d-%02d-%02d', empty($_POST['bday3']) ? 0 : (int) $_POST['bday3'], (int) $_POST['bday1'], (int) $_POST['bday2']); } // Validate the passed langauge file. if (isset($_POST['lngfile']) && !empty($modSettings['userLanguage'])) { $language_directories = array($settings['default_theme_dir'] . '/languages', $settings['actual_theme_dir'] . '/languages'); if (!empty($settings['base_theme_dir'])) { $language_directories[] = $settings['base_theme_dir'] . '/languages'; } $language_directories = array_unique($language_directories); foreach ($language_directories as $language_dir) { if (!file_exists($language_dir)) { continue; } $dir = dir($language_dir); while ($entry = $dir->read()) { if (preg_match('~^index\\.(.+)\\.php$~', $entry, $matches) && $matches[1] == $_POST['lngfile']) { // Got it! $found = true; $_SESSION['language'] = $_POST['lngfile']; break 2; } } $dir->close(); } if (empty($found)) { unset($_POST['lngfile']); } } else { unset($_POST['lngfile']); } // Set the options needed for registration. $regOptions = array('interface' => 'guest', 'username' => $_POST['user'], 'email' => $_POST['email'], 'password' => $_POST['passwrd1'], 'password_check' => $_POST['passwrd2'], 'check_reserved_name' => true, 'check_password_strength' => true, 'check_email_ban' => true, 'send_welcome_email' => !empty($modSettings['send_welcomeEmail']), 'require' => !empty($modSettings['coppaAge']) && !isset($_POST['skip_coppa']) ? 'coppa' : (empty($modSettings['registration_method']) ? 'nothing' : ($modSettings['registration_method'] == 1 ? 'activation' : 'approval')), 'extra_register_vars' => array(), 'theme_vars' => array()); // Include the additional options that might have been filled in. foreach ($possible_strings as $var) { if (isset($_POST[$var])) { $regOptions['extra_register_vars'][$var] = '\'' . $func['htmlspecialchars']($_POST[$var]) . '\''; } } foreach ($possible_ints as $var) { if (isset($_POST[$var])) { $regOptions['extra_register_vars'][$var] = (int) $_POST[$var]; } } foreach ($possible_floats as $var) { if (isset($_POST[$var])) { $regOptions['extra_register_vars'][$var] = (double) $_POST[$var]; } } foreach ($possible_bools as $var) { if (isset($_POST[$var])) { $regOptions['extra_register_vars'][$var] = empty($_POST[$var]) ? 0 : 1; } } // Registration options are always default options... if (isset($_POST['default_options'])) { $_POST['options'] = isset($_POST['options']) ? $_POST['options'] + $_POST['default_options'] : $_POST['default_options']; } $regOptions['theme_vars'] = isset($_POST['options']) && is_array($_POST['options']) ? htmlspecialchars__recursive($_POST['options']) : array(); $memberID = registerMember($regOptions); // If COPPA has been selected then things get complicated, setup the template. if (!empty($modSettings['coppaAge']) && !isset($_POST['skip_coppa'])) { redirectexit('action=coppa;member=' . $memberID); } elseif (!empty($modSettings['registration_method'])) { loadTemplate('Register'); $context += array('page_title' => &$txt[97], 'sub_template' => 'after', 'description' => $modSettings['registration_method'] == 2 ? $txt['approval_after_registration'] : $txt['activate_after_registration']); } else { setLoginCookie(60 * $modSettings['cookieTime'], $memberID, sha1(sha1(strtolower($regOptions['username']) . $regOptions['password']) . substr($regOptions['register_vars']['passwordSalt'], 1, -1))); redirectexit('action=login2;sa=check;member=' . $memberID, $context['server']['needs_login_fix']); } }
function RegisterCheckUsername() { global $sourcedir, $smcFunc, $context, $txt; // This is XML! loadTemplate('Xml'); $context['sub_template'] = 'check_username'; $context['checked_username'] = isset($_GET['username']) ? $_GET['username'] : ''; $context['valid_username'] = true; // Clean it up like mother would. $context['checked_username'] = preg_replace('~[\\t\\n\\r \\x0B\\0' . ($context['utf8'] ? $context['server']['complex_preg_chars'] ? '\\x{A0}\\x{AD}\\x{2000}-\\x{200F}\\x{201F}\\x{202F}\\x{3000}\\x{FEFF}' : " -‟ ‟ " : '\\x00-\\x08\\x0B\\x0C\\x0E-\\x19\\xA0') . ']+~' . ($context['utf8'] ? 'u' : ''), ' ', $context['checked_username']); if ($smcFunc['strlen']($context['checked_username']) > 25) { $context['checked_username'] = $smcFunc['htmltrim']($smcFunc['substr']($context['checked_username'], 0, 25)); } //xxx only allow these characters if (!RegisterUserIsAllowed($context['checked_username'], "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ /-:.%0123456789_")) { $context['valid_username'] = false; } // Only these characters are permitted. if (preg_match('~[<>&"\'=\\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $context['checked_username'])) != 0 || $context['checked_username'] == '_' || $context['checked_username'] == '|' || strpos($context['checked_username'], '[code') !== false || strpos($context['checked_username'], '[/code') !== false) { $context['valid_username'] = false; } if (stristr($context['checked_username'], $txt['guest_title']) !== false) { $context['valid_username'] = false; } if (trim($context['checked_username']) == '') { $context['valid_username'] = false; } else { require_once $sourcedir . '/Subs-Members.php'; $context['valid_username'] &= isReservedName($context['checked_username'], 0, false, false) ? 0 : 1; } }
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]); } } }
/** * Checks a username obeys a load of rules * * - Returns null if fine * * @package Authorization * @param int $memID * @param string $username * @param string $error_context * @param boolean $check_reserved_name * @param boolean $fatal pass through to isReservedName * @return string */ function validateUsername($memID, $username, $error_context = 'register', $check_reserved_name = true, $fatal = true) { global $txt; $errors = Error_Context::context($error_context, 0); // Don't use too long a name. if (Util::strlen($username) > 25) { $errors->addError('error_long_name'); } // No name?! How can you register with no name? if ($username == '') { $errors->addError('need_username'); } // Only these characters are permitted. if (in_array($username, array('_', '|')) || preg_match('~[<>&"\'=\\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $username)) != 0 || strpos($username, '[code') !== false || strpos($username, '[/code') !== false) { $errors->addError('error_invalid_characters_username'); } if (stristr($username, $txt['guest_title']) !== false) { $errors->addError(array('username_reserved', array($txt['guest_title'])), 1); } if ($check_reserved_name) { require_once SUBSDIR . '/Members.subs.php'; if (isReservedName($username, $memID, false, $fatal)) { $errors->addError(array('name_in_use', array(htmlspecialchars($username, ENT_COMPAT, 'UTF-8')))); } } }
/** * Posts or saves the message composed with Post(). * * requires various permissions depending on the action. * handles attachment, post, and calendar saving. * sends off notifications, and allows for announcements and moderation. * accessed from ?action=post2. */ public function action_post2() { global $board, $topic, $txt, $modSettings, $context, $user_settings; global $user_info, $board_info, $options, $ignore_temp; // Sneaking off, are we? if (empty($_POST) && empty($topic)) { if (empty($_SERVER['CONTENT_LENGTH'])) { redirectexit('action=post;board=' . $board . '.0'); } else { fatal_lang_error('post_upload_error', false); } } elseif (empty($_POST) && !empty($topic)) { redirectexit('action=post;topic=' . $topic . '.0'); } // No need! $context['robot_no_index'] = true; // We are now in post2 action $context['current_action'] = 'post2'; require_once SOURCEDIR . '/AttachmentErrorContext.class.php'; // No errors as yet. $post_errors = Error_Context::context('post', 1); $attach_errors = Attachment_Error_Context::context(); // If the session has timed out, let the user re-submit their form. if (checkSession('post', '', false) != '') { $post_errors->addError('session_timeout'); // Disable the preview so that any potentially malicious code is not executed $_REQUEST['preview'] = false; return $this->action_post(); } // Wrong verification code? if (!$user_info['is_admin'] && !$user_info['is_mod'] && !empty($modSettings['posts_require_captcha']) && ($user_info['posts'] < $modSettings['posts_require_captcha'] || $user_info['is_guest'] && $modSettings['posts_require_captcha'] == -1)) { require_once SUBSDIR . '/VerificationControls.class.php'; $verificationOptions = array('id' => 'post'); $context['require_verification'] = create_control_verification($verificationOptions, true); if (is_array($context['require_verification'])) { foreach ($context['require_verification'] as $verification_error) { $post_errors->addError($verification_error); } } } require_once SUBSDIR . '/Boards.subs.php'; require_once SUBSDIR . '/Post.subs.php'; loadLanguage('Post'); // Drafts enabled and needed? if (!empty($modSettings['drafts_enabled']) && (isset($_POST['save_draft']) || isset($_POST['id_draft']))) { require_once SUBSDIR . '/Drafts.subs.php'; } // First check to see if they are trying to delete any current attachments. if (isset($_POST['attach_del'])) { $keep_temp = array(); $keep_ids = array(); foreach ($_POST['attach_del'] as $dummy) { if (strpos($dummy, 'post_tmp_' . $user_info['id']) !== false) { $keep_temp[] = $dummy; } else { $keep_ids[] = (int) $dummy; } } if (isset($_SESSION['temp_attachments'])) { foreach ($_SESSION['temp_attachments'] as $attachID => $attachment) { if (isset($_SESSION['temp_attachments']['post']['files'], $attachment['name']) && in_array($attachment['name'], $_SESSION['temp_attachments']['post']['files']) || in_array($attachID, $keep_temp) || strpos($attachID, 'post_tmp_' . $user_info['id']) === false) { continue; } unset($_SESSION['temp_attachments'][$attachID]); @unlink($attachment['tmp_name']); } } if (!empty($_REQUEST['msg'])) { require_once SUBSDIR . '/ManageAttachments.subs.php'; $attachmentQuery = array('attachment_type' => 0, 'id_msg' => (int) $_REQUEST['msg'], 'not_id_attach' => $keep_ids); removeAttachments($attachmentQuery); } } // Then try to upload any attachments. $context['attachments']['can']['post'] = !empty($modSettings['attachmentEnable']) && $modSettings['attachmentEnable'] == 1 && (allowedTo('post_attachment') || $modSettings['postmod_active'] && allowedTo('post_unapproved_attachments')); if ($context['attachments']['can']['post'] && empty($_POST['from_qr'])) { require_once SUBSDIR . '/Attachments.subs.php'; if (isset($_REQUEST['msg'])) { processAttachments((int) $_REQUEST['msg']); } else { processAttachments(); } } // Previewing? Go back to start. if (isset($_REQUEST['preview'])) { return $this->action_post(); } // Prevent double submission of this form. checkSubmitOnce('check'); // If this isn't a new topic load the topic info that we need. if (!empty($topic)) { require_once SUBSDIR . '/Topic.subs.php'; $topic_info = getTopicInfo($topic); // Though the topic should be there, it might have vanished. if (empty($topic_info)) { fatal_lang_error('topic_doesnt_exist'); } // Did this topic suddenly move? Just checking... if ($topic_info['id_board'] != $board) { fatal_lang_error('not_a_topic'); } } // Replying to a topic? if (!empty($topic) && !isset($_REQUEST['msg'])) { // Don't allow a post if it's locked. if ($topic_info['locked'] != 0 && !allowedTo('moderate_board')) { fatal_lang_error('topic_locked', false); } // Sorry, multiple polls aren't allowed... yet. You should stop giving me ideas :P. if (isset($_REQUEST['poll']) && $topic_info['id_poll'] > 0) { unset($_REQUEST['poll']); } // Do the permissions and approval stuff... $becomesApproved = true; if ($topic_info['id_member_started'] != $user_info['id']) { if ($modSettings['postmod_active'] && allowedTo('post_unapproved_replies_any') && !allowedTo('post_reply_any')) { $becomesApproved = false; } else { isAllowedTo('post_reply_any'); } } elseif (!allowedTo('post_reply_any')) { if ($modSettings['postmod_active']) { if (allowedTo('post_unapproved_replies_own') && !allowedTo('post_reply_own')) { $becomesApproved = false; } elseif ($user_info['is_guest'] && allowedTo('post_unapproved_replies_any')) { $becomesApproved = false; } else { isAllowedTo('post_reply_own'); } } } if (isset($_POST['lock'])) { // Nothing is changed to the lock. if (empty($topic_info['locked']) && empty($_POST['lock']) || !empty($_POST['lock']) && !empty($topic_info['locked'])) { unset($_POST['lock']); } elseif (!allowedTo(array('lock_any', 'lock_own')) || !allowedTo('lock_any') && $user_info['id'] != $topic_info['id_member_started']) { unset($_POST['lock']); } elseif (!allowedTo('lock_any')) { // You cannot override a moderator lock. if ($topic_info['locked'] == 1) { unset($_POST['lock']); } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 2; } } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 1; } } // So you wanna (un)sticky this...let's see. if (isset($_POST['sticky']) && (empty($modSettings['enableStickyTopics']) || $_POST['sticky'] == $topic_info['is_sticky'] || !allowedTo('make_sticky'))) { unset($_POST['sticky']); } // If drafts are enabled, then pass this off if (!empty($modSettings['drafts_enabled']) && isset($_POST['save_draft'])) { saveDraft(); return $this->action_post(); } // If the number of replies has changed, if the setting is enabled, go back to action_post() - which handles the error. if (empty($options['no_new_reply_warning']) && isset($_POST['last_msg']) && $topic_info['id_last_msg'] > $_POST['last_msg']) { addInlineJavascript(' $(document).ready(function () { $("html,body").scrollTop($(\'.category_header:visible:first\').offset().top); });'); return $this->action_post(); } $posterIsGuest = $user_info['is_guest']; } elseif (empty($topic)) { // Now don't be silly, new topics will get their own id_msg soon enough. unset($_REQUEST['msg'], $_POST['msg'], $_GET['msg']); // Do like, the permissions, for safety and stuff... $becomesApproved = true; if ($modSettings['postmod_active'] && !allowedTo('post_new') && allowedTo('post_unapproved_topics')) { $becomesApproved = false; } else { isAllowedTo('post_new'); } if (isset($_POST['lock'])) { // New topics are by default not locked. if (empty($_POST['lock'])) { unset($_POST['lock']); } elseif (!allowedTo(array('lock_any', 'lock_own'))) { unset($_POST['lock']); } else { $_POST['lock'] = allowedTo('lock_any') ? 1 : 2; } } if (isset($_POST['sticky']) && (empty($modSettings['enableStickyTopics']) || empty($_POST['sticky']) || !allowedTo('make_sticky'))) { unset($_POST['sticky']); } // Saving your new topic as a draft first? if (!empty($modSettings['drafts_enabled']) && isset($_POST['save_draft'])) { saveDraft(); return $this->action_post(); } $posterIsGuest = $user_info['is_guest']; } elseif (isset($_REQUEST['msg']) && !empty($topic)) { $_REQUEST['msg'] = (int) $_REQUEST['msg']; require_once SUBSDIR . '/Messages.subs.php'; $msgInfo = basicMessageInfo($_REQUEST['msg'], true); if (empty($msgInfo)) { fatal_lang_error('cant_find_messages', false); } if (!empty($topic_info['locked']) && !allowedTo('moderate_board')) { fatal_lang_error('topic_locked', false); } if (isset($_POST['lock'])) { // Nothing changes to the lock status. if (empty($_POST['lock']) && empty($topic_info['locked']) || !empty($_POST['lock']) && !empty($topic_info['locked'])) { unset($_POST['lock']); } elseif (!allowedTo(array('lock_any', 'lock_own')) || !allowedTo('lock_any') && $user_info['id'] != $topic_info['id_member_started']) { unset($_POST['lock']); } elseif (!allowedTo('lock_any')) { // You're not allowed to break a moderator's lock. if ($topic_info['locked'] == 1) { unset($_POST['lock']); } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 2; } } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 1; } } // Change the sticky status of this topic? if (isset($_POST['sticky']) && (!allowedTo('make_sticky') || $_POST['sticky'] == $topic_info['is_sticky'])) { unset($_POST['sticky']); } if ($msgInfo['id_member'] == $user_info['id'] && !allowedTo('modify_any')) { if ((!$modSettings['postmod_active'] || $msgInfo['approved']) && !empty($modSettings['edit_disable_time']) && $msgInfo['poster_time'] + ($modSettings['edit_disable_time'] + 5) * 60 < time()) { fatal_lang_error('modify_post_time_passed', false); } elseif ($topic_info['id_member_started'] == $user_info['id'] && !allowedTo('modify_own')) { isAllowedTo('modify_replies'); } else { isAllowedTo('modify_own'); } } elseif ($topic_info['id_member_started'] == $user_info['id'] && !allowedTo('modify_any')) { isAllowedTo('modify_replies'); // If you're modifying a reply, I say it better be logged... $moderationAction = true; } else { isAllowedTo('modify_any'); // Log it, assuming you're not modifying your own post. if ($msgInfo['id_member'] != $user_info['id']) { $moderationAction = true; } } // If drafts are enabled, then lets send this off to save if (!empty($modSettings['drafts_enabled']) && isset($_POST['save_draft'])) { saveDraft(); return $this->action_post(); } $posterIsGuest = empty($msgInfo['id_member']); // Can they approve it? $can_approve = allowedTo('approve_posts'); $becomesApproved = $modSettings['postmod_active'] ? $can_approve && !$msgInfo['approved'] ? !empty($_REQUEST['approve']) ? 1 : 0 : $msgInfo['approved'] : 1; $approve_has_changed = $msgInfo['approved'] != $becomesApproved; if (!allowedTo('moderate_forum') || !$posterIsGuest) { $_POST['guestname'] = $msgInfo['poster_name']; $_POST['email'] = $msgInfo['poster_email']; } } // In case we want to override if (allowedTo('approve_posts')) { $becomesApproved = !isset($_REQUEST['approve']) || !empty($_REQUEST['approve']) ? 1 : 0; $approve_has_changed = isset($msgInfo['approved']) ? $msgInfo['approved'] != $becomesApproved : false; } // If the poster is a guest evaluate the legality of name and email. if ($posterIsGuest) { $_POST['guestname'] = !isset($_POST['guestname']) ? '' : Util::htmlspecialchars(trim($_POST['guestname'])); $_POST['email'] = !isset($_POST['email']) ? '' : Util::htmlspecialchars(trim($_POST['email'])); if ($_POST['guestname'] == '' || $_POST['guestname'] == '_') { $post_errors->addError('no_name'); } if (Util::strlen($_POST['guestname']) > 25) { $post_errors->addError('long_name'); } if (empty($modSettings['guest_post_no_email'])) { // Only check if they changed it! if (!isset($msgInfo) || $msgInfo['poster_email'] != $_POST['email']) { require_once SUBSDIR . '/DataValidator.class.php'; if (!allowedTo('moderate_forum') && !Data_Validator::is_valid($_POST, array('email' => 'valid_email|required'), array('email' => 'trim'))) { empty($_POST['email']) ? $post_errors->addError('no_email') : $post_errors->addError('bad_email'); } } // Now make sure this email address is not banned from posting. isBannedEmail($_POST['email'], 'cannot_post', sprintf($txt['you_are_post_banned'], $txt['guest_title'])); } // In case they are making multiple posts this visit, help them along by storing their name. if (!$post_errors->hasErrors()) { $_SESSION['guest_name'] = $_POST['guestname']; $_SESSION['guest_email'] = $_POST['email']; } } // Check the subject and message. if (!isset($_POST['subject']) || Util::htmltrim(Util::htmlspecialchars($_POST['subject'])) === '') { $post_errors->addError('no_subject'); } if (!isset($_POST['message']) || Util::htmltrim(Util::htmlspecialchars($_POST['message'], ENT_QUOTES)) === '') { $post_errors->addError('no_message'); } elseif (!empty($modSettings['max_messageLength']) && Util::strlen($_POST['message']) > $modSettings['max_messageLength']) { $post_errors->addError(array('long_message', array($modSettings['max_messageLength']))); } else { // Prepare the message a bit for some additional testing. $_POST['message'] = Util::htmlspecialchars($_POST['message'], ENT_QUOTES); // Preparse code. (Zef) if ($user_info['is_guest']) { $user_info['name'] = $_POST['guestname']; } preparsecode($_POST['message']); // Let's see if there's still some content left without the tags. if (Util::htmltrim(strip_tags(parse_bbc($_POST['message'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['message'], '[html]') === false)) { $post_errors->addError('no_message'); } } if (isset($_POST['calendar']) && !isset($_REQUEST['deleteevent']) && Util::htmltrim($_POST['evtitle']) === '') { $post_errors->addError('no_event'); } // Validate the poll... if (isset($_REQUEST['poll']) && !empty($modSettings['pollMode'])) { if (!empty($topic) && !isset($_REQUEST['msg'])) { fatal_lang_error('no_access', false); } // This is a new topic... so it's a new poll. if (empty($topic)) { isAllowedTo('poll_post'); } elseif ($user_info['id'] == $topic_info['id_member_started'] && !allowedTo('poll_add_any')) { isAllowedTo('poll_add_own'); } else { isAllowedTo('poll_add_any'); } if (!isset($_POST['question']) || trim($_POST['question']) == '') { $post_errors->addError('no_question'); } $_POST['options'] = empty($_POST['options']) ? array() : htmltrim__recursive($_POST['options']); // Get rid of empty ones. foreach ($_POST['options'] as $k => $option) { if ($option == '') { unset($_POST['options'][$k], $_POST['options'][$k]); } } // What are you going to vote between with one choice?!? if (count($_POST['options']) < 2) { $post_errors->addError('poll_few'); } elseif (count($_POST['options']) > 256) { $post_errors->addError('poll_many'); } } if ($posterIsGuest) { // If user is a guest, make sure the chosen name isn't taken. require_once SUBSDIR . '/Members.subs.php'; if (isReservedName($_POST['guestname'], 0, true, false) && (!isset($msgInfo['poster_name']) || $_POST['guestname'] != $msgInfo['poster_name'])) { $post_errors->addError('bad_name'); } } elseif (!isset($_REQUEST['msg'])) { $_POST['guestname'] = $user_info['username']; $_POST['email'] = $user_info['email']; } // Posting somewhere else? Are we sure you can? if (!empty($_REQUEST['post_in_board'])) { $new_board = (int) $_REQUEST['post_in_board']; if (!allowedTo('post_new', $new_board)) { $post_in_board = boardInfo($new_board); if (!empty($post_in_board)) { $post_errors->addError(array('post_new_board', array($post_in_board['name']))); } else { $post_errors->addError('post_new'); } } } // Any mistakes? if ($post_errors->hasErrors() || $attach_errors->hasErrors()) { addInlineJavascript(' $(document).ready(function () { $("html,body").scrollTop($(\'.category_header:visible:first\').offset().top); });'); return $this->action_post(); } // Make sure the user isn't spamming the board. if (!isset($_REQUEST['msg'])) { spamProtection('post'); } // At about this point, we're posting and that's that. ignore_user_abort(true); @set_time_limit(300); // Add special html entities to the subject, name, and email. $_POST['subject'] = strtr(Util::htmlspecialchars($_POST['subject']), array("\r" => '', "\n" => '', "\t" => '')); $_POST['guestname'] = htmlspecialchars($_POST['guestname'], ENT_COMPAT, 'UTF-8'); $_POST['email'] = htmlspecialchars($_POST['email'], ENT_COMPAT, 'UTF-8'); // At this point, we want to make sure the subject isn't too long. if (Util::strlen($_POST['subject']) > 100) { $_POST['subject'] = Util::substr($_POST['subject'], 0, 100); } if (!empty($modSettings['mentions_enabled']) && !empty($_REQUEST['uid'])) { $query_params = array(); $query_params['member_ids'] = array_unique(array_map('intval', $_REQUEST['uid'])); require_once SUBSDIR . '/Members.subs.php'; $mentioned_members = membersBy('member_ids', $query_params, true); $replacements = 0; $actually_mentioned = array(); foreach ($mentioned_members as $member) { $_POST['message'] = str_replace('@' . $member['real_name'], '[member=' . $member['id_member'] . ']' . $member['real_name'] . '[/member]', $_POST['message'], $replacements); if ($replacements > 0) { $actually_mentioned[] = $member['id_member']; } } } // Make the poll... if (isset($_REQUEST['poll'])) { // Make sure that the user has not entered a ridiculous number of options.. if (empty($_POST['poll_max_votes']) || $_POST['poll_max_votes'] <= 0) { $_POST['poll_max_votes'] = 1; } elseif ($_POST['poll_max_votes'] > count($_POST['options'])) { $_POST['poll_max_votes'] = count($_POST['options']); } else { $_POST['poll_max_votes'] = (int) $_POST['poll_max_votes']; } $_POST['poll_expire'] = (int) $_POST['poll_expire']; $_POST['poll_expire'] = $_POST['poll_expire'] > 9999 ? 9999 : ($_POST['poll_expire'] < 0 ? 0 : $_POST['poll_expire']); // Just set it to zero if it's not there.. if (!isset($_POST['poll_hide'])) { $_POST['poll_hide'] = 0; } else { $_POST['poll_hide'] = (int) $_POST['poll_hide']; } $_POST['poll_change_vote'] = isset($_POST['poll_change_vote']) ? 1 : 0; $_POST['poll_guest_vote'] = isset($_POST['poll_guest_vote']) ? 1 : 0; // Make sure guests are actually allowed to vote generally. if ($_POST['poll_guest_vote']) { require_once SUBSDIR . '/Members.subs.php'; $allowedVoteGroups = groupsAllowedTo('poll_vote', $board); if (!in_array(-1, $allowedVoteGroups['allowed'])) { $_POST['poll_guest_vote'] = 0; } } // If the user tries to set the poll too far in advance, don't let them. if (!empty($_POST['poll_expire']) && $_POST['poll_expire'] < 1) { fatal_lang_error('poll_range_error', false); } elseif (empty($_POST['poll_expire']) && $_POST['poll_hide'] == 2) { $_POST['poll_hide'] = 1; } // Clean up the question and answers. $_POST['question'] = htmlspecialchars($_POST['question'], ENT_COMPAT, 'UTF-8'); $_POST['question'] = Util::substr($_POST['question'], 0, 255); $_POST['question'] = preg_replace('~&#(\\d{4,5}|[2-9]\\d{2,4}|1[2-9]\\d);~', '&#$1;', $_POST['question']); $_POST['options'] = htmlspecialchars__recursive($_POST['options']); // Finally, make the poll. require_once SUBSDIR . '/Poll.subs.php'; $id_poll = createPoll($_POST['question'], $user_info['id'], $_POST['guestname'], $_POST['poll_max_votes'], $_POST['poll_hide'], $_POST['poll_expire'], $_POST['poll_change_vote'], $_POST['poll_guest_vote'], $_POST['options']); } else { $id_poll = 0; } // ...or attach a new file... if (empty($ignore_temp) && $context['attachments']['can']['post'] && !empty($_SESSION['temp_attachments']) && empty($_POST['from_qr'])) { $attachIDs = array(); foreach ($_SESSION['temp_attachments'] as $attachID => $attachment) { if ($attachID != 'initial_error' && strpos($attachID, 'post_tmp_' . $user_info['id']) === false) { continue; } // If there was an initial error just show that message. if ($attachID == 'initial_error') { unset($_SESSION['temp_attachments']); break; } // No errors, then try to create the attachment if (empty($attachment['errors'])) { // Load the attachmentOptions array with the data needed to create an attachment $attachmentOptions = array('post' => isset($_REQUEST['msg']) ? $_REQUEST['msg'] : 0, 'poster' => $user_info['id'], 'name' => $attachment['name'], 'tmp_name' => $attachment['tmp_name'], 'size' => isset($attachment['size']) ? $attachment['size'] : 0, 'mime_type' => isset($attachment['type']) ? $attachment['type'] : '', 'id_folder' => isset($attachment['id_folder']) ? $attachment['id_folder'] : 0, 'approved' => !$modSettings['postmod_active'] || allowedTo('post_attachment'), 'errors' => array()); if (createAttachment($attachmentOptions)) { $attachIDs[] = $attachmentOptions['id']; if (!empty($attachmentOptions['thumb'])) { $attachIDs[] = $attachmentOptions['thumb']; } } } else { @unlink($attachment['tmp_name']); } } unset($_SESSION['temp_attachments']); } // Creating a new topic? $newTopic = empty($_REQUEST['msg']) && empty($topic); $_POST['icon'] = !empty($attachIDs) && $_POST['icon'] == 'xx' ? 'clip' : $_POST['icon']; // Collect all parameters for the creation or modification of a post. $msgOptions = array('id' => empty($_REQUEST['msg']) ? 0 : (int) $_REQUEST['msg'], 'subject' => $_POST['subject'], 'body' => $_POST['message'], 'icon' => preg_replace('~[\\./\\\\*:"\'<>]~', '', $_POST['icon']), 'smileys_enabled' => !isset($_POST['ns']), 'attachments' => empty($attachIDs) ? array() : $attachIDs, 'approved' => $becomesApproved); $topicOptions = array('id' => empty($topic) ? 0 : $topic, 'board' => $board, 'poll' => isset($_REQUEST['poll']) ? $id_poll : null, 'lock_mode' => isset($_POST['lock']) ? (int) $_POST['lock'] : null, 'sticky_mode' => isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics']) ? (int) $_POST['sticky'] : null, 'mark_as_read' => true, 'is_approved' => !$modSettings['postmod_active'] || empty($topic) || !empty($board_info['cur_topic_approved'])); $posterOptions = array('id' => $user_info['id'], 'name' => $_POST['guestname'], 'email' => $_POST['email'], 'update_post_count' => !$user_info['is_guest'] && !isset($_REQUEST['msg']) && $board_info['posts_count']); // This is an already existing message. Edit it. if (!empty($_REQUEST['msg'])) { // Have admins allowed people to hide their screwups? if (time() - $msgInfo['poster_time'] > $modSettings['edit_wait_time'] || $user_info['id'] != $msgInfo['id_member']) { $msgOptions['modify_time'] = time(); $msgOptions['modify_name'] = $user_info['name']; } // This will save some time... if (empty($approve_has_changed)) { unset($msgOptions['approved']); } modifyPost($msgOptions, $topicOptions, $posterOptions); } else { if (!empty($modSettings['enableFollowup']) && !empty($_REQUEST['followup'])) { $original_post = (int) $_REQUEST['followup']; } // We also have to fake the board: // if it's valid and it's not the current, let's forget about the "current" and load the new one if (!empty($new_board) && $board !== $new_board) { $board = $new_board; loadBoard(); // Some details changed $topicOptions['board'] = $board; $topicOptions['is_approved'] = !$modSettings['postmod_active'] || empty($topic) || !empty($board_info['cur_topic_approved']); $posterOptions['update_post_count'] = !$user_info['is_guest'] && !isset($_REQUEST['msg']) && $board_info['posts_count']; } createPost($msgOptions, $topicOptions, $posterOptions); if (isset($topicOptions['id'])) { $topic = $topicOptions['id']; } if (!empty($modSettings['enableFollowup'])) { require_once SUBSDIR . '/FollowUps.subs.php'; require_once SUBSDIR . '/Messages.subs.php'; // Time to update the original message with a pointer to the new one if (!empty($original_post) && canAccessMessage($original_post)) { linkMessages($original_post, $topic); } } } // If we had a draft for this, its time to remove it since it was just posted if (!empty($modSettings['drafts_enabled']) && !empty($_POST['id_draft'])) { deleteDrafts($_POST['id_draft'], $user_info['id']); } // Editing or posting an event? if (isset($_POST['calendar']) && (!isset($_REQUEST['eventid']) || $_REQUEST['eventid'] == -1)) { require_once SUBSDIR . '/Calendar.subs.php'; // Make sure they can link an event to this post. canLinkEvent(); // Insert the event. $eventOptions = array('id_board' => $board, 'id_topic' => $topic, 'title' => $_POST['evtitle'], 'member' => $user_info['id'], 'start_date' => sprintf('%04d-%02d-%02d', $_POST['year'], $_POST['month'], $_POST['day']), 'span' => isset($_POST['span']) && $_POST['span'] > 0 ? min((int) $modSettings['cal_maxspan'], (int) $_POST['span'] - 1) : 0); insertEvent($eventOptions); } elseif (isset($_POST['calendar'])) { $_REQUEST['eventid'] = (int) $_REQUEST['eventid']; // Validate the post... require_once SUBSDIR . '/Calendar.subs.php'; validateEventPost(); // If you're not allowed to edit any events, you have to be the poster. if (!allowedTo('calendar_edit_any')) { $event_poster = getEventPoster($_REQUEST['eventid']); // Silly hacker, Trix are for kids. ...probably trademarked somewhere, this is FAIR USE! (parody...) isAllowedTo('calendar_edit_' . ($event_poster == $user_info['id'] ? 'own' : 'any')); } // Delete it? if (isset($_REQUEST['deleteevent'])) { removeEvent($_REQUEST['eventid']); } else { $span = !empty($modSettings['cal_allowspan']) && !empty($_REQUEST['span']) ? min((int) $modSettings['cal_maxspan'], (int) $_REQUEST['span'] - 1) : 0; $start_time = mktime(0, 0, 0, (int) $_REQUEST['month'], (int) $_REQUEST['day'], (int) $_REQUEST['year']); $eventOptions = array('start_date' => strftime('%Y-%m-%d', $start_time), 'end_date' => strftime('%Y-%m-%d', $start_time + $span * 86400), 'title' => $_REQUEST['evtitle']); modifyEvent($_REQUEST['eventid'], $eventOptions); } } // Marking boards as read. // (You just posted and they will be unread.) if (!$user_info['is_guest']) { $board_list = !empty($board_info['parent_boards']) ? array_keys($board_info['parent_boards']) : array(); // Returning to the topic? if (!empty($_REQUEST['goback'])) { $board_list[] = $board; } if (!empty($board_list)) { markBoardsRead($board_list, false, false); } } // Turn notification on or off. if (!empty($_POST['notify']) && allowedTo('mark_any_notify')) { setTopicNotification($user_info['id'], $topic, true); } elseif (!$newTopic) { setTopicNotification($user_info['id'], $topic, false); } // Log an act of moderation - modifying. if (!empty($moderationAction)) { logAction('modify', array('topic' => $topic, 'message' => (int) $_REQUEST['msg'], 'member' => $msgInfo['id_member'], 'board' => $board)); } if (isset($_POST['lock']) && $_POST['lock'] != 2) { logAction(empty($_POST['lock']) ? 'unlock' : 'lock', array('topic' => $topicOptions['id'], 'board' => $topicOptions['board'])); } if (isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics'])) { logAction(empty($_POST['sticky']) ? 'unsticky' : 'sticky', array('topic' => $topicOptions['id'], 'board' => $topicOptions['board'])); } // Notify any members who have notification turned on for this topic/board - only do this if it's going to be approved(!) if ($becomesApproved) { require_once SUBSDIR . '/Notification.subs.php'; if ($newTopic) { $notifyData = array('body' => $_POST['message'], 'subject' => $_POST['subject'], 'name' => $user_info['name'], 'poster' => $user_info['id'], 'msg' => $msgOptions['id'], 'board' => $board, 'topic' => $topic, 'signature' => isset($user_settings['signature']) ? $user_settings['signature'] : ''); sendBoardNotifications($notifyData); } elseif (empty($_REQUEST['msg'])) { // Only send it to everyone if the topic is approved, otherwise just to the topic starter if they want it. if ($topic_info['approved']) { sendNotifications($topic, 'reply'); } else { sendNotifications($topic, 'reply', array(), $topic_info['id_member_started']); } } } if (!empty($modSettings['mentions_enabled']) && !empty($actually_mentioned)) { require_once CONTROLLERDIR . '/Mentions.controller.php'; $mentions = new Mentions_Controller(); $mentions->setData(array('id_member' => $actually_mentioned, 'type' => 'men', 'id_msg' => $msgOptions['id'], 'status' => $becomesApproved ? 'new' : 'unapproved')); $mentions->action_add(); } if ($board_info['num_topics'] == 0) { cache_put_data('board-' . $board, null, 120); } if (!empty($_POST['announce_topic'])) { redirectexit('action=announce;sa=selectgroup;topic=' . $topic . (!empty($_POST['move']) && allowedTo('move_any') ? ';move' : '') . (empty($_REQUEST['goback']) ? '' : ';goback')); } if (!empty($_POST['move']) && allowedTo('move_any')) { redirectexit('action=movetopic;topic=' . $topic . '.0' . (empty($_REQUEST['goback']) ? '' : ';goback')); } // Return to post if the mod is on. if (isset($_REQUEST['msg']) && !empty($_REQUEST['goback'])) { redirectexit('topic=' . $topic . '.msg' . $_REQUEST['msg'] . '#msg' . $_REQUEST['msg'], isBrowser('ie')); } elseif (!empty($_REQUEST['goback'])) { redirectexit('topic=' . $topic . '.new#new', isBrowser('ie')); } else { redirectexit('board=' . $board . '.0'); } }
function registerMember(&$regOptions, $return_errors = false) { global $scripturl, $txt, $modSettings, $context, $sourcedir; global $user_info, $options, $settings, $smcFunc; loadLanguage('Login'); // We'll need some external functions. require_once $sourcedir . '/lib/Subs-Auth.php'; require_once $sourcedir . '/lib/Subs-Post.php'; // Put any errors in here. $reg_errors = array(); // Registration from the admin center, let them sweat a little more. if ($regOptions['interface'] == 'admin') { is_not_guest(); isAllowedTo('moderate_forum'); } elseif ($regOptions['interface'] == 'guest') { // You cannot register twice... if (empty($user_info['is_guest'])) { redirectexit(); } // Make sure they didn't just register with this session. if (!empty($_SESSION['just_registered']) && empty($modSettings['disableRegisterCheck'])) { fatal_lang_error('register_only_once', false); } } // What method of authorization are we going to use? if (empty($regOptions['auth_method']) || !in_array($regOptions['auth_method'], array('password', 'openid'))) { if (!empty($regOptions['openid'])) { $regOptions['auth_method'] = 'openid'; } else { $regOptions['auth_method'] = 'password'; } } // No name?! How can you register with no name? if (empty($regOptions['username'])) { $reg_errors[] = array('lang', 'need_username'); } // Spaces and other odd characters are evil... $regOptions['username'] = preg_replace('~[\\t\\n\\r\\x0B\\0' . ($context['server']['complex_preg_chars'] ? '\\x{A0}' : " ") . ']+~u', ' ', $regOptions['username']); // Don't use too long a name. if (commonAPI::strlen($regOptions['username']) > 25) { $reg_errors[] = array('lang', 'error_long_name'); } // Only these characters are permitted. if (preg_match('~[<>&"\'=\\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $regOptions['username'])) != 0 || $regOptions['username'] == '_' || $regOptions['username'] == '|' || strpos($regOptions['username'], '[code') !== false || strpos($regOptions['username'], '[/code') !== false) { $reg_errors[] = array('lang', 'error_invalid_characters_username'); } if (commonAPI::strtolower($regOptions['username']) === commonAPI::strtolower($txt['guest_title'])) { $reg_errors[] = array('lang', 'username_reserved', 'general', array($txt['guest_title'])); } // !!! Separate the sprintf? if (empty($regOptions['email']) || preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', $regOptions['email']) === 0 || strlen($regOptions['email']) > 255) { $reg_errors[] = array('done', sprintf($txt['valid_email_needed'], commonAPI::htmlspecialchars($regOptions['username']))); } if (!empty($regOptions['check_reserved_name']) && isReservedName($regOptions['username'], 0, false)) { if ($regOptions['password'] == 'chocolate cake') { $reg_errors[] = array('done', 'Sorry, I don\'t take bribes... you\'ll need to come up with a different name.'); } $reg_errors[] = array('done', '(' . htmlspecialchars($regOptions['username']) . ') ' . $txt['name_in_use']); } // Generate a validation code if it's supposed to be emailed. $validation_code = ''; if ($regOptions['require'] == 'activation') { $validation_code = generateValidationCode(); } // If you haven't put in a password generate one. if ($regOptions['interface'] == 'admin' && $regOptions['password'] == '' && $regOptions['auth_method'] == 'password') { mt_srand(time() + 1277); $regOptions['password'] = generateValidationCode(); $regOptions['password_check'] = $regOptions['password']; } elseif ($regOptions['password'] != $regOptions['password_check'] && $regOptions['auth_method'] == 'password') { $reg_errors[] = array('lang', 'passwords_dont_match'); } // That's kind of easy to guess... if ($regOptions['password'] == '') { if ($regOptions['auth_method'] == 'password') { $reg_errors[] = array('lang', 'no_password'); } else { $regOptions['password'] = sha1(mt_rand()); } } // Now perform hard password validation as required. if (!empty($regOptions['check_password_strength'])) { $passwordError = validatePassword($regOptions['password'], $regOptions['username'], array($regOptions['email'])); // Password isn't legal? if ($passwordError != null) { $reg_errors[] = array('lang', 'profile_error_password_' . $passwordError); } } // If they are using an OpenID that hasn't been verified yet error out. // !!! Change this so they can register without having to attempt a login first if ($regOptions['auth_method'] == 'openid' && (empty($_SESSION['openid']['verified']) || $_SESSION['openid']['openid_uri'] != $regOptions['openid'])) { $reg_errors[] = array('lang', 'openid_not_verified'); } // You may not be allowed to register this email. if (!empty($regOptions['check_email_ban'])) { isBannedEmail($regOptions['email'], 'cannot_register', $txt['ban_register_prohibited']); } // Check if the email address is in use. $request = smf_db_query(' SELECT id_member FROM {db_prefix}members WHERE email_address = {string:email_address} OR email_address = {string:username} LIMIT 1', array('email_address' => $regOptions['email'], 'username' => $regOptions['username'])); // !!! Separate the sprintf? if (mysql_num_rows($request) != 0) { $reg_errors[] = array('lang', 'email_in_use', false, array(htmlspecialchars($regOptions['email']))); } mysql_free_result($request); // If we found any errors we need to do something about it right away! foreach ($reg_errors as $key => $error) { /* Note for each error: 0 = 'lang' if it's an index, 'done' if it's clear text. 1 = The text/index. 2 = Whether to log. 3 = sprintf data if necessary. */ if ($error[0] == 'lang') { loadLanguage('Errors'); } $message = $error[0] == 'lang' ? empty($error[3]) ? $txt[$error[1]] : vsprintf($txt[$error[1]], $error[3]) : $error[1]; // What to do, what to do, what to do. if ($return_errors) { if (!empty($error[2])) { log_error($message, $error[2]); } $reg_errors[$key] = $message; } else { fatal_error($message, empty($error[2]) ? false : $error[2]); } } // If there's any errors left return them at once! if (!empty($reg_errors)) { return $reg_errors; } $reservedVars = array('actual_theme_url', 'actual_images_url', 'base_theme_dir', 'base_theme_url', 'default_images_url', 'default_theme_dir', 'default_theme_url', 'default_template', 'images_url', 'number_recent_posts', 'smiley_sets_default', 'theme_dir', 'theme_id', 'theme_layers', 'theme_templates', 'theme_url'); // Can't change reserved vars. if (isset($regOptions['theme_vars']) && array_intersect($regOptions['theme_vars'], $reservedVars) != array()) { fatal_lang_error('no_theme'); } // Some of these might be overwritten. (the lower ones that are in the arrays below.) $regOptions['register_vars'] = array('member_name' => $regOptions['username'], 'email_address' => $regOptions['email'], 'passwd' => sha1(strtolower($regOptions['username']) . $regOptions['password']), 'password_salt' => substr(md5(mt_rand()), 0, 4), 'posts' => 0, 'date_registered' => time(), 'member_ip' => $regOptions['interface'] == 'admin' ? '127.0.0.1' : $user_info['ip'], 'member_ip2' => $regOptions['interface'] == 'admin' ? '127.0.0.1' : $_SERVER['BAN_CHECK_IP'], 'validation_code' => $validation_code, 'real_name' => $regOptions['username'], 'personal_text' => $modSettings['default_personal_text'], 'pm_email_notify' => 1, 'id_theme' => 0, 'id_post_group' => 4, 'lngfile' => '', 'buddy_list' => '', 'pm_ignore_list' => '', 'message_labels' => '', 'location' => '', 'time_format' => '', 'signature' => '', 'avatar' => '', 'usertitle' => '', 'secret_question' => '', 'secret_answer' => '', 'additional_groups' => '', 'ignore_boards' => '', 'smiley_set' => '', 'openid_uri' => !empty($regOptions['openid']) ? $regOptions['openid'] : ''); // Setup the activation status on this new account so it is correct - firstly is it an under age account? if ($regOptions['require'] == 'coppa') { $regOptions['register_vars']['is_activated'] = 5; // !!! This should be changed. To what should be it be changed?? $regOptions['register_vars']['validation_code'] = ''; } elseif ($regOptions['require'] == 'nothing') { $regOptions['register_vars']['is_activated'] = 1; } elseif ($regOptions['require'] == 'activation') { $regOptions['register_vars']['is_activated'] = 0; } else { $regOptions['register_vars']['is_activated'] = 3; } if (isset($regOptions['memberGroup'])) { // Make sure the id_group will be valid, if this is an administator. $regOptions['register_vars']['id_group'] = $regOptions['memberGroup'] == 1 && !allowedTo('admin_forum') ? 0 : $regOptions['memberGroup']; // Check if this group is assignable. $unassignableGroups = array(-1, 3); $request = smf_db_query(' SELECT id_group FROM {db_prefix}membergroups WHERE min_posts != {int:min_posts}' . (allowedTo('admin_forum') ? '' : ' OR group_type = {int:is_protected}'), array('min_posts' => -1, 'is_protected' => 1)); while ($row = mysql_fetch_assoc($request)) { $unassignableGroups[] = $row['id_group']; } mysql_free_result($request); if (in_array($regOptions['register_vars']['id_group'], $unassignableGroups)) { $regOptions['register_vars']['id_group'] = 0; } } // Integrate optional member settings to be set. if (!empty($regOptions['extra_register_vars'])) { foreach ($regOptions['extra_register_vars'] as $var => $value) { $regOptions['register_vars'][$var] = $value; } } // Integrate optional user theme options to be set. $theme_vars = array(); if (!empty($regOptions['theme_vars'])) { foreach ($regOptions['theme_vars'] as $var => $value) { $theme_vars[$var] = $value; } } // Call an optional function to validate the users' input. HookAPI::callHook('integrate_register', array(&$regOptions, &$theme_vars)); // Right, now let's prepare for insertion. $knownInts = array('date_registered', 'posts', 'id_group', 'last_login', 'instant_messages', 'unread_messages', 'new_pm', 'pm_prefs', 'gender', 'hide_email', 'show_online', 'pm_email_notify', 'karma_good', 'karma_bad', 'notify_announcements', 'notify_send_body', 'notify_regularity', 'notify_types', 'id_theme', 'is_activated', 'id_msg_last_visit', 'id_post_group', 'total_time_logged_in', 'warning'); $knownFloats = array('time_offset'); $column_names = array(); $values = array(); foreach ($regOptions['register_vars'] as $var => $val) { $type = 'string'; if (in_array($var, $knownInts)) { $type = 'int'; } elseif (in_array($var, $knownFloats)) { $type = 'float'; } elseif ($var == 'birthdate') { $type = 'date'; } $column_names[$var] = $type; $values[$var] = $val; } // Register them into the database. smf_db_insert('', '{db_prefix}members', $column_names, $values, array('id_member')); $memberID = smf_db_insert_id('{db_prefix}members', 'id_member'); // Update the number of members and latest member's info - and pass the name, but remove the 's. if ($regOptions['register_vars']['is_activated'] == 1) { updateStats('member', $memberID, $regOptions['register_vars']['real_name']); } else { updateStats('member'); } // Theme variables too? if (!empty($theme_vars)) { $inserts = array(); foreach ($theme_vars as $var => $val) { $inserts[] = array($memberID, $var, $val); } smf_db_insert('insert', '{db_prefix}themes', array('id_member' => 'int', 'variable' => 'string-255', 'value' => 'string-65534'), $inserts, array('id_member', 'variable')); } // If it's enabled, increase the registrations for today. trackStats(array('registers' => '+')); // Administrative registrations are a bit different... if ($regOptions['interface'] == 'admin') { if ($regOptions['require'] == 'activation') { $email_message = 'admin_register_activate'; } elseif (!empty($regOptions['send_welcome_email'])) { $email_message = 'admin_register_immediate'; } if (isset($email_message)) { $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $memberID . ';code=' . $validation_code, 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $memberID, 'ACTIVATIONCODE' => $validation_code); $emaildata = loadEmailTemplate($email_message, $replacements); sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } // All admins are finished here. return $memberID; } // Can post straight away - welcome them to your fantastic community... if ($regOptions['require'] == 'nothing') { if (!empty($regOptions['send_welcome_email'])) { $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'OPENID' => !empty($regOptions['openid']) ? $regOptions['openid'] : ''); $emaildata = loadEmailTemplate('register_' . ($regOptions['auth_method'] == 'openid' ? 'openid_' : '') . 'immediate', $replacements); sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } // Send admin their notification. adminNotify('standard', $memberID, $regOptions['username']); } elseif ($regOptions['require'] == 'activation' || $regOptions['require'] == 'coppa') { $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'OPENID' => !empty($regOptions['openid']) ? $regOptions['openid'] : ''); if ($regOptions['require'] == 'activation') { $replacements += array('ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $memberID . ';code=' . $validation_code, 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $memberID, 'ACTIVATIONCODE' => $validation_code); } else { $replacements += array('COPPALINK' => $scripturl . '?action=coppa;u=' . $memberID); } $emaildata = loadEmailTemplate('register_' . ($regOptions['auth_method'] == 'openid' ? 'openid_' : '') . ($regOptions['require'] == 'activation' ? 'activate' : 'coppa'), $replacements); sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } else { $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'OPENID' => !empty($regOptions['openid']) ? $regOptions['openid'] : ''); $emaildata = loadEmailTemplate('register_' . ($regOptions['auth_method'] == 'openid' ? 'openid_' : '') . 'pending', $replacements); sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); // Admin gets informed here... adminNotify('approval', $memberID, $regOptions['username']); } // Okay, they're for sure registered... make sure the session is aware of this for security. (Just married :P!) $_SESSION['just_registered'] = 1; return $memberID; }
function saveProfileChanges(&$profile_vars, &$post_errors, $memID) { global $db_prefix, $user_info, $txt, $modSettings, $user_profile; global $newpassemail, $validationCode, $context, $settings, $sourcedir; global $func; // These make life easier.... $old_profile =& $user_profile[$memID]; // Permissions... if ($context['user']['is_owner']) { $changeIdentity = allowedTo(array('profile_identity_any', 'profile_identity_own')); $changeOther = allowedTo(array('profile_extra_any', 'profile_extra_own')); } else { $changeIdentity = allowedTo('profile_identity_any'); $changeOther = allowedTo('profile_extra_any'); } // Arrays of all the changes - makes things easier. $profile_bools = array('notifyAnnouncements', 'notifyOnce', 'notifySendBody'); $profile_ints = array('pm_email_notify', 'notifyTypes', 'ICQ', 'gender', 'ID_THEME'); $profile_floats = array('timeOffset'); $profile_strings = array('websiteUrl', 'websiteTitle', 'AIM', 'YIM', 'location', 'birthdate', 'timeFormat', 'buddy_list', 'pm_ignore_list', 'smileySet', 'signature', 'personalText', 'avatar'); // Fix the spaces in messenger screennames... $fix_spaces = array('MSN', 'AIM', 'YIM'); foreach ($fix_spaces as $var) { // !!! Why? if (isset($_POST[$var])) { $_POST[$var] = strtr($_POST[$var], ' ', '+'); } } // Make sure the MSN one is an email address, not something like 'none' :P. if (isset($_POST['MSN']) && ($_POST['MSN'] == '' || preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', $_POST['MSN']) != 0)) { $profile_strings[] = 'MSN'; } // Validate the title... if (!empty($modSettings['titlesEnable']) && (allowedTo('profile_title_any') || allowedTo('profile_title_own') && $context['user']['is_owner'])) { $profile_strings[] = 'usertitle'; } // Validate the timeOffset... if (isset($_POST['timeOffset'])) { $_POST['timeOffset'] = strtr($_POST['timeOffset'], ',', '.'); if ($_POST['timeOffset'] < -23.5 || $_POST['timeOffset'] > 23.5) { $post_errors[] = 'bad_offset'; } } // Fix the URL... if (isset($_POST['websiteUrl'])) { if (strlen(trim($_POST['websiteUrl'])) > 0 && strpos($_POST['websiteUrl'], '://') === false) { $_POST['websiteUrl'] = 'http://' . $_POST['websiteUrl']; } if (strlen($_POST['websiteUrl']) < 8) { $_POST['websiteUrl'] = ''; } } // !!! Should we check for this year and tell them they made a mistake :P? (based on coppa at least?) if (isset($_POST['birthdate'])) { if (preg_match('/(\\d{4})[\\-\\., ](\\d{2})[\\-\\., ](\\d{2})/', $_POST['birthdate'], $dates) === 1) { $_POST['birthdate'] = 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'; } else { unset($_POST['birthdate']); } } elseif (isset($_POST['bday1'], $_POST['bday2'], $_POST['bday3']) && $_POST['bday1'] > 0 && $_POST['bday2'] > 0) { $_POST['birthdate'] = checkdate($_POST['bday1'], $_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'; } elseif (isset($_POST['bday1']) || isset($_POST['bday2']) || isset($_POST['bday3'])) { $_POST['birthdate'] = '0001-01-01'; } if (isset($_POST['im_email_notify'])) { $_POST['pm_email_notify'] = $_POST['im_email_notify']; } // Validate and set the ignorelist... if (isset($_POST['pm_ignore_list']) || isset($_POST['im_ignore_list'])) { if (!isset($_POST['pm_ignore_list'])) { $_POST['pm_ignore_list'] = $_POST['im_ignore_list']; } $_POST['pm_ignore_list'] = strtr($func['htmltrim']($_POST['pm_ignore_list']), array('\\\'' => ''', "\n" => "', '", "\r" => '', '"' => '')); if (preg_match('~(\\A|,)\\*(\\Z|,)~s', $_POST['pm_ignore_list']) == 0) { $result = db_query("\n\t\t\t\tSELECT ID_MEMBER\n\t\t\t\tFROM {$db_prefix}members\n\t\t\t\tWHERE memberName IN ('{$_POST['pm_ignore_list']}') OR realName IN ('{$_POST['pm_ignore_list']}')\n\t\t\t\tLIMIT " . (substr_count($_POST['pm_ignore_list'], '\', \'') + 1), __FILE__, __LINE__); $_POST['pm_ignore_list'] = ''; while ($row = mysql_fetch_assoc($result)) { $_POST['pm_ignore_list'] .= $row['ID_MEMBER'] . ','; } mysql_free_result($result); // !!! Did we find all the members? $_POST['pm_ignore_list'] = substr($_POST['pm_ignore_list'], 0, -1); } else { $_POST['pm_ignore_list'] = '*'; } } // Similarly, do the same for the buddy list if (isset($_POST['buddy_list'])) { $_POST['buddy_list'] = strtr(trim($_POST['buddy_list']), array('\\\'' => ''', "\n" => "', '", "\r" => '', '"' => '')); if (trim($_POST['buddy_list']) != '') { $result = db_query("\n\t\t\t\tSELECT ID_MEMBER\n\t\t\t\tFROM {$db_prefix}members\n\t\t\t\tWHERE memberName IN ('{$_POST['buddy_list']}') OR realName IN ('{$_POST['buddy_list']}')\n\t\t\t\tLIMIT " . (substr_count($_POST['buddy_list'], '\', \'') + 1), __FILE__, __LINE__); $_POST['buddy_list'] = ''; while ($row = mysql_fetch_assoc($result)) { $_POST['buddy_list'] .= $row['ID_MEMBER'] . ','; } mysql_free_result($result); // !!! Did we find all the members? $_POST['buddy_list'] = substr($_POST['buddy_list'], 0, -1); } } // Validate the smiley set. if (isset($_POST['smileySet'])) { $smiley_sets = explode(',', $modSettings['smiley_sets_known']); if (!in_array($_POST['smileySet'], $smiley_sets) && $_POST['smileySet'] != 'none') { $_POST['smileySet'] = ''; } } // Make sure the signature isn't too long. if (isset($_POST['signature'])) { require_once $sourcedir . '/Subs-Post.php'; if (!empty($modSettings['max_signatureLength']) && $func['strlen']($_POST['signature']) > $modSettings['max_signatureLength']) { $_POST['signature'] = addslashes($func['substr'](stripslashes($_POST['signature']), 0, $modSettings['max_signatureLength'])); } if (strlen($_POST['signature']) > 65534) { $_POST['signature'] = addslashes($func['truncate'](stripslashes($_POST['signature']), 65534)); } $_POST['signature'] = strtr($_POST['signature'], array('"' => '\\"', ''' => '\\'', ''' => '\\'')); preparsecode($_POST['signature']); } // Identity-only changes... if ($changeIdentity) { // This block is only concerned with display name validation. if (isset($_POST['realName']) && (!empty($modSettings['allow_editDisplayName']) || allowedTo('moderate_forum')) && trim($_POST['realName']) != $old_profile['realName']) { $_POST['realName'] = trim(preg_replace('~[\\s]~' . ($context['utf8'] ? 'u' : ''), ' ', $_POST['realName'])); if (trim($_POST['realName']) == '') { $post_errors[] = 'no_name'; } elseif ($func['strlen']($_POST['realName']) > 60) { $post_errors[] = 'name_too_long'; } else { require_once $sourcedir . '/Subs-Members.php'; if (isReservedName($_POST['realName'], $memID)) { $post_errors[] = 'name_taken'; } } if (isset($_POST['realName'])) { $profile_vars['realName'] = '\'' . $_POST['realName'] . '\''; } } // Change the registration date. if (!empty($_POST['dateRegistered']) && allowedTo('admin_forum')) { // Bad date! Go try again - please? if (($_POST['dateRegistered'] = strtotime($_POST['dateRegistered'])) === -1) { fatal_error($txt['smf233'] . ' ' . strftime('%d %b %Y ' . (strpos($user_info['time_format'], '%H') !== false ? '%I:%M:%S %p' : '%H:%M:%S'), forum_time(false)), false); } elseif ($_POST['dateRegistered'] != $txt[470] && $_POST['dateRegistered'] != strtotime(strftime('%Y-%m-%d', $user_profile[$memID]['dateRegistered'] + ($user_info['time_offset'] + $modSettings['time_offset']) * 3600))) { $profile_vars['dateRegistered'] = $_POST['dateRegistered'] - ($user_info['time_offset'] + $modSettings['time_offset']) * 3600; } } // Change the number of posts. if (isset($_POST['posts']) && allowedTo('moderate_forum')) { $profile_vars['posts'] = $_POST['posts'] != '' ? (int) strtr($_POST['posts'], array(',' => '', '.' => '', ' ' => '')) : '\'\''; } // This block is only concerned with email address validation.. if (isset($_POST['emailAddress']) && strtolower($_POST['emailAddress']) != strtolower($old_profile['emailAddress'])) { $_POST['emailAddress'] = strtr($_POST['emailAddress'], array(''' => '\\\'')); // Prepare the new password, or check if they want to change their own. if (!empty($modSettings['send_validation_onChange']) && !allowedTo('moderate_forum')) { require_once $sourcedir . '/Subs-Members.php'; $validationCode = generateValidationCode(); $profile_vars['validation_code'] = '\'' . $validationCode . '\''; $profile_vars['is_activated'] = '2'; $newpassemail = true; } // Check the name and email for validity. if (trim($_POST['emailAddress']) == '') { $post_errors[] = 'no_email'; } if (preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', stripslashes($_POST['emailAddress'])) == 0) { $post_errors[] = 'bad_email'; } // Email addresses should be and stay unique. $request = db_query("\n\t\t\t\tSELECT ID_MEMBER\n\t\t\t\tFROM {$db_prefix}members\n\t\t\t\tWHERE ID_MEMBER != {$memID}\n\t\t\t\t\tAND emailAddress = '{$_POST['emailAddress']}'\n\t\t\t\tLIMIT 1", __FILE__, __LINE__); if (mysql_num_rows($request) > 0) { $post_errors[] = 'email_taken'; } mysql_free_result($request); $profile_vars['emailAddress'] = '\'' . $_POST['emailAddress'] . '\''; } // Hide email address? if (isset($_POST['hideEmail']) && (!empty($modSettings['allow_hideEmail']) || allowedTo('moderate_forum'))) { $profile_vars['hideEmail'] = empty($_POST['hideEmail']) ? '0' : '1'; } // Are they allowed to change their hide status? if (isset($_POST['showOnline']) && (!empty($modSettings['allow_hideOnline']) || allowedTo('moderate_forum'))) { $profile_vars['showOnline'] = empty($_POST['showOnline']) ? '0' : '1'; } // If they're trying to change the password, let's check they pick a sensible one. if (isset($_POST['passwrd1']) && $_POST['passwrd1'] != '') { // Do the two entries for the password even match? if ($_POST['passwrd1'] != $_POST['passwrd2']) { $post_errors[] = 'bad_new_password'; } // Let's get the validation function into play... require_once $sourcedir . '/Subs-Auth.php'; $passwordErrors = validatePassword($_POST['passwrd1'], $user_info['username'], array($user_info['name'], $user_info['email'])); // Were there errors? if ($passwordErrors != null) { $post_errors[] = 'password_' . $passwordErrors; } // Set up the new password variable... ready for storage. $profile_vars['passwd'] = '\'' . sha1(strtolower($old_profile['memberName']) . un_htmlspecialchars(stripslashes($_POST['passwrd1']))) . '\''; } if (isset($_POST['secretQuestion'])) { $profile_vars['secretQuestion'] = '\'' . $_POST['secretQuestion'] . '\''; } // Do you have a *secret* password? if (isset($_POST['secretAnswer']) && $_POST['secretAnswer'] != '') { $profile_vars['secretAnswer'] = '\'' . md5($_POST['secretAnswer']) . '\''; } } // Things they can do if they are a forum moderator. if (allowedTo('moderate_forum')) { if (($_REQUEST['sa'] == 'activateAccount' || !empty($_POST['is_activated'])) && isset($old_profile['is_activated']) && $old_profile['is_activated'] != 1) { // If we are approving the deletion of an account, we do something special ;) if ($old_profile['is_activated'] == 4) { require_once $sourcedir . '/Subs-Members.php'; deleteMembers($memID); redirectexit(); } if (isset($modSettings['integrate_activate']) && function_exists($modSettings['integrate_activate'])) { call_user_func($modSettings['integrate_activate'], $old_profile['memberName']); } // Actually update this member now, as it guarantees the unapproved count can't get corrupted. updateMemberData($memID, array('is_activated' => $old_profile['is_activated'] >= 10 ? '11' : '1', 'validation_code' => '\'\'')); // If we are doing approval, update the stats for the member just incase. if (in_array($old_profile['is_activated'], array(3, 4, 13, 14))) { updateSettings(array('unapprovedMembers' => $modSettings['unapprovedMembers'] > 1 ? $modSettings['unapprovedMembers'] - 1 : 0)); } // Make sure we update the stats too. updateStats('member', false); } if (isset($_POST['karmaGood'])) { $profile_vars['karmaGood'] = $_POST['karmaGood'] != '' ? (int) $_POST['karmaGood'] : '\'\''; } if (isset($_POST['karmaBad'])) { $profile_vars['karmaBad'] = $_POST['karmaBad'] != '' ? (int) $_POST['karmaBad'] : '\'\''; } } // Assigning membergroups (you need admin_forum permissions to change an admins' membergroups). if (allowedTo('manage_membergroups')) { // The account page allows the change of your ID_GROUP - but not to admin!. if (isset($_POST['ID_GROUP']) && (allowedTo('admin_forum') || (int) $_POST['ID_GROUP'] != 1 && $old_profile['ID_GROUP'] != 1)) { $profile_vars['ID_GROUP'] = (int) $_POST['ID_GROUP']; } // Find the additional membergroups (if any) if (isset($_POST['additionalGroups']) && is_array($_POST['additionalGroups'])) { foreach ($_POST['additionalGroups'] as $i => $group_id) { if ((int) $group_id == 0 || !allowedTo('admin_forum') && (int) $group_id == 1) { unset($_POST['additionalGroups'][$i], $_POST['additionalGroups'][$i]); } else { $_POST['additionalGroups'][$i] = (int) $group_id; } } // Put admin back in there if you don't have permission to take it away. if (!allowedTo('admin_forum') && in_array(1, explode(',', $old_profile['additionalGroups']))) { $_POST['additionalGroups'][] = 1; } $profile_vars['additionalGroups'] = '\'' . implode(',', $_POST['additionalGroups']) . '\''; } // Too often, people remove delete their own account, or something. if (in_array(1, explode(',', $old_profile['additionalGroups'])) || $old_profile['ID_GROUP'] == 1) { $stillAdmin = !isset($profile_vars['ID_GROUP']) || $profile_vars['ID_GROUP'] == 1 || isset($_POST['additionalGroups']) && in_array(1, $_POST['additionalGroups']); // If they would no longer be an admin, look for any other... if (!$stillAdmin) { $request = db_query("\n\t\t\t\t\tSELECT ID_MEMBER\n\t\t\t\t\tFROM {$db_prefix}members\n\t\t\t\t\tWHERE (ID_GROUP = 1 OR FIND_IN_SET(1, additionalGroups))\n\t\t\t\t\t\tAND ID_MEMBER != {$memID}\n\t\t\t\t\tLIMIT 1", __FILE__, __LINE__); list($another) = mysql_fetch_row($request); mysql_free_result($request); if (empty($another)) { fatal_lang_error('at_least_one_admin'); } } } } // Validate the language file... if (($changeIdentity || $changeOther) && isset($_POST['lngfile']) && !empty($modSettings['userLanguage'])) { $language_directories = array($settings['default_theme_dir'] . '/languages', $settings['actual_theme_dir'] . '/languages'); if (!empty($settings['base_theme_dir'])) { $language_directories[] = $settings['base_theme_dir'] . '/languages'; } $language_directories = array_unique($language_directories); foreach ($language_directories as $language_dir) { if (!file_exists($language_dir)) { continue; } $dir = dir($language_dir); while ($entry = $dir->read()) { if (preg_match('~^index\\.(.+)\\.php$~', $entry, $matches) && $matches[1] == $_POST['lngfile']) { $profile_vars['lngfile'] = "'{$_POST['lngfile']}'"; // If they are the owner, make this persist even after they log out. if ($context['user']['is_owner']) { $_SESSION['language'] = $_POST['lngfile']; } } } $dir->close(); } } // Here's where we sort out all the 'other' values... if ($changeOther) { makeThemeChanges($memID, isset($_POST['ID_THEME']) ? (int) $_POST['ID_THEME'] : $old_profile['ID_THEME']); makeAvatarChanges($memID, $post_errors); makeNotificationChanges($memID); foreach ($profile_bools as $var) { if (isset($_POST[$var])) { $profile_vars[$var] = empty($_POST[$var]) ? '0' : '1'; } } foreach ($profile_ints as $var) { if (isset($_POST[$var])) { $profile_vars[$var] = $_POST[$var] != '' ? (int) $_POST[$var] : '\'\''; } } foreach ($profile_floats as $var) { if (isset($_POST[$var])) { $profile_vars[$var] = (double) $_POST[$var]; } } foreach ($profile_strings as $var) { if (isset($_POST[$var])) { $profile_vars[$var] = '\'' . $_POST[$var] . '\''; } } } if (isset($profile_vars['ICQ']) && $profile_vars['ICQ'] == '0') { $profile_vars['ICQ'] = '\'\''; } }
/** * Checks a username obeys a load of rules * * @param int $memID, * @param string $username * @return string Returns null if fine */ function validateUsername($memID, $username, $return_error = false, $check_reserved_name = true) { global $sourcedir, $txt, $smcFunc, $user_info; $errors = array(); // Don't use too long a name. if ($smcFunc['strlen']($username) > 25) { $errors[] = array('lang', 'error_long_name'); } // No name?! How can you register with no name? if ($username == '') { $errors[] = array('lang', 'need_username'); } // Only these characters are permitted. if (in_array($username, array('_', '|')) || preg_match('~[<>&"\'=\\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $username)) != 0 || strpos($username, '[code') !== false || strpos($username, '[/code') !== false) { $errors[] = array('lang', 'error_invalid_characters_username'); } if (stristr($username, $txt['guest_title']) !== false) { $errors[] = array('lang', 'username_reserved', 'general', array($txt['guest_title'])); } if ($check_reserved_name) { require_once $sourcedir . '/Subs-Members.php'; if (isReservedName($username, $memID, false)) { $errors[] = array('done', '(' . htmlspecialchars($username) . ') ' . $txt['name_in_use']); } } if ($return_error) { return $errors; } elseif (empty($errors)) { return null; } loadLanguage('Errors'); $error = $errors[0]; $message = $error[0] == 'lang' ? empty($error[3]) ? $txt[$error[1]] : vsprintf($txt[$error[1]], $error[3]) : $error[1]; fatal_error($message, empty($error[2]) || $user_info['is_admin'] ? false : $error[2]); }
function method_sign_in() { global $db_prefix, $context, $user_profile, $modSettings, $register, $sourcedir, $user_info, $boardurl, $txt; require_once $sourcedir . '/Register.php'; require_once $sourcedir . '/Subs-Members.php'; require_once $sourcedir . '/Subs-Auth.php'; $token = $context['mob_request']['params'][0][0]; $code = $context['mob_request']['params'][1][0]; $email = isset($context['mob_request']['params'][2][0]) ? base64_decode($context['mob_request']['params'][2][0]) : ''; $username = isset($context['mob_request']['params'][3][0]) ? base64_decode($context['mob_request']['params'][3][0]) : ''; $password = isset($context['mob_request']['params'][4][0]) ? base64_decode($context['mob_request']['params'][4][0]) : ''; // verify tapatalk token and code first $ttid = TapatalkSsoVerification($token, $code); if (empty($ttid)) { get_error('Tapatalk authorization verify failed, please login with your username and password.'); } $tapatalk_id_email = $ttid->email; $result_status = true; $register = false; $result_text = ''; if (!$ttid->result || empty($tapatalk_id_email)) { get_error($ttid->result_text ? $ttid->result_text : 'Tapatalk authorization verify failed, please login with your username and password'); } // sign in with email or register an account $login_id = emailExists($tapatalk_id_email); if (empty($login_id)) { if (empty($username)) { get_error('Invalid Parameters', 2); } else { if (isReservedName($username, 0, true, false)) { get_error($txt[473], 1); } else { if (empty($password)) { $password = tt_generatePassword(); } $_POST['user'] = $username; $_POST['email'] = $tapatalk_id_email; $_POST['passwrd1'] = $password; $_POST['passwrd2'] = $password; $_POST['regagree'] = 'on'; $_POST['regSubmit'] = 'Register'; $_POST['skip_coppa'] = 1; $_SESSION['old_url'] = $boardurl; $modSettings['disable_visual_verification'] = 1; $modSettings['recaptcha_enabled'] = 0; $modSettings['recaptcha_enable'] = 0; $modSettings['captchaenable'] = 0; // compatibility with old CAPTCHA Mod $modSettings['anti_spam_ver_enable'] = false; if ($modSettings['registration_method'] == 1) { $modSettings['registration_method'] = 0; } $login_id = Register2(); $register = true; $result_status = $modSettings['registration_method'] == 2 ? false : true; $result_text = $modSettings['registration_method'] == 2 ? $txt['approval_after_registration'] : ''; if (empty($login_id)) { get_error('Register failed'); } } } } // do login if ($login_id) { $request = db_query("\n SELECT passwd, ID_MEMBER AS id_member, is_activated, ID_GROUP AS id_group, emailAddress AS email_address, additionalGroups AS additional_groups, memberName AS member_name,\n passwordSalt AS password_salt, ID_POST_GROUP\n FROM {$db_prefix}members\n WHERE ID_MEMBER = '{$login_id}'\n ", __FILE__, __LINE__); $user = mysql_fetch_assoc($request); if ($user['is_activated'] == 3 && !$register) { fatal_lang_error('still_awaiting_approval'); } // Set the login cookie setLoginCookie(60 * $modSettings['cookieTime'], $login_id, sha1($user['passwd'] . $user['password_salt'])); loadMemberData($user['id_member'], false, 'profile'); $user_info = $user_profile[$user['id_member']]; $user_info['is_guest'] = false; $user_info['is_admin'] = $user['id_group'] == 1 || in_array(1, explode(',', $user['additional_groups'])); $user_info['id'] = $user['id_member']; if (empty($user_info['additionalGroups'])) { $user_info['groups'] = array($user_info['ID_GROUP'], $user_info['ID_POST_GROUP']); } else { $user_info['groups'] = array_merge(array($user_info['ID_GROUP'], $user_info['ID_POST_GROUP']), explode(',', $user_info['additionalGroups'])); } $user_info['groups'] = array_unique(array_map('intval', $user_info['groups'])); // Banned? is_not_banned(true); // Don't stick the language or theme after this point. unset($_SESSION['language']); unset($_SESSION['ID_THEME']); // You've logged in, haven't you? updateMemberData($user_info['id'], array('lastLogin' => time(), 'memberIP' => '\'' . $user_info['ip'] . '\'', 'memberIP2' => '\'' . $_SERVER['BAN_CHECK_IP'] . '\'')); // Get rid of the online entry for that old guest.... db_query("\n DELETE FROM {$db_prefix}log_online\n WHERE session = 'ip{$user_info['ip']}'\n LIMIT 1", __FILE__, __LINE__); $_SESSION['log_time'] = 0; loadPermissions(); update_push(); // We got this far? return a positive response.... outputRPCLogin($result_status, $result_text); } else { get_error('Sign In Failed'); } }