function testSimpleError() { $error_context = Error_Context::context(); // Let's add an error and see $error_context->addError('test'); $this->assertTrue($error_context->hasErrors()); $this->assertTrue($error_context->hasError('test')); $this->assertFalse($error_context->hasError('test2')); $this->assertEqual($error_context->getErrorType(), Error_Context::MINOR); // Now the error can be removed $error_context->removeError('test'); $this->assertFalse($error_context->hasErrors()); $this->assertFalse($error_context->hasError('test')); $this->assertFalse($error_context->hasError('test2')); $this->assertFalse($error_context->getErrors()); }
/** * Create a anti-bot verification control? * * @param mixed[] $verificationOptions * @param bool $do_test = false */ function create_control_verification(&$verificationOptions, $do_test = false) { global $context; // We need to remember this because when failing the page is realoaded and the // code must remain the same (unless it has to change) static $all_instances = array(); // Always have an ID. assert(isset($verificationOptions['id'])); $isNew = !isset($context['controls']['verification'][$verificationOptions['id']]); if ($isNew) { $context['controls']['verification'][$verificationOptions['id']] = array('id' => $verificationOptions['id'], 'max_errors' => isset($verificationOptions['max_errors']) ? $verificationOptions['max_errors'] : 3, 'render' => false); } $thisVerification =& $context['controls']['verification'][$verificationOptions['id']]; if (!isset($_SESSION[$verificationOptions['id'] . '_vv'])) { $_SESSION[$verificationOptions['id'] . '_vv'] = array(); } $force_refresh = (!empty($_SESSION[$verificationOptions['id'] . '_vv']['did_pass']) || empty($_SESSION[$verificationOptions['id'] . '_vv']['count']) || $_SESSION[$verificationOptions['id'] . '_vv']['count'] > 3) && empty($verificationOptions['dont_refresh']); if (!isset($all_instances[$verificationOptions['id']])) { $known_verifications = loadVerificationControls(); $all_instances[$verificationOptions['id']] = array(); foreach ($known_verifications as $verification) { $class_name = 'Verification_Controls_' . ucfirst($verification); $current_instance = new $class_name($verificationOptions); // If there is anything to show, otherwise forget it if ($current_instance->showVerification($isNew, $force_refresh)) { $all_instances[$verificationOptions['id']][$verification] = $current_instance; } } } $instances =& $all_instances[$verificationOptions['id']]; // Is there actually going to be anything? if (empty($instances)) { return false; } elseif (!$isNew && !$do_test) { return true; } $verification_errors = Error_Context::context($verificationOptions['id']); $increase_error_count = false; // Start with any testing. if ($do_test) { // This cannot happen! if (!isset($_SESSION[$verificationOptions['id'] . '_vv']['count'])) { fatal_lang_error('no_access', false); } foreach ($instances as $instance) { $outcome = $instance->doTest(); if ($outcome !== true) { $increase_error_count = true; $verification_errors->addError($outcome); } } } // Any errors means we refresh potentially. if ($increase_error_count) { if (empty($_SESSION[$verificationOptions['id'] . '_vv']['errors'])) { $_SESSION[$verificationOptions['id'] . '_vv']['errors'] = 0; } elseif ($_SESSION[$verificationOptions['id'] . '_vv']['errors'] > $thisVerification['max_errors']) { $force_refresh = true; } // Keep a track of these. $_SESSION[$verificationOptions['id'] . '_vv']['errors']++; } // Are we refreshing then? if ($force_refresh) { // Assume nothing went before. $_SESSION[$verificationOptions['id'] . '_vv']['count'] = 0; $_SESSION[$verificationOptions['id'] . '_vv']['errors'] = 0; $_SESSION[$verificationOptions['id'] . '_vv']['did_pass'] = false; } foreach ($instances as $test => $instance) { $instance->createTest($force_refresh); $thisVerification['test'][$test] = $instance->prepareContext(); if ($instance->hasVisibleTemplate()) { $thisVerification['render'] = true; } } $_SESSION[$verificationOptions['id'] . '_vv']['count'] = empty($_SESSION[$verificationOptions['id'] . '_vv']['count']) ? 1 : $_SESSION[$verificationOptions['id'] . '_vv']['count'] + 1; // Return errors if we have them. if ($verification_errors->hasErrors()) { // @todo temporary until the error class is implemented in register $error_codes = array(); foreach ($verification_errors->getErrors() as $errors) { foreach ($errors as $error) { $error_codes[] = $error; } } return $error_codes; } elseif ($do_test) { $_SESSION[$verificationOptions['id'] . '_vv']['did_pass'] = true; } // Say that everything went well chaps. return true; }
/** * See if a username already exists. */ private function _registerCheckUsername() { global $context; // This is XML! loadTemplate('Xml'); $context['sub_template'] = 'check_username'; $context['checked_username'] = isset($_GET['username']) ? un_htmlspecialchars($_GET['username']) : ''; $context['valid_username'] = true; // Clean it up like mother would. $context['checked_username'] = preg_replace('~[\\t\\n\\r \\x0B\\0\\x{A0}\\x{AD}\\x{2000}-\\x{200F}\\x{201F}\\x{202F}\\x{3000}\\x{FEFF}]+~u', ' ', $context['checked_username']); $errors = Error_Context::context('valid_username', 0); require_once SUBSDIR . '/Auth.subs.php'; validateUsername(0, $context['checked_username'], 'valid_username', true, false); $context['valid_username'] = !$errors->hasErrors(); }
/** * Creates a new ban group * * What it does: * - If a ban group with the same name already exists or the group s successfully created the ID is returned * - On error the error code is returned or false * * @package Bans * @param mixed[] $ban_info * @return int the ban group's ID */ function insertBanGroup($ban_info = array()) { $db = database(); $ban_errors = Error_Context::context('ban', 1); if (empty($ban_info['name'])) { $ban_errors->addError('ban_name_empty'); } if (empty($ban_info['cannot']['access']) && empty($ban_info['cannot']['register']) && empty($ban_info['cannot']['post']) && empty($ban_info['cannot']['login'])) { $ban_errors->addError('ban_unknown_restriction_type'); } if ($ban_errors->hasErrors()) { return false; } // Check whether a ban with this name already exists. $request = $db->query('', ' SELECT id_ban_group FROM {db_prefix}ban_groups WHERE name = {string:new_ban_name}' . ' LIMIT 1', array('new_ban_name' => $ban_info['name'])); // @todo shouldn't be an error here? if ($db->num_rows($request) == 1) { list($id_ban) = $db->fetch_row($request); $db->free_result($request); return $id_ban; } $db->free_result($request); // Yes yes, we're ready to add now. $db->insert('', '{db_prefix}ban_groups', array('name' => 'string-20', 'ban_time' => 'int', 'expire_time' => 'raw', 'cannot_access' => 'int', 'cannot_register' => 'int', 'cannot_post' => 'int', 'cannot_login' => 'int', 'reason' => 'string-255', 'notes' => 'string-65534'), array($ban_info['name'], time(), $ban_info['db_expiration'], $ban_info['cannot']['access'], $ban_info['cannot']['register'], $ban_info['cannot']['post'], $ban_info['cannot']['login'], $ban_info['reason'], $ban_info['notes']), array('id_ban_group')); $ban_info['id'] = $db->insert_id('{db_prefix}ban_groups', 'id_ban_group'); if (empty($ban_info['id'])) { $ban_errors->addError('impossible_insert_new_bangroup'); } return $ban_info['id']; }
/** * Send the emails. * * - Sends off emails to all the moderators. * - Sends to administrators and global moderators. (1 and 2) * - Called by action_reporttm(), and thus has the same permission and setting requirements as it does. * - Accessed through ?action=reporttm when posting. */ public function action_reporttm2() { global $txt, $scripturl, $topic, $board, $user_info, $modSettings, $language, $context; // You must have the proper permissions! isAllowedTo('report_any'); // Make sure they aren't spamming. spamProtection('reporttm'); require_once SUBSDIR . '/Mail.subs.php'; // No errors, yet. $report_errors = Error_Context::context('report', 1); // Check their session. if (checkSession('post', '', false) != '') { $report_errors->addError('session_timeout'); } // Make sure we have a comment and it's clean. if (!isset($_POST['comment']) || Util::htmltrim($_POST['comment']) === '') { $report_errors->addError('no_comment'); } $poster_comment = strtr(Util::htmlspecialchars($_POST['comment']), array("\r" => '', "\t" => '')); if (Util::strlen($poster_comment) > 254) { $report_errors->addError('post_too_long'); } // Guests need to provide their address! if ($user_info['is_guest']) { require_once SUBSDIR . '/DataValidator.class.php'; if (!Data_Validator::is_valid($_POST, array('email' => 'valid_email'), array('email' => 'trim'))) { empty($_POST['email']) ? $report_errors->addError('no_email') : $report_errors->addError('bad_email'); } isBannedEmail($_POST['email'], 'cannot_post', sprintf($txt['you_are_post_banned'], $txt['guest_title'])); $user_info['email'] = htmlspecialchars($_POST['email'], ENT_COMPAT, 'UTF-8'); } // Could they get the right verification code? if ($user_info['is_guest'] && !empty($modSettings['guests_report_require_captcha'])) { require_once SUBSDIR . '/VerificationControls.class.php'; $verificationOptions = array('id' => 'report'); $context['require_verification'] = create_control_verification($verificationOptions, true); if (is_array($context['require_verification'])) { foreach ($context['require_verification'] as $error) { $report_errors->addError($error, 0); } } } // Any errors? if ($report_errors->hasErrors()) { return $this->action_reporttm(); } // Get the basic topic information, and make sure they can see it. $msg_id = (int) $_POST['msg']; $message = posterDetails($msg_id, $topic); if (empty($message)) { fatal_lang_error('no_board', false); } $poster_name = un_htmlspecialchars($message['real_name']) . ($message['real_name'] != $message['poster_name'] ? ' (' . $message['poster_name'] . ')' : ''); $reporterName = un_htmlspecialchars($user_info['name']) . ($user_info['name'] != $user_info['username'] && $user_info['username'] != '' ? ' (' . $user_info['username'] . ')' : ''); $subject = un_htmlspecialchars($message['subject']); // Get a list of members with the moderate_board permission. require_once SUBSDIR . '/Members.subs.php'; $moderators = membersAllowedTo('moderate_board', $board); $result = getBasicMemberData($moderators, array('preferences' => true, 'sort' => 'lngfile')); $mod_to_notify = array(); foreach ($result as $row) { if ($row['notify_types'] != 4) { $mod_to_notify[] = $row; } } // Check that moderators do exist! if (empty($mod_to_notify)) { fatal_lang_error('no_mods', false); } // If we get here, I believe we should make a record of this, for historical significance, yabber. if (empty($modSettings['disable_log_report'])) { require_once SUBSDIR . '/Messages.subs.php'; $id_report = recordReport($message, $poster_comment); // If we're just going to ignore these, then who gives a monkeys... if ($id_report === false) { redirectexit('topic=' . $topic . '.msg' . $msg_id . '#msg' . $msg_id); } } // Find out who the real moderators are - for mod preferences. require_once SUBSDIR . '/Boards.subs.php'; $real_mods = getBoardModerators($board, true); // Send every moderator an email. foreach ($mod_to_notify as $row) { // Maybe they don't want to know?! if (!empty($row['mod_prefs'])) { list(, , $pref_binary) = explode('|', $row['mod_prefs']); if (!($pref_binary & 1) && (!($pref_binary & 2) || !in_array($row['id_member'], $real_mods))) { continue; } } $replacements = array('TOPICSUBJECT' => $subject, 'POSTERNAME' => $poster_name, 'REPORTERNAME' => $reporterName, 'TOPICLINK' => $scripturl . '?topic=' . $topic . '.msg' . $msg_id . '#msg' . $msg_id, 'REPORTLINK' => !empty($id_report) ? $scripturl . '?action=moderate;area=reports;report=' . $id_report : '', 'COMMENT' => $_POST['comment']); $emaildata = loadEmailTemplate('report_to_moderator', $replacements, empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']); // Send it to the moderator. sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], $user_info['email'], null, false, 2); } // Keep track of when the mod reports get updated, that way we know when we need to look again. updateSettings(array('last_mod_report_action' => time())); // Back to the post we reported! redirectexit('reportsent;topic=' . $topic . '.msg' . $msg_id . '#msg' . $msg_id); }
/** * Update the settings for a poll, or add a new one. * Must be called with a topic specified in the URL. * The user must have poll_edit_any/poll_add_any permission * for the relevant action. Otherwise they must be poll starter * with poll_edit_own permission for editing, or be topic starter * with poll_add_any permission for adding. * In the case of an error, this function will redirect back to * action_editpoll and display the relevant error message. * Upon successful completion of action will direct user back to topic. * Accessed via ?action=editpoll2. */ public function action_editpoll2() { global $topic, $board, $user_info; // Sneaking off, are we? if (empty($_POST)) { redirectexit('action=editpoll;topic=' . $topic . '.0'); } $poll_errors = Error_Context::context('poll'); if (checkSession('post', '', false) != '') { $poll_errors->addError('session_timeout'); } if (isset($_POST['preview'])) { return $this->action_editpoll(); } // HACKERS (!!) can't edit :P. if (empty($topic)) { fatal_lang_error('no_access', false); } // Is this a new poll, or editing an existing? $isEdit = isset($_REQUEST['add']) ? 0 : 1; // Make sure we have our stuff. require_once SUBSDIR . '/Poll.subs.php'; // Get the starter and the poll's ID - if it's an edit. $bcinfo = getPollStarter($topic); // Check their adding/editing is valid. if (!$isEdit && !empty($bcinfo['id_poll'])) { fatal_lang_error('poll_already_exists'); } elseif ($isEdit && empty($bcinfo['id_poll'])) { fatal_lang_error('poll_not_found'); } // Check if they have the power to add or edit the poll. if ($isEdit && !allowedTo('poll_edit_any')) { isAllowedTo('poll_edit_' . ($user_info['id'] == $bcinfo['id_member_started'] || $bcinfo['poll_starter'] != 0 && $user_info['id'] == $bcinfo['poll_starter'] ? 'own' : 'any')); } elseif (!$isEdit && !allowedTo('poll_add_any')) { isAllowedTo('poll_add_' . ($user_info['id'] == $bcinfo['id_member_started'] ? 'own' : 'any')); } $optionCount = 0; $idCount = 0; // Ensure the user is leaving a valid amount of options - there must be at least two. foreach ($_POST['options'] as $k => $option) { if (trim($option) != '') { $optionCount++; $idCount = max($idCount, $k); } } if ($optionCount < 2) { $poll_errors->addError('poll_few'); } elseif ($optionCount > 256 || $idCount > 255) { $poll_errors->addError('poll_many'); } // Also - ensure they are not removing the question. if (trim($_POST['question']) == '') { $poll_errors->addError('no_question'); } // Got any errors to report? if ($poll_errors->hasErrors()) { return $this->action_editpoll(); } // Prevent double submission of this form. checkSubmitOnce('check'); // Now we've done all our error checking, let's get the core poll information cleaned... question first. $_POST['question'] = Util::htmlspecialchars($_POST['question']); $_POST['question'] = Util::substr($_POST['question'], 0, 255); $_POST['poll_hide'] = (int) $_POST['poll_hide']; $_POST['poll_expire'] = isset($_POST['poll_expire']) ? (int) $_POST['poll_expire'] : 0; $_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'; $allowedGroups = groupsAllowedTo('poll_vote', $board); if (!in_array(-1, $allowedGroups['allowed'])) { $_POST['poll_guest_vote'] = 0; } } // Ensure that the number options allowed makes sense, and the expiration date is valid. if (!$isEdit || allowedTo('moderate_board')) { $_POST['poll_expire'] = $_POST['poll_expire'] > 9999 ? 9999 : ($_POST['poll_expire'] < 0 ? 0 : $_POST['poll_expire']); if (empty($_POST['poll_expire']) && $_POST['poll_hide'] == 2) { $_POST['poll_hide'] = 1; } elseif (!$isEdit || $_POST['poll_expire'] != ceil($bcinfo['expire_time'] <= time() ? -1 : ($bcinfo['expire_time'] - time()) / (3600 * 24))) { $_POST['poll_expire'] = empty($_POST['poll_expire']) ? '0' : time() + $_POST['poll_expire'] * 3600 * 24; } else { $_POST['poll_expire'] = $bcinfo['expire_time']; } if (empty($_POST['poll_max_votes']) || $_POST['poll_max_votes'] <= 0) { $_POST['poll_max_votes'] = 1; } else { $_POST['poll_max_votes'] = (int) $_POST['poll_max_votes']; } } // If we're editing, let's commit the changes. if ($isEdit) { modifyPoll($bcinfo['id_poll'], $_POST['question'], !empty($_POST['poll_max_votes']) ? $_POST['poll_max_votes'] : 0, $_POST['poll_hide'], !empty($_POST['poll_expire']) ? $_POST['poll_expire'] : 0, $_POST['poll_change_vote'], $_POST['poll_guest_vote']); } else { // Create the poll. $bcinfo['id_poll'] = createPoll($_POST['question'], $user_info['id'], $user_info['username'], $_POST['poll_max_votes'], $_POST['poll_hide'], $_POST['poll_expire'], $_POST['poll_change_vote'], $_POST['poll_guest_vote']); // Link the poll to the topic. associatedPoll($topic, $bcinfo['id_poll']); } // Get all the choices. (no better way to remove all emptied and add previously non-existent ones.) $choices = array_keys(pollOptions($bcinfo['id_poll'])); $add_options = array(); $update_options = array(); $delete_options = array(); foreach ($_POST['options'] as $k => $option) { // Make sure the key is numeric for sanity's sake. $k = (int) $k; // They've cleared the box. Either they want it deleted, or it never existed. if (trim($option) == '') { // They want it deleted. Bye. if (in_array($k, $choices)) { $delete_options[] = $k; } // Skip the rest... continue; } // Dress the option up for its big date with the database. $option = Util::htmlspecialchars($option); // If it's already there, update it. If it's not... add it. if (in_array($k, $choices)) { $update_options[] = array($bcinfo['id_poll'], $k, $option); } else { $add_options[] = array($bcinfo['id_poll'], $k, $option, 0); } } if (!empty($update_options)) { modifyPollOption($update_options); } if (!empty($add_options)) { insertPollOptions($add_options); } // I'm sorry, but... well, no one was choosing you. Poor options, I'll put you out of your misery. if (!empty($delete_options)) { deletePollOptions($bcinfo['id_poll'], $delete_options); } // Shall I reset the vote count, sir? if (isset($_POST['resetVoteCount'])) { resetVotes($bcinfo['id_poll']); } call_integration_hook('integrate_poll_add_edit', array($bcinfo['id_poll'], $isEdit)); // Off we go. redirectexit('topic=' . $topic . '.' . $_REQUEST['start']); }
/** * Does the actual saving of the article data * * - validates the data is safe to save * - updates existing articles or creates new ones */ private function _sportal_admin_article_edit_save() { global $context, $txt, $modSettings; // No errors, yet. $article_errors = Error_Context::context('article', 0); // Use our standard validation functions in a few spots require_once SUBSDIR . '/DataValidator.class.php'; $validator = new Data_Validator(); // If its not new, lets load the current data if (!$this->_is_new) { $_REQUEST['article_id'] = (int) $_REQUEST['article_id']; $context['article'] = sportal_get_articles($_REQUEST['article_id']); } // Clean and Review the post data for compliance $validator->sanitation_rules(array('title' => 'trim|Util::htmlspecialchars', 'namespace' => 'trim|Util::htmlspecialchars', 'article_id' => 'intval', 'category_id' => 'intval', 'permissions' => 'intval', 'type' => 'trim', 'content' => 'trim')); $validator->validation_rules(array('title' => 'required', 'namespace' => 'alpha_numeric|required', 'type' => 'required', 'content' => 'required')); $validator->text_replacements(array('title' => $txt['sp_admin_articles_col_title'], 'namespace' => $txt['sp_admin_articles_col_namespace'], 'content' => $txt['sp_admin_articles_col_body'])); // If you messed this up, back you go if (!$validator->validate($_POST)) { foreach ($validator->validation_errors() as $id => $error) { $article_errors->addError($error); } $this->action_sportal_admin_article_edit(); } // Lets make sure this namespace (article id) is unique $has_duplicate = sp_duplicate_articles($validator->article_id, $validator->namespace); if (!empty($has_duplicate)) { $article_errors->addError('sp_error_article_namespace_duplicate'); } // And we can't have just a numeric namespace (article id) if (preg_replace('~[0-9]+~', '', $validator->namespace) === '') { $article_errors->addError('sp_error_article_namespace_numeric'); } // Posting some PHP code, and allowed? Then we need to validate it will run if ($_POST['type'] === 'php' && !empty($_POST['content']) && empty($modSettings['sp_disable_php_validation'])) { $validator_php = new Data_Validator(); $validator_php->validation_rules(array('content' => 'php_syntax')); // Bad PHP code if (!$validator_php->validate(array('content' => $_POST['content']))) { $article_errors->addError($validator_php->validation_errors()); } } // None shall pass ... with errors if ($article_errors->hasErrors()) { $this->action_sportal_admin_article_edit(); } // No errors then, prepare the data for saving $article_info = array('id' => $validator->article_id, 'id_category' => $validator->category_id, 'namespace' => $validator->namespace, 'title' => $validator->title, 'body' => Util::htmlspecialchars($_POST['content'], ENT_QUOTES), 'type' => in_array($validator->type, array('bbc', 'html', 'php')) ? $_POST['type'] : 'bbc', 'permissions' => $validator->permissions, 'status' => !empty($_POST['status']) ? 1 : 0); if ($article_info['type'] === 'bbc') { preparsecode($article_info['body']); } // Save away checkSession(); sp_save_article($article_info, $this->_is_new); redirectexit('action=admin;area=portalarticles'); return true; }
/** * This function handles submitted forms that add, modify or remove ban triggers. */ public function action_edit2() { global $context; require_once SUBSDIR . '/Bans.subs.php'; // Check with security first checkSession(); validateToken('admin-bet'); $ban_errors = Error_Context::context('ban', 1); // Adding or editing a ban group if (isset($_POST['add_ban']) || isset($_POST['modify_ban'])) { $ban_info = array(); // Let's collect all the information we need $ban_info['id'] = isset($_REQUEST['bg']) ? (int) $_REQUEST['bg'] : 0; $ban_info['is_new'] = empty($ban_info['id']); $ban_info['expire_date'] = !empty($_POST['expire_date']) ? (int) $_POST['expire_date'] : 0; $ban_info['expiration'] = array('status' => isset($_POST['expiration']) && in_array($_POST['expiration'], array('never', 'one_day', 'expired')) ? $_POST['expiration'] : 'never', 'days' => $ban_info['expire_date']); $ban_info['db_expiration'] = $ban_info['expiration']['status'] == 'never' ? 'NULL' : ($ban_info['expiration']['status'] == 'one_day' ? time() + 24 * 60 * 60 * $ban_info['expire_date'] : 0); $ban_info['full_ban'] = empty($_POST['full_ban']) ? 0 : 1; $ban_info['reason'] = !empty($_POST['reason']) ? Util::htmlspecialchars($_POST['reason'], ENT_QUOTES) : ''; $ban_info['name'] = !empty($_POST['ban_name']) ? Util::htmlspecialchars($_POST['ban_name'], ENT_QUOTES) : ''; $ban_info['notes'] = isset($_POST['notes']) ? Util::htmlspecialchars($_POST['notes'], ENT_QUOTES) : ''; $ban_info['notes'] = str_replace(array("\r", "\n", ' '), array('', '<br />', ' '), $ban_info['notes']); $ban_info['cannot']['access'] = empty($ban_info['full_ban']) ? 0 : 1; $ban_info['cannot']['post'] = !empty($ban_info['full_ban']) || empty($_POST['cannot_post']) ? 0 : 1; $ban_info['cannot']['register'] = !empty($ban_info['full_ban']) || empty($_POST['cannot_register']) ? 0 : 1; $ban_info['cannot']['login'] = !empty($ban_info['full_ban']) || empty($_POST['cannot_login']) ? 0 : 1; // Adding a new ban group if (empty($ban_info['id'])) { $ban_group_id = insertBanGroup($ban_info); } else { $ban_group_id = updateBanGroup($ban_info); } if ($ban_group_id !== false) { $ban_info['id'] = $ban_group_id; $ban_info['is_new'] = false; } $context['ban'] = $ban_info; } // Update the triggers associated with this ban if (isset($_POST['ban_suggestions'])) { $saved_triggers = saveTriggers($_POST['ban_suggestions'], $ban_info['id'], isset($_REQUEST['u']) ? (int) $_REQUEST['u'] : 0, isset($_REQUEST['bi']) ? (int) $_REQUEST['bi'] : 0); $context['ban_suggestions']['saved_triggers'] = $saved_triggers; } // Something went wrong somewhere, ban info or triggers, ... Oh well, let's go back. if ($ban_errors->hasErrors()) { $context['ban_suggestions'] = $saved_triggers; $context['ban']['from_user'] = true; // They may have entered a name not using the member select box if (isset($_REQUEST['u'])) { $context['ban_suggestions'] = array_merge($context['ban_suggestions'], getMemberData((int) $_REQUEST['u'])); } elseif (isset($_REQUEST['user'])) { $context['ban']['from_user'] = false; $context['use_autosuggest'] = true; $context['ban_suggestions']['member']['name'] = $_REQUEST['user']; } // Not strictly necessary, but it's nice if (!empty($context['ban_suggestions']['member']['id'])) { $context['ban_suggestions']['other_ips'] = banLoadAdditionalIPs($context['ban_suggestions']['member']['id']); } return $this->action_edit(); } if (isset($_POST['ban_items'])) { $ban_group_id = isset($_REQUEST['bg']) ? (int) $_REQUEST['bg'] : 0; $ban_items = array_map('intval', $_POST['ban_items']); removeBanTriggers($ban_items, $ban_group_id); } // Register the last modified date. updateSettings(array('banLastUpdated' => time())); // Update the member table to represent the new ban situation. updateBanMembers(); // Go back to an appropriate spot redirectexit('action=admin;area=ban;sa=' . (isset($_POST['add_ban']) ? 'list' : 'edit;bg=' . $ban_group_id)); }
/** * 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')))); } } }
/** * Registers a member to the forum. * * What it does: * - Allows two types of interface: 'guest' and 'admin'. The first * - includes hammering protection, the latter can perform the registration silently. * - The strings used in the options array are assumed to be escaped. * - Allows to perform several checks on the input, e.g. reserved names. * - The function will adjust member statistics. * - If an error is detected will fatal error on all errors unless return_errors is true. * * @package Members * @uses Auth.subs.php * @uses Mail.subs.php * @param mixed[] $regOptions * @param string $error_context * @return integer the ID of the newly created member */ function registerMember(&$regOptions, $error_context = 'register') { global $scripturl, $txt, $modSettings, $user_info; $db = database(); loadLanguage('Login'); // We'll need some external functions. require_once SUBSDIR . '/Auth.subs.php'; require_once SUBSDIR . '/Mail.subs.php'; // Put any errors in here. $reg_errors = Error_Context::context($error_context, 0); // 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'; } } // Spaces and other odd characters are evil... $regOptions['username'] = 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', ' ', $regOptions['username'])); // Valid emails only require_once SUBSDIR . '/DataValidator.class.php'; if (!Data_Validator::is_valid($regOptions, array('email' => 'valid_email|required|max_length[255]'), array('email' => 'trim'))) { $reg_errors->addError('bad_email'); } validateUsername(0, $regOptions['username'], $error_context, !empty($regOptions['check_reserved_name'])); // 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->addError('passwords_dont_match'); } // That's kind of easy to guess... if ($regOptions['password'] == '') { if ($regOptions['auth_method'] == 'password') { $reg_errors->addError('no_password'); } else { $regOptions['password'] = sha1(mt_rand()); } } // Now perform hard password validation as required. if (!empty($regOptions['check_password_strength']) && $regOptions['password'] != '') { $passwordError = validatePassword($regOptions['password'], $regOptions['username'], array($regOptions['email'])); // Password isn't legal? if ($passwordError != null) { $reg_errors->addError('profile_error_password_' . $passwordError); } } // 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('', ' 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'])); if ($db->num_rows($request) != 0) { $reg_errors->addError(array('email_in_use', array(htmlspecialchars($regOptions['email'], ENT_COMPAT, 'UTF-8')))); } $db->free_result($request); // Perhaps someone else wants to check this user call_integration_hook('integrate_register_check', array(&$regOptions, &$reg_errors)); // If there's any errors left return them at once! if ($reg_errors->hasErrors()) { return false; } $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']) && count(array_intersect(array_keys($regOptions['theme_vars']), $reservedVars)) != 0) { fatal_lang_error('no_theme'); } // New password hash require_once SUBSDIR . '/Auth.subs.php'; // 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' => validateLoginPassword($regOptions['password'], '', $regOptions['username'], true), 'password_salt' => substr(md5(mt_rand()), 0, 4), 'posts' => 0, 'date_registered' => !empty($regOptions['time']) ? $regOptions['time'] : time(), 'member_ip' => $regOptions['interface'] == 'admin' ? '127.0.0.1' : $regOptions['ip'], 'member_ip2' => $regOptions['interface'] == 'admin' ? '127.0.0.1' : $regOptions['ip2'], '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' => '', 'website_title' => '', 'website_url' => '', '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; // @todo 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('', ' 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 = $db->fetch_assoc($request)) { $unassignableGroups[] = $row['id_group']; } $db->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; } } // Right, now let's prepare for insertion. $knownInts = array('date_registered', 'posts', 'id_group', 'last_login', 'personal_messages', 'unread_messages', 'notifications', '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'); // Call an optional function to validate the users' input. call_integration_hook('integrate_register', array(&$regOptions, &$theme_vars, &$knownInts, &$knownFloats)); $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. $db->insert('', '{db_prefix}members', $column_names, $values, array('id_member')); $memberID = $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) { updateMemberStats($memberID, $regOptions['register_vars']['real_name']); } else { updateMemberStats(); } // Theme variables too? if (!empty($theme_vars)) { $inserts = array(); foreach ($theme_vars as $var => $val) { $inserts[] = array($memberID, $var, $val); } $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); } } else { // 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. require_once SUBSDIR . '/Notification.subs.php'; sendAdminNotifications('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... require_once SUBSDIR . '/Notification.subs.php'; sendAdminNotifications('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; } // If they are for sure registered, let other people to know about it call_integration_hook('integrate_register_after', array($regOptions, $memberID)); return $memberID; }
/** * Used to edit the body or subject of a message inline * called from action=jsmodify from script and topic js */ public function action_jsmodify() { global $modSettings, $board, $topic; global $user_info, $context; $db = database(); // We have to have a topic! if (empty($topic)) { obExit(false); } checkSession('get'); require_once SUBSDIR . '/Post.subs.php'; // Assume the first message if no message ID was given. $request = $db->query('', ' SELECT t.locked, t.num_replies, t.id_member_started, t.id_first_msg, m.id_msg, m.id_member, m.poster_time, m.subject, m.smileys_enabled, m.body, m.icon, m.modified_time, m.modified_name, m.approved FROM {db_prefix}messages AS m INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic}) WHERE m.id_msg = {raw:id_msg} AND m.id_topic = {int:current_topic}' . (allowedTo('modify_any') || allowedTo('approve_posts') ? '' : (!$modSettings['postmod_active'] ? ' AND (m.id_member != {int:guest_id} AND m.id_member = {int:current_member})' : ' AND (m.approved = {int:is_approved} OR (m.id_member != {int:guest_id} AND m.id_member = {int:current_member}))')), array('current_member' => $user_info['id'], 'current_topic' => $topic, 'id_msg' => empty($_REQUEST['msg']) ? 't.id_first_msg' : (int) $_REQUEST['msg'], 'is_approved' => 1, 'guest_id' => 0)); if ($db->num_rows($request) == 0) { fatal_lang_error('no_board', false); } $row = $db->fetch_assoc($request); $db->free_result($request); // Change either body or subject requires permissions to modify messages. if (isset($_POST['message']) || isset($_POST['subject']) || isset($_REQUEST['icon'])) { if (!empty($row['locked'])) { isAllowedTo('moderate_board'); } 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 ($row['id_member_started'] == $user_info['id'] && !allowedTo('modify_own')) { isAllowedTo('modify_replies'); } else { isAllowedTo('modify_own'); } } elseif ($row['id_member_started'] == $user_info['id'] && !allowedTo('modify_any')) { isAllowedTo('modify_replies'); } else { isAllowedTo('modify_any'); } // Only log this action if it wasn't your message. $moderationAction = $row['id_member'] != $user_info['id']; } $post_errors = Error_Context::context('post', 1); if (isset($_POST['subject']) && Util::htmltrim(Util::htmlspecialchars($_POST['subject'])) !== '') { $_POST['subject'] = strtr(Util::htmlspecialchars($_POST['subject']), array("\r" => '', "\n" => '', "\t" => '')); // Maximum number of characters. if (Util::strlen($_POST['subject']) > 100) { $_POST['subject'] = Util::substr($_POST['subject'], 0, 100); } } elseif (isset($_POST['subject'])) { $post_errors->addError('no_subject'); unset($_POST['subject']); } if (isset($_POST['message'])) { if (Util::htmltrim(Util::htmlspecialchars($_POST['message'])) === '') { $post_errors->addError('no_message'); unset($_POST['message']); } elseif (!empty($modSettings['max_messageLength']) && Util::strlen($_POST['message']) > $modSettings['max_messageLength']) { $post_errors->addError(array('long_message', array($modSettings['max_messageLength']))); unset($_POST['message']); } else { $_POST['message'] = Util::htmlspecialchars($_POST['message'], ENT_QUOTES); preparsecode($_POST['message']); if (Util::htmltrim(strip_tags(parse_bbc($_POST['message'], false), '<img>')) === '') { $post_errors->addError('no_message'); unset($_POST['message']); } } } if (isset($_POST['lock'])) { if (!allowedTo(array('lock_any', 'lock_own')) || !allowedTo('lock_any') && $user_info['id'] != $row['id_member']) { unset($_POST['lock']); } elseif (!allowedTo('lock_any')) { if ($row['locked'] == 1) { unset($_POST['lock']); } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 2; } } elseif (!empty($row['locked']) && !empty($_POST['lock']) || $_POST['lock'] == $row['locked']) { unset($_POST['lock']); } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 1; } } if (isset($_POST['sticky']) && !allowedTo('make_sticky')) { unset($_POST['sticky']); } if (!$post_errors->hasErrors()) { $msgOptions = array('id' => $row['id_msg'], 'subject' => isset($_POST['subject']) ? $_POST['subject'] : null, 'body' => isset($_POST['message']) ? $_POST['message'] : null, 'icon' => isset($_REQUEST['icon']) ? preg_replace('~[\\./\\\\*\':"<>]~', '', $_REQUEST['icon']) : null); $topicOptions = array('id' => $topic, 'board' => $board, 'lock_mode' => isset($_POST['lock']) ? (int) $_POST['lock'] : null, 'sticky_mode' => isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics']) ? (int) $_POST['sticky'] : null, 'mark_as_read' => false); $posterOptions = array(); // Only consider marking as editing if they have edited the subject, message or icon. if (isset($_POST['subject']) && $_POST['subject'] != $row['subject'] || isset($_POST['message']) && $_POST['message'] != $row['body'] || isset($_REQUEST['icon']) && $_REQUEST['icon'] != $row['icon']) { // And even then only if the time has passed... 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']; } } else { $moderationAction = false; } modifyPost($msgOptions, $topicOptions, $posterOptions); // If we didn't change anything this time but had before put back the old info. if (!isset($msgOptions['modify_time']) && !empty($row['modified_time'])) { $msgOptions['modify_time'] = $row['modified_time']; $msgOptions['modify_name'] = $row['modified_name']; } // Changing the first subject updates other subjects to 'Re: new_subject'. if (isset($_POST['subject']) && isset($_REQUEST['change_all_subjects']) && $row['id_first_msg'] == $row['id_msg'] && !empty($row['num_replies']) && (allowedTo('modify_any') || $row['id_member_started'] == $user_info['id'] && allowedTo('modify_replies'))) { // Get the proper (default language) response prefix first. $context['response_prefix'] = response_prefix(); $db->query('', ' UPDATE {db_prefix}messages SET subject = {string:subject} WHERE id_topic = {int:current_topic} AND id_msg != {int:id_first_msg}', array('current_topic' => $topic, 'id_first_msg' => $row['id_first_msg'], 'subject' => $context['response_prefix'] . $_POST['subject'])); } if (!empty($moderationAction)) { logAction('modify', array('topic' => $topic, 'message' => $row['id_msg'], 'member' => $row['id_member'], 'board' => $board)); } } if (isset($_REQUEST['xml'])) { $context['sub_template'] = 'modifydone'; if (!$post_errors->hasErrors() && isset($msgOptions['subject']) && isset($msgOptions['body'])) { $context['message'] = array('id' => $row['id_msg'], 'modified' => array('time' => isset($msgOptions['modify_time']) ? standardTime($msgOptions['modify_time']) : '', 'html_time' => isset($msgOptions['modify_time']) ? htmlTime($msgOptions['modify_time']) : '', 'timestamp' => isset($msgOptions['modify_time']) ? forum_time(true, $msgOptions['modify_time']) : 0, 'name' => isset($msgOptions['modify_time']) ? $msgOptions['modify_name'] : ''), 'subject' => $msgOptions['subject'], 'first_in_topic' => $row['id_msg'] == $row['id_first_msg'], 'body' => strtr($msgOptions['body'], array(']]>' => ']]]]><![CDATA[>'))); censorText($context['message']['subject']); censorText($context['message']['body']); $context['message']['body'] = parse_bbc($context['message']['body'], $row['smileys_enabled'], $row['id_msg']); } elseif (!$post_errors->hasErrors()) { $context['sub_template'] = 'modifytopicdone'; $context['message'] = array('id' => $row['id_msg'], 'modified' => array('time' => isset($msgOptions['modify_time']) ? standardTime($msgOptions['modify_time']) : '', 'html_time' => isset($msgOptions['modify_time']) ? htmlTime($msgOptions['modify_time']) : '', 'timestamp' => isset($msgOptions['modify_time']) ? forum_time(true, $msgOptions['modify_time']) : 0, 'name' => isset($msgOptions['modify_time']) ? $msgOptions['modify_name'] : ''), 'subject' => isset($msgOptions['subject']) ? $msgOptions['subject'] : ''); censorText($context['message']['subject']); } else { $context['message'] = array('id' => $row['id_msg'], 'errors' => array(), 'error_in_subject' => $post_errors->hasError('no_subject'), 'error_in_body' => $post_errors->hasError('no_message') || $post_errors->hasError('long_message')); $context['message']['errors'] = $post_errors->prepareErrors(); } } else { obExit(false); } }
/** * Send a personal message. */ public function action_send2() { global $txt, $context, $user_info, $modSettings; // All the helpers we need require_once SUBSDIR . '/Auth.subs.php'; require_once SUBSDIR . '/Post.subs.php'; // PM Drafts enabled and needed? if ($context['drafts_pm_save'] && (isset($_POST['save_draft']) || isset($_POST['id_pm_draft']))) { require_once SUBSDIR . '/Drafts.subs.php'; } loadLanguage('PersonalMessage', '', false); // Extract out the spam settings - it saves database space! list($modSettings['max_pm_recipients'], $modSettings['pm_posts_verification'], $modSettings['pm_posts_per_hour']) = explode(',', $modSettings['pm_spam_settings']); // Initialize the errors we're about to make. $post_errors = Error_Context::context('pm', 1); // Check whether we've gone over the limit of messages we can send per hour - fatal error if fails! if (!empty($modSettings['pm_posts_per_hour']) && !allowedTo(array('admin_forum', 'moderate_forum', 'send_mail')) && $user_info['mod_cache']['bq'] == '0=1' && $user_info['mod_cache']['gq'] == '0=1') { // How many have they sent this last hour? $pmCount = pmCount($user_info['id'], 3600); if (!empty($pmCount) && $pmCount >= $modSettings['pm_posts_per_hour']) { if (!isset($_REQUEST['xml'])) { fatal_lang_error('pm_too_many_per_hour', true, array($modSettings['pm_posts_per_hour'])); } else { $post_errors->addError('pm_too_many_per_hour'); } } } // If your session timed out, show an error, but do allow to re-submit. if (!isset($_REQUEST['xml']) && checkSession('post', '', false) != '') { $post_errors->addError('session_timeout'); } $_REQUEST['subject'] = isset($_REQUEST['subject']) ? strtr(Util::htmltrim($_POST['subject']), array("\r" => '', "\n" => '', "\t" => '')) : ''; $_REQUEST['to'] = empty($_POST['to']) ? empty($_GET['to']) ? '' : $_GET['to'] : $_POST['to']; $_REQUEST['bcc'] = empty($_POST['bcc']) ? empty($_GET['bcc']) ? '' : $_GET['bcc'] : $_POST['bcc']; // Route the input from the 'u' parameter to the 'to'-list. if (!empty($_POST['u'])) { $_POST['recipient_to'] = explode(',', $_POST['u']); } // Construct the list of recipients. $recipientList = array(); $namedRecipientList = array(); $namesNotFound = array(); foreach (array('to', 'bcc') as $recipientType) { // First, let's see if there's user ID's given. $recipientList[$recipientType] = array(); if (!empty($_POST['recipient_' . $recipientType]) && is_array($_POST['recipient_' . $recipientType])) { foreach ($_POST['recipient_' . $recipientType] as $recipient) { $recipientList[$recipientType][] = (int) $recipient; } } // Are there also literal names set? if (!empty($_REQUEST[$recipientType])) { // We're going to take out the "s anyway ;). $recipientString = strtr($_REQUEST[$recipientType], array('\\"' => '"')); preg_match_all('~"([^"]+)"~', $recipientString, $matches); $namedRecipientList[$recipientType] = array_unique(array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $recipientString)))); // Clean any literal names entered foreach ($namedRecipientList[$recipientType] as $index => $recipient) { if (strlen(trim($recipient)) > 0) { $namedRecipientList[$recipientType][$index] = Util::htmlspecialchars(Util::strtolower(trim($recipient))); } else { unset($namedRecipientList[$recipientType][$index]); } } // Now see if we can resolove the entered name to an actual user if (!empty($namedRecipientList[$recipientType])) { $foundMembers = findMembers($namedRecipientList[$recipientType]); // Assume all are not found, until proven otherwise. $namesNotFound[$recipientType] = $namedRecipientList[$recipientType]; // Make sure we only have each member listed once, incase they did not use the select list foreach ($foundMembers as $member) { $testNames = array(Util::strtolower($member['username']), Util::strtolower($member['name']), Util::strtolower($member['email'])); if (count(array_intersect($testNames, $namedRecipientList[$recipientType])) !== 0) { $recipientList[$recipientType][] = $member['id']; // Get rid of this username, since we found it. $namesNotFound[$recipientType] = array_diff($namesNotFound[$recipientType], $testNames); } } } } // Selected a recipient to be deleted? Remove them now. if (!empty($_POST['delete_recipient'])) { $recipientList[$recipientType] = array_diff($recipientList[$recipientType], array((int) $_POST['delete_recipient'])); } // Make sure we don't include the same name twice $recipientList[$recipientType] = array_unique($recipientList[$recipientType]); } // Are we changing the recipients some how? $is_recipient_change = !empty($_POST['delete_recipient']) || !empty($_POST['to_submit']) || !empty($_POST['bcc_submit']); // Check if there's at least one recipient. if (empty($recipientList['to']) && empty($recipientList['bcc'])) { $post_errors->addError('no_to'); } // Make sure that we remove the members who did get it from the screen. if (!$is_recipient_change) { foreach (array_keys($recipientList) as $recipientType) { if (!empty($namesNotFound[$recipientType])) { $post_errors->addError('bad_' . $recipientType); // Since we already have a post error, remove the previous one. $post_errors->removeError('no_to'); foreach ($namesNotFound[$recipientType] as $name) { $context['send_log']['failed'][] = sprintf($txt['pm_error_user_not_found'], $name); } } } } // Did they make any mistakes like no subject or message? if ($_REQUEST['subject'] == '') { $post_errors->addError('no_subject'); } if (!isset($_REQUEST['message']) || $_REQUEST['message'] == '') { $post_errors->addError('no_message'); } elseif (!empty($modSettings['max_messageLength']) && Util::strlen($_REQUEST['message']) > $modSettings['max_messageLength']) { $post_errors->addError('long_message'); } else { // Preparse the message. $message = $_REQUEST['message']; preparsecode($message); // Make sure there's still some content left without the tags. if (Util::htmltrim(strip_tags(parse_bbc(Util::htmlspecialchars($message, ENT_QUOTES), false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($message, '[html]') === false)) { $post_errors->addError('no_message'); } } // Wrong verification code? if (!$user_info['is_admin'] && !isset($_REQUEST['xml']) && !empty($modSettings['pm_posts_verification']) && $user_info['posts'] < $modSettings['pm_posts_verification']) { require_once SUBSDIR . '/VerificationControls.class.php'; $verificationOptions = array('id' => 'pm'); $context['require_verification'] = create_control_verification($verificationOptions, true); if (is_array($context['require_verification'])) { foreach ($context['require_verification'] as $error) { $post_errors->addError($error); } } } // If they made any errors, give them a chance to make amends. if ($post_errors->hasErrors() && !$is_recipient_change && !isset($_REQUEST['preview']) && !isset($_REQUEST['xml'])) { return messagePostError($namedRecipientList, $recipientList); } // Want to take a second glance before you send? if (isset($_REQUEST['preview'])) { // Set everything up to be displayed. $context['preview_subject'] = Util::htmlspecialchars($_REQUEST['subject']); $context['preview_message'] = Util::htmlspecialchars($_REQUEST['message'], ENT_QUOTES, 'UTF-8', true); preparsecode($context['preview_message'], true); // Parse out the BBC if it is enabled. $context['preview_message'] = parse_bbc($context['preview_message']); // Censor, as always. censorText($context['preview_subject']); censorText($context['preview_message']); // Set a descriptive title. $context['page_title'] = $txt['preview'] . ' - ' . $context['preview_subject']; // Pretend they messed up but don't ignore if they really did :P. return messagePostError($namedRecipientList, $recipientList); } elseif ($is_recipient_change) { // Maybe we couldn't find one? foreach ($namesNotFound as $recipientType => $names) { $post_errors->addError('bad_' . $recipientType); foreach ($names as $name) { $context['send_log']['failed'][] = sprintf($txt['pm_error_user_not_found'], $name); } } return messagePostError($namedRecipientList, $recipientList); } // Want to save this as a draft and think about it some more? if ($context['drafts_pm_save'] && isset($_POST['save_draft'])) { savePMDraft($recipientList); return messagePostError($namedRecipientList, $recipientList); } elseif (!empty($modSettings['max_pm_recipients']) && count($recipientList['to']) + count($recipientList['bcc']) > $modSettings['max_pm_recipients'] && !allowedTo(array('moderate_forum', 'send_mail', 'admin_forum'))) { $context['send_log'] = array('sent' => array(), 'failed' => array(sprintf($txt['pm_too_many_recipients'], $modSettings['max_pm_recipients']))); return messagePostError($namedRecipientList, $recipientList); } // Protect from message spamming. spamProtection('pm'); // Prevent double submission of this form. checkSubmitOnce('check'); // Finally do the actual sending of the PM. if (!empty($recipientList['to']) || !empty($recipientList['bcc'])) { $context['send_log'] = sendpm($recipientList, $_REQUEST['subject'], $_REQUEST['message'], true, null, !empty($_REQUEST['pm_head']) ? (int) $_REQUEST['pm_head'] : 0); } else { $context['send_log'] = array('sent' => array(), 'failed' => array()); } // Mark the message as "replied to". if (!empty($context['send_log']['sent']) && !empty($_REQUEST['replied_to']) && isset($_REQUEST['f']) && $_REQUEST['f'] == 'inbox') { require_once SUBSDIR . '/PersonalMessage.subs.php'; setPMRepliedStatus($user_info['id'], (int) $_REQUEST['replied_to']); } // If one or more of the recipients were invalid, go back to the post screen with the failed usernames. if (!empty($context['send_log']['failed'])) { return messagePostError($namesNotFound, array('to' => array_intersect($recipientList['to'], $context['send_log']['failed']), 'bcc' => array_intersect($recipientList['bcc'], $context['send_log']['failed']))); } // Message sent successfully? if (!empty($context['send_log']) && empty($context['send_log']['failed'])) { $context['current_label_redirect'] = $context['current_label_redirect'] . ';done=sent'; // If we had a PM draft for this one, then its time to remove it since it was just sent if ($context['drafts_pm_save'] && !empty($_POST['id_pm_draft'])) { deleteDrafts($_POST['id_pm_draft'], $user_info['id']); } } // Go back to the where they sent from, if possible... redirectexit($context['current_label_redirect']); }
/** * Saves a PM draft in the user_drafts table * * - The core draft feature must be enabled, as well as the pm draft option * - Determines if this is a new or and update to an existing pm draft * * @package Drafts * @param mixed[] $recipientList */ function savePMDraft($recipientList) { global $context, $user_info, $modSettings; // Ajax calling if (!isset($context['drafts_pm_save'])) { $context['drafts_pm_save'] = !empty($modSettings['drafts_enabled']) && !empty($modSettings['drafts_pm_enabled']) && allowedTo('pm_draft'); } // PM survey says ... can you stay or must you go if (empty($context['drafts_pm_save']) || !isset($_POST['save_draft']) || !isset($_POST['id_pm_draft'])) { return false; } // Read in what was sent $id_pm_draft = empty($_POST['id_pm_draft']) ? 0 : (int) $_POST['id_pm_draft']; $draft_info = loadDraft($id_pm_draft, 1); $post_errors = Error_Context::context('pm', 1); // 5 seconds is the same limit we have for posting if (isset($_REQUEST['xml']) && !empty($draft_info['poster_time']) && time() < $draft_info['poster_time'] + 5) { // Send something back to the javascript caller if (!empty($id_pm_draft)) { loadTemplate('Xml'); $context['sub_template'] = 'xml_draft'; $context['id_draft'] = $id_pm_draft; $context['draft_saved_on'] = $draft_info['poster_time']; obExit(); } return true; } // Determine who this is being sent to if (isset($_REQUEST['xml'])) { $recipientList['to'] = isset($_POST['recipient_to']) ? explode(',', $_POST['recipient_to']) : array(); $recipientList['bcc'] = isset($_POST['recipient_bcc']) ? explode(',', $_POST['recipient_bcc']) : array(); } elseif (!empty($draft_info['to_list']) && empty($recipientList)) { $recipientList = unserialize($draft_info['to_list']); } // Prepare the data $draft = array('id_pm_draft' => $id_pm_draft, 'reply_id' => empty($_POST['replied_to']) ? 0 : (int) $_POST['replied_to'], 'body' => Util::htmlspecialchars($_POST['message'], ENT_QUOTES), 'subject' => strtr(Util::htmlspecialchars($_POST['subject']), array("\r" => '', "\n" => '', "\t" => '')), 'id_member' => $user_info['id']); // message and subject always need a bit more work preparsecode($draft['body']); if (Util::strlen($draft['subject']) > 100) { $draft['subject'] = Util::substr($draft['subject'], 0, 100); } // Modifying an existing PM draft? if (!empty($id_pm_draft) && !empty($draft_info)) { modify_pm_draft($draft, $recipientList); // some items to return to the form $context['draft_saved'] = true; $context['id_pm_draft'] = $id_pm_draft; } else { $id_pm_draft = create_pm_draft($draft, $recipientList); // Everything go as expected, if not toss back an error if (!empty($id_pm_draft)) { $context['draft_saved'] = true; $context['id_pm_draft'] = $id_pm_draft; } else { $post_errors->addError('draft_not_saved'); } } // if we were called from the autosave function, send something back if (!empty($id_pm_draft) && isset($_REQUEST['xml']) && !$post_errors->hasError('session_timeout')) { loadTemplate('Xml'); $context['sub_template'] = 'xml_draft'; $context['id_draft'] = $id_pm_draft; $context['draft_saved_on'] = time(); obExit(); } return; }
public function action_register2() { global $txt, $modSettings, $context, $user_info; // Start collecting together any errors. $reg_errors = Error_Context::context('register', 0); // Check they are who they should be checkSession(); if (!validateToken('register', 'post', true, false)) { $reg_errors->addError('token_verification'); } // You can't register if it's disabled. if (!empty($modSettings['registration_method']) && $modSettings['registration_method'] == 3) { fatal_lang_error('registration_disabled', false); } // Well, if you don't agree, you can't register. if (!empty($modSettings['requireAgreement']) && !isset($_POST['checkbox_agreement'])) { $reg_errors->addError('agreement_unchecked'); } // Make sure they came from *somewhere*, have a session. if (!isset($_SESSION['old_url'])) { redirectexit('action=register'); } // Check their provider deatils match up correctly in case they're pulling something funny if ($_POST['provider'] != $_SESSION['extauth_info']['provider']) { redirectexit('action=register'); } // Clean up foreach ($_POST as $key => $value) { if (!is_array($_POST[$key])) { $_POST[$key] = htmltrim__recursive(str_replace(array("\n", "\r"), '', $_POST[$key])); } } // Needed for isReservedName() and registerMember() require_once SUBSDIR . '/Members.subs.php'; // Needed for generateValidationCode() require_once SUBSDIR . '/Auth.subs.php'; // Set the options needed for registration. $regOptions = array('interface' => 'guest', 'username' => !empty($_POST['user']) ? $_POST['user'] : '', 'email' => !empty($_POST['email']) ? $_POST['email'] : '', 'check_reserved_name' => true, 'check_password_strength' => true, 'check_email_ban' => true, 'send_welcome_email' => !empty($modSettings['send_welcomeEmail']), 'require' => empty($modSettings['registration_method']) ? 'nothing' : ($modSettings['registration_method'] == 1 ? 'activation' : 'approval')); // Lets check for other errors before trying to register the member. if ($reg_errors->hasErrors()) { return $this->action_register(); } mt_srand(time() + 1277); $regOptions['password'] = generateValidationCode(); $regOptions['password_check'] = $regOptions['password']; // 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'); } } // One last error check if ($reg_errors->hasErrors()) { return $this->action_register(); } // Do our spam protection now. spamProtection('register'); // Since all is well, we'll go ahead and associate the member's external account addAuth($memberID, $_SESSION['extauth_info']['provider'], $_SESSION['extauth_info']['uid'], $_SESSION['extauth_info']['name']); // Basic template variable setup. if (!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']); } }
/** * Add an error * * @param string $error error code * @param string|null $lang_file = null */ public function addError($error, $lang_file = null) { if (empty($error)) { return; } if ($this->_active_attach == 'generic') { if (!isset($this->_attachs[$this->_active_attach])) { $this->_generic_error = Error_Context::context('attach_generic_error', 1); } $this->_generic_error->addError($error, $lang_file); return; } $this->_attachs[$this->_active_attach]['error']->addError($error, $lang_file); }
/** * Does the actual saving of the page data * * - validates the data is safe to save * - updates existing pages or creates new ones */ private function _sportal_admin_page_edit_save() { global $txt, $context, $modSettings; // No errors, yet. $pages_errors = Error_Context::context('pages', 0); // Use our standard validation functions in a few spots require_once SUBSDIR . '/DataValidator.class.php'; $validator = new Data_Validator(); // Clean and Review the post data for compliance $validator->sanitation_rules(array('title' => 'trim|Util::htmlspecialchars', 'namespace' => 'trim|Util::htmlspecialchars', 'permissions' => 'intval', 'type' => 'trim', 'content' => 'trim')); $validator->validation_rules(array('title' => 'required', 'namespace' => 'alpha_numeric|required', 'type' => 'required', 'content' => 'required')); $validator->text_replacements(array('title' => $txt['sp_error_page_name_empty'], 'namespace' => $txt['sp_error_page_namespace_empty'], 'content' => $txt['sp_admin_pages_col_body'])); // If you messed this up, back you go if (!$validator->validate($_POST)) { foreach ($validator->validation_errors() as $id => $error) { $pages_errors->addError($error); } $this->action_sportal_admin_page_edit(); } // Can't have the same name in the same space twice $has_duplicate = sp_check_duplicate_pages($_POST['namespace'], $_POST['page_id']); if (!empty($has_duplicate)) { $pages_errors->addError('sp_error_page_namespace_duplicate'); } // Can't have a simple numeric namespace if (preg_replace('~[0-9]+~', '', $_POST['namespace']) === '') { $pages_errors->addError('sp_error_page_namespace_numeric'); } if ($_POST['type'] === 'php' && !allowedTo('admin_forum')) { fatal_lang_error('cannot_admin_forum', false); } // Running some php code, then we need to validate its legit code if ($_POST['type'] === 'php' && !empty($_POST['content']) && empty($modSettings['sp_disable_php_validation'])) { $validator_php = new Data_Validator(); $validator_php->validation_rules(array('content' => 'php_syntax')); // Bad PHP code if (!$validator_php->validate(array('content' => $_POST['content']))) { $pages_errors->addError($validator_php->validation_errors()); } } // None shall pass ... with errors if ($pages_errors->hasErrors()) { $this->action_sportal_admin_page_edit(); } // If you made it this far, we are going to save the work if (!empty($_POST['blocks']) && is_array($_POST['blocks'])) { foreach ($_POST['blocks'] as $id => $block) { $_POST['blocks'][$id] = (int) $block; } } else { $_POST['blocks'] = array(); } // The data for the fields $page_info = array('id' => (int) $_POST['page_id'], 'namespace' => Util::htmlspecialchars($_POST['namespace'], ENT_QUOTES), 'title' => Util::htmlspecialchars($_POST['title'], ENT_QUOTES), 'body' => Util::htmlspecialchars($_POST['content'], ENT_QUOTES), 'type' => in_array($_POST['type'], array('bbc', 'html', 'php')) ? $_POST['type'] : 'bbc', 'permissions' => (int) $_POST['permissions'], 'style' => sportal_parse_style('implode'), 'status' => !empty($_POST['status']) ? 1 : 0); if ($page_info['type'] === 'bbc') { preparsecode($page_info['body']); } // Save away sp_save_page($page_info, $context['SPortal']['is_new']); $to_show = array(); $not_to_show = array(); $changes = array(); foreach ($context['page_blocks'] as $page_blocks) { foreach ($page_blocks as $block) { if ($block['shown'] && !in_array($block['id'], $_POST['blocks'])) { $not_to_show[] = $block['id']; } elseif (!$block['shown'] && in_array($block['id'], $_POST['blocks'])) { $to_show[] = $block['id']; } } } foreach ($to_show as $id) { if (empty($this->blocks[$id]['display']) && empty($this->blocks[$id]['display_custom']) || $this->blocks[$id]['display'] == 'sportal') { $changes[$id] = array('display' => 'portal,p' . $page_info['id'], 'display_custom' => ''); } elseif (in_array($this->blocks[$id]['display'], array('allaction', 'allboard'))) { $changes[$id] = array('display' => '', 'display_custom' => $this->blocks[$id]['display'] . ',p' . $page_info['id']); } elseif (in_array('-p' . $page_info['id'], explode(',', $this->blocks[$id]['display_custom']))) { $changes[$id] = array('display' => $this->blocks[$id]['display'], 'display_custom' => implode(',', array_diff(explode(',', $this->blocks[$id]['display_custom']), array('-p' . $page_info['id'])))); } elseif (empty($this->blocks[$id]['display_custom'])) { $changes[$id] = array('display' => implode(',', array_merge(explode(',', $this->blocks[$id]['display']), array('p' . $page_info['id']))), 'display_custom' => ''); } else { $changes[$id] = array('display' => $this->blocks[$id]['display'], 'display_custom' => implode(',', array_merge(explode(',', $this->blocks[$id]['display_custom']), array('p' . $page_info['id'])))); } } foreach ($not_to_show as $id) { if (count(array_intersect(array($this->blocks[$id]['display'], $this->blocks[$id]['display_custom']), array('sforum', 'allpages', 'all'))) > 0) { $changes[$id] = array('display' => '', 'display_custom' => $this->blocks[$id]['display'] . $this->blocks[$id]['display_custom'] . ',-p' . $page_info['id']); } elseif (empty($this->blocks[$id]['display_custom'])) { $changes[$id] = array('display' => implode(',', array_diff(explode(',', $this->blocks[$id]['display']), array('p' . $page_info['id']))), 'display_custom' => ''); } else { $changes[$id] = array('display' => implode(',', array_diff(explode(',', $this->blocks[$id]['display']), array('p' . $page_info['id']))), 'display_custom' => implode(',', array_diff(explode(',', $this->blocks[$id]['display_custom']), array('p' . $page_info['id'])))); } } // Update the blocks as needed foreach ($changes as $id => $data) { sp_update_block_visibility($id, $data); } redirectexit('action=admin;area=portalpages'); return true; }
/** * This function allows the admin to register a new member by hand. * * - It also allows assigning a primary group to the member being registered. * - Accessed by ?action=admin;area=regcenter;sa=register * - Requires the moderate_forum permission. * * @uses Register template, admin_register sub-template. */ public function action_register() { global $txt, $context, $scripturl, $user_info; if (!empty($_POST['regSubmit'])) { checkSession(); validateToken('admin-regc'); foreach ($_POST as $key => $dummy) { if (!is_array($_POST[$key])) { $_POST[$key] = htmltrim__recursive(str_replace(array("\n", "\r"), '', $_POST[$key])); } } $regOptions = array('interface' => 'admin', 'username' => $_POST['user'], 'email' => $_POST['email'], 'password' => $_POST['password'], 'password_check' => $_POST['password'], 'check_reserved_name' => true, 'check_password_strength' => true, 'check_email_ban' => false, 'send_welcome_email' => isset($_POST['emailPassword']) || empty($_POST['password']), 'require' => isset($_POST['emailActivate']) ? 'activation' : 'nothing', 'memberGroup' => empty($_POST['group']) || !allowedTo('manage_membergroups') ? 0 : (int) $_POST['group']); require_once SUBSDIR . '/Members.subs.php'; $reg_errors = Error_Context::context('register', 0); $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 $error_severity = $reg_errors->hasErrors(1) && !$user_info['is_admin'] ? 1 : null; foreach ($reg_errors->prepareErrors($error_severity) as $error) { fatal_error($error, $error_severity === null ? false : 'general'); } if (!empty($memberID)) { $context['new_member'] = array('id' => $memberID, 'name' => $_POST['user'], 'href' => $scripturl . '?action=profile;u=' . $memberID, 'link' => '<a href="' . $scripturl . '?action=profile;u=' . $memberID . '">' . $_POST['user'] . '</a>'); $context['registration_done'] = sprintf($txt['admin_register_done'], $context['new_member']['link']); } } // Load the assignable member groups. if (allowedTo('manage_membergroups')) { require_once SUBSDIR . '/Membergroups.subs.php'; if (allowedTo('admin_forum')) { $includes = array('admin', 'globalmod', 'member'); } else { $includes = array('globalmod', 'member', 'custom'); } $groups = array(); $membergroups = getBasicMembergroupData($includes, array('hidden', 'protected')); foreach ($membergroups as $membergroup) { $groups[$membergroup['id']] = $membergroup['name']; } $context['member_groups'] = $groups; } else { $context['member_groups'] = array(); } // Basic stuff. addInlineJavascript('disableAutoComplete();', true); $context['sub_template'] = 'admin_register'; $context['page_title'] = $txt['registration_center']; createToken('admin-regc'); }