/** * Verify the activation code, and activate the user if correct. * Accessed by ?action=activate */ public function action_activate() { global $context, $txt, $modSettings, $scripturl, $language, $user_info; require_once SUBSDIR . '/Auth.subs.php'; // Logged in users should not bother to activate their accounts if (!empty($user_info['id'])) { redirectexit(); } loadLanguage('Login'); loadTemplate('Login'); loadJavascriptFile('sha256.js', array('defer' => true)); if (empty($_REQUEST['u']) && empty($_POST['user'])) { if (empty($modSettings['registration_method']) || $modSettings['registration_method'] == '3') { fatal_lang_error('no_access', false); } $context['member_id'] = 0; $context['sub_template'] = 'resend'; $context['page_title'] = $txt['invalid_activation_resend']; $context['can_activate'] = empty($modSettings['registration_method']) || $modSettings['registration_method'] == '1'; $context['default_username'] = isset($_GET['user']) ? $_GET['user'] : ''; return; } // Get the code from the database... $row = findUser(empty($_REQUEST['u']) ? ' member_name = {string:email_address} OR email_address = {string:email_address}' : ' id_member = {int:id_member}', array('id_member' => isset($_REQUEST['u']) ? (int) $_REQUEST['u'] : 0, 'email_address' => isset($_POST['user']) ? $_POST['user'] : ''), false); // Does this user exist at all? if (empty($row)) { $context['sub_template'] = 'retry_activate'; $context['page_title'] = $txt['invalid_userid']; $context['member_id'] = 0; return; } // Change their email address? (they probably tried a fake one first :P.) require_once SUBSDIR . '/Auth.subs.php'; if (isset($_POST['new_email'], $_REQUEST['passwd']) && validateLoginPassword($_REQUEST['passwd'], $row['passwd'], $row['member_name'], true) && ($row['is_activated'] == 0 || $row['is_activated'] == 2)) { if (empty($modSettings['registration_method']) || $modSettings['registration_method'] == 3) { fatal_lang_error('no_access', false); } // @todo Separate the sprintf? require_once SUBSDIR . '/DataValidator.class.php'; if (!Data_Validator::is_valid($_POST, array('new_email' => 'valid_email|required|max_length[255]'), array('new_email' => 'trim'))) { fatal_error(sprintf($txt['valid_email_needed'], htmlspecialchars($_POST['new_email'], ENT_COMPAT, 'UTF-8')), false); } // Make sure their email isn't banned. isBannedEmail($_POST['new_email'], 'cannot_register', $txt['ban_register_prohibited']); // Ummm... don't even dare try to take someone else's email!! // @todo Separate the sprintf? if (userByEmail($_POST['new_email'])) { fatal_lang_error('email_in_use', false, array(htmlspecialchars($_POST['new_email'], ENT_COMPAT, 'UTF-8'))); } updateMemberData($row['id_member'], array('email_address' => $_POST['new_email'])); $row['email_address'] = $_POST['new_email']; $email_change = true; } // Resend the password, but only if the account wasn't activated yet. if (!empty($_REQUEST['sa']) && $_REQUEST['sa'] == 'resend' && ($row['is_activated'] == 0 || $row['is_activated'] == 2) && (!isset($_REQUEST['code']) || $_REQUEST['code'] == '')) { require_once SUBSDIR . '/Mail.subs.php'; $replacements = array('REALNAME' => $row['real_name'], 'USERNAME' => $row['member_name'], 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $row['id_member'] . ';code=' . $row['validation_code'], 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $row['id_member'], 'ACTIVATIONCODE' => $row['validation_code'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder'); $emaildata = loadEmailTemplate('resend_activate_message', $replacements, empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']); sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); $context['page_title'] = $txt['invalid_activation_resend']; // This will ensure we don't actually get an error message if it works! $context['error_title'] = ''; fatal_lang_error(!empty($email_change) ? 'change_email_success' : 'resend_email_success', false); } // Quit if this code is not right. if (empty($_REQUEST['code']) || $row['validation_code'] != $_REQUEST['code']) { if (!empty($row['is_activated'])) { fatal_lang_error('already_activated', false); } elseif ($row['validation_code'] == '') { loadLanguage('Profile'); fatal_error($txt['registration_not_approved'] . ' <a href="' . $scripturl . '?action=activate;user='******'member_name'] . '">' . $txt['here'] . '</a>.', false); } $context['sub_template'] = 'retry_activate'; $context['page_title'] = $txt['invalid_activation_code']; $context['member_id'] = $row['id_member']; return; } // Let the integration know that they've been activated! call_integration_hook('integrate_activate', array($row['member_name'])); // Validation complete - update the database! updateMemberData($row['id_member'], array('is_activated' => 1, 'validation_code' => '')); // Also do a proper member stat re-evaluation. updateStats('member', false); if (!isset($_POST['new_email'])) { require_once SUBSDIR . '/Notification.subs.php'; sendAdminNotifications('activation', $row['id_member'], $row['member_name']); } $context += array('page_title' => $txt['registration_successful'], 'sub_template' => 'login', 'default_username' => $row['member_name'], 'default_password' => '', 'never_expire' => false, 'description' => $txt['activate_success']); }
function notifyMembersBoard(&$topicData) { global $txt, $scripturl, $language, $user_info; global $modSettings, $sourcedir, $board, $smcFunc, $context; require_once $sourcedir . '/Subs-Post.php'; // Do we have one or lots of topics? if (isset($topicData['body'])) { $topicData = array($topicData); } // Find out what boards we have... and clear out any rubbish! $boards = array(); foreach ($topicData as $key => $topic) { if (!empty($topic['board'])) { $boards[$topic['board']][] = $key; } else { unset($topic[$key]); continue; } // Censor the subject and body... censorText($topicData[$key]['subject']); censorText($topicData[$key]['body']); $topicData[$key]['subject'] = un_htmlspecialchars($topicData[$key]['subject']); $topicData[$key]['body'] = trim(un_htmlspecialchars(strip_tags(strtr(parse_bbc($topicData[$key]['body'], false), array('<br />' => "\n", '</div>' => "\n", '</li>' => "\n", '[' => '[', ']' => ']'))))); } // Just the board numbers. $board_index = array_unique(array_keys($boards)); if (empty($board_index)) { return; } // Yea, we need to add this to the digest queue. $digest_insert = array(); foreach ($topicData as $id => $data) { $digest_insert[] = array($data['topic'], $data['msg'], 'topic', $user_info['id']); } $smcFunc['db_insert']('', '{db_prefix}log_digest', array('id_topic' => 'int', 'id_msg' => 'int', 'note_type' => 'string', 'exclude' => 'int'), $digest_insert, array()); // Find the members with notification on for these boards. $members = $smcFunc['db_query']('', ' SELECT mem.id_member, mem.email_address, mem.notify_regularity, mem.notify_send_body, mem.lngfile, ln.sent, ln.id_board, mem.id_group, mem.additional_groups, b.member_groups, mem.id_post_group FROM {db_prefix}log_notify AS ln INNER JOIN {db_prefix}boards AS b ON (b.id_board = ln.id_board) INNER JOIN {db_prefix}members AS mem ON (mem.id_member = ln.id_member) WHERE ln.id_board IN ({array_int:board_list}) AND mem.id_member != {int:current_member} AND mem.is_activated = {int:is_activated} AND mem.notify_types != {int:notify_types} AND mem.notify_regularity < {int:notify_regularity} ORDER BY mem.lngfile', array('current_member' => $user_info['id'], 'board_list' => $board_index, 'is_activated' => 1, 'notify_types' => 4, 'notify_regularity' => 2)); while ($rowmember = $smcFunc['db_fetch_assoc']($members)) { if ($rowmember['id_group'] != 1) { $allowed = explode(',', $rowmember['member_groups']); $rowmember['additional_groups'] = explode(',', $rowmember['additional_groups']); $rowmember['additional_groups'][] = $rowmember['id_group']; $rowmember['additional_groups'][] = $rowmember['id_post_group']; if (count(array_intersect($allowed, $rowmember['additional_groups'])) == 0) { continue; } } $langloaded = loadLanguage('EmailTemplates', empty($rowmember['lngfile']) || empty($modSettings['userLanguage']) ? $language : $rowmember['lngfile'], false); // Now loop through all the notifications to send for this board. if (empty($boards[$rowmember['id_board']])) { continue; } $sentOnceAlready = 0; foreach ($boards[$rowmember['id_board']] as $key) { // Don't notify the guy who started the topic! //!!! In this case actually send them a "it's approved hooray" email if ($topicData[$key]['poster'] == $rowmember['id_member']) { continue; } // Setup the string for adding the body to the message, if a user wants it. $send_body = empty($modSettings['disallow_sendBody']) && !empty($rowmember['notify_send_body']); $replacements = array('TOPICSUBJECT' => $topicData[$key]['subject'], 'TOPICLINK' => $scripturl . '?topic=' . $topicData[$key]['topic'] . '.new#new', 'MESSAGE' => $topicData[$key]['body'], 'UNSUBSCRIBELINK' => $scripturl . '?action=notifyboard;board=' . $topicData[$key]['board'] . '.0'); if (!$send_body) { unset($replacements['MESSAGE']); } // Figure out which email to send off $emailtype = ''; // Send only if once is off or it's on and it hasn't been sent. if (!empty($rowmember['notify_regularity']) && !$sentOnceAlready && empty($rowmember['sent'])) { $emailtype = 'notify_boards_once'; } elseif (empty($rowmember['notify_regularity'])) { $emailtype = 'notify_boards'; } if (!empty($emailtype)) { $emailtype .= $send_body ? '_body' : ''; $emaildata = loadEmailTemplate($emailtype, $replacements, $langloaded); sendmail($rowmember['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 3); } $sentOnceAlready = 1; } } $smcFunc['db_free_result']($members); // Sent! $smcFunc['db_query']('', ' UPDATE {db_prefix}log_notify SET sent = {int:is_sent} WHERE id_board IN ({array_int:board_list}) AND id_member != {int:current_member}', array('current_member' => $user_info['id'], 'board_list' => $board_index, 'is_sent' => 1)); }
function Activate() { global $context, $txt, $modSettings, $scripturl, $sourcedir, $language; loadLanguage('Login'); //loadTemplate('Login'); if (empty($_REQUEST['u']) && empty($_POST['user'])) { if (empty($modSettings['registration_method']) || $modSettings['registration_method'] == 3) { fatal_lang_error('no_access', false); } $context['member_id'] = 0; EoS_Smarty::loadTemplate('generic_skeleton'); EoS_Smarty::getConfigInstance()->registerHookTemplate('generic_content_area', 'loginout/resend'); $context['page_title'] = $txt['invalid_activation_resend']; $context['can_activate'] = empty($modSettings['registration_method']) || $modSettings['registration_method'] == 1; $context['default_username'] = isset($_GET['user']) ? $_GET['user'] : ''; return; } // Get the code from the database... $request = smf_db_query(' SELECT id_member, validation_code, member_name, real_name, email_address, is_activated, passwd, lngfile FROM {db_prefix}members' . (empty($_REQUEST['u']) ? ' WHERE member_name = {string:email_address} OR email_address = {string:email_address}' : ' WHERE id_member = {int:id_member}') . ' LIMIT 1', array('id_member' => isset($_REQUEST['u']) ? (int) $_REQUEST['u'] : 0, 'email_address' => isset($_POST['user']) ? $_POST['user'] : '')); // Does this user exist at all? if (mysql_num_rows($request) == 0) { EoS_Smarty::loadTemplate('generic_skeleton'); EoS_Smarty::getConfigInstance()->registerHookTemplate('generic_content_area', 'loginout/retry_activate'); $context['page_title'] = $txt['invalid_userid']; $context['member_id'] = 0; return; } $row = mysql_fetch_assoc($request); mysql_free_result($request); // Change their email address? (they probably tried a fake one first :P.) if (isset($_POST['new_email'], $_REQUEST['passwd']) && sha1(strtolower($row['member_name']) . $_REQUEST['passwd']) == $row['passwd']) { if (empty($modSettings['registration_method']) || $modSettings['registration_method'] == 3) { fatal_lang_error('no_access', false); } // !!! Separate the sprintf? if (preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', $_POST['new_email']) == 0) { fatal_error(sprintf($txt['valid_email_needed'], htmlspecialchars($_POST['new_email'])), false); } // Make sure their email isn't banned. isBannedEmail($_POST['new_email'], 'cannot_register', $txt['ban_register_prohibited']); // Ummm... don't even dare try to take someone else's email!! $request = smf_db_query(' SELECT id_member FROM {db_prefix}members WHERE email_address = {string:email_address} LIMIT 1', array('email_address' => $_POST['new_email'])); // !!! Separate the sprintf? if (mysql_num_rows($request) != 0) { fatal_lang_error('email_in_use', false, array(htmlspecialchars($_POST['new_email']))); } mysql_free_result($request); updateMemberData($row['id_member'], array('email_address' => $_POST['new_email'])); $row['email_address'] = $_POST['new_email']; $email_change = true; } // Resend the password, but only if the account wasn't activated yet. if (!empty($_REQUEST['sa']) && $_REQUEST['sa'] == 'resend' && ($row['is_activated'] == 0 || $row['is_activated'] == 2) && (!isset($_REQUEST['code']) || $_REQUEST['code'] == '')) { require_once $sourcedir . '/lib/Subs-Post.php'; $replacements = array('REALNAME' => $row['real_name'], 'USERNAME' => $row['member_name'], 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $row['id_member'] . ';code=' . $row['validation_code'], 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $row['id_member'], 'ACTIVATIONCODE' => $row['validation_code'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder'); $emaildata = loadEmailTemplate('resend_activate_message', $replacements, empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']); sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); $context['page_title'] = $txt['invalid_activation_resend']; // This will ensure we don't actually get an error message if it works! $context['error_title'] = ''; fatal_lang_error(!empty($email_change) ? 'change_email_success' : 'resend_email_success', false); } // Quit if this code is not right. if (empty($_REQUEST['code']) || $row['validation_code'] != $_REQUEST['code']) { if (!empty($row['is_activated'])) { fatal_lang_error('already_activated', false); } elseif ($row['validation_code'] == '') { loadLanguage('Profile'); fatal_error($txt['registration_not_approved'] . ' <a href="' . $scripturl . '?action=activate;user='******'member_name'] . '">' . $txt['here'] . '</a>.', false); } EoS_Smarty::loadTemplate('generic_skeleton'); EoS_Smarty::getConfigInstance()->registerHookTemplate('generic_content_area', 'loginout/retry_activate'); $context['page_title'] = $txt['invalid_activation_code']; $context['member_id'] = $row['id_member']; return; } // Let the integration know that they've been activated! HookAPI::callHook('integrate_activate', array($row['member_name'])); // Validation complete - update the database! updateMemberData($row['id_member'], array('is_activated' => 1, 'validation_code' => '')); // Also do a proper member stat re-evaluation. updateStats('member', false); if (!isset($_POST['new_email'])) { $actid = 0; require_once $sourcedir . '/lib/Subs-Post.php'; // add to the activity stream if ($modSettings['astream_active']) { require_once $sourcedir . '/lib/Subs-Activities.php'; $actid = aStreamAdd($row['id_member'], ACT_NEWMEMBER, array('member_name' => $row['member_name']), 0, 0, 0, $row['id_member']); } adminNotify('activation', $row['id_member'], $row['member_name'], $actid, ACT_NEWMEMBER); } EoS_Smarty::loadTemplate('generic_skeleton'); EoS_Smarty::getConfigInstance()->registerHookTemplate('generic_content_area', 'loginout/login'); $context += array('page_title' => $txt['registration_successful'], 'sub_template' => 'login', 'default_username' => $row['member_name'], 'default_password' => '', 'never_expire' => false, 'description' => $txt['activate_success']); }
function ReportToModerator2() { global $txt, $scripturl, $topic, $board, $user_info, $modSettings, $sourcedir, $language, $context, $smcFunc; // You must have the proper permissions! isAllowedTo('report_any'); // Make sure they aren't spamming. spamProtection('reporttm'); require_once $sourcedir . '/Subs-Post.php'; // No errors, yet. $post_errors = array(); // Check their session. if (checkSession('post', '', false) != '') { $post_errors[] = 'session_timeout'; } // Make sure we have a comment and it's clean. if (!isset($_POST['comment']) || $smcFunc['htmltrim']($_POST['comment']) === '') { $post_errors[] = 'no_comment'; } $poster_comment = strtr($smcFunc['htmlspecialchars']($_POST['comment']), array("\r" => '', "\n" => '', "\t" => '')); // Guests need to provide their address! if ($user_info['is_guest']) { $_POST['email'] = !isset($_POST['email']) ? '' : trim($_POST['email']); if ($_POST['email'] === '') { $post_errors[] = 'no_email'; } elseif (preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', $_POST['email']) == 0) { $post_errors[] = 'bad_email'; } isBannedEmail($_POST['email'], 'cannot_post', sprintf($txt['you_are_post_banned'], $txt['guest_title'])); $user_info['email'] = htmlspecialchars($_POST['email']); } // Could they get the right verification code? if ($user_info['is_guest'] && !empty($modSettings['guests_report_require_captcha'])) { require_once $sourcedir . '/Subs-Editor.php'; $verificationOptions = array('id' => 'report'); $context['require_verification'] = create_control_verification($verificationOptions, true); if (is_array($context['require_verification'])) { $post_errors = array_merge($post_errors, $context['require_verification']); } } // Any errors? if (!empty($post_errors)) { loadLanguage('Errors'); $context['post_errors'] = array(); foreach ($post_errors as $post_error) { $context['post_errors'][] = $txt['error_' . $post_error]; } return ReportToModerator(); } // Get the basic topic information, and make sure they can see it. $_POST['msg'] = (int) $_POST['msg']; $request = $smcFunc['db_query']('', ' SELECT m.id_topic, m.id_board, m.subject, m.body, m.id_member AS id_poster, m.poster_name, mem.real_name FROM {db_prefix}messages AS m LEFT JOIN {db_prefix}members AS mem ON (m.id_member = mem.id_member) WHERE m.id_msg = {int:id_msg} AND m.id_topic = {int:current_topic} LIMIT 1', array('current_topic' => $topic, 'id_msg' => $_POST['msg'])); if ($smcFunc['db_num_rows']($request) == 0) { fatal_lang_error('no_board', false); } $message = $smcFunc['db_fetch_assoc']($request); $smcFunc['db_free_result']($request); $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 $sourcedir . '/Subs-Members.php'; $moderators = membersAllowedTo('moderate_board', $board); $request = $smcFunc['db_query']('', ' SELECT id_member, email_address, lngfile, mod_prefs FROM {db_prefix}members WHERE id_member IN ({array_int:moderator_list}) AND notify_types != {int:notify_types} ORDER BY lngfile', array('moderator_list' => $moderators, 'notify_types' => 4)); // Check that moderators do exist! if ($smcFunc['db_num_rows']($request) == 0) { 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'])) { $request2 = $smcFunc['db_query']('', ' SELECT id_report, ignore_all FROM {db_prefix}log_reported WHERE id_msg = {int:id_msg} AND (closed = {int:not_closed} OR ignore_all = {int:ignored}) ORDER BY ignore_all DESC', array('id_msg' => $_POST['msg'], 'not_closed' => 0, 'ignored' => 1)); if ($smcFunc['db_num_rows']($request2) != 0) { list($id_report, $ignore) = $smcFunc['db_fetch_row']($request2); } $smcFunc['db_free_result']($request2); // If we're just going to ignore these, then who gives a monkeys... if (!empty($ignore)) { redirectexit('topic=' . $topic . '.msg' . $_POST['msg'] . '#msg' . $_POST['msg']); } // Already reported? My god, we could be dealing with a real rogue here... if (!empty($id_report)) { $smcFunc['db_query']('', ' UPDATE {db_prefix}log_reported SET num_reports = num_reports + 1, time_updated = {int:current_time} WHERE id_report = {int:id_report}', array('current_time' => time(), 'id_report' => $id_report)); } else { if (empty($message['real_name'])) { $message['real_name'] = $message['poster_name']; } $smcFunc['db_insert']('', '{db_prefix}log_reported', array('id_msg' => 'int', 'id_topic' => 'int', 'id_board' => 'int', 'id_member' => 'int', 'membername' => 'string', 'subject' => 'string', 'body' => 'string', 'time_started' => 'int', 'time_updated' => 'int', 'num_reports' => 'int', 'closed' => 'int'), array($_POST['msg'], $message['id_topic'], $message['id_board'], $message['id_poster'], $message['real_name'], $message['subject'], $message['body'], time(), time(), 1, 0), array('id_report')); $id_report = $smcFunc['db_insert_id']('{db_prefix}log_reported', 'id_report'); } // Now just add our report... if ($id_report) { $smcFunc['db_insert']('', '{db_prefix}log_reported_comments', array('id_report' => 'int', 'id_member' => 'int', 'membername' => 'string', 'email_address' => 'string', 'member_ip' => 'string', 'comment' => 'string', 'time_sent' => 'int'), array($id_report, $user_info['id'], $user_info['name'], $user_info['email'], $user_info['ip'], $poster_comment, time()), array('id_comment')); } } // Find out who the real moderators are - for mod preferences. $request2 = $smcFunc['db_query']('', ' SELECT id_member FROM {db_prefix}moderators WHERE id_board = {int:current_board}', array('current_board' => $board)); $real_mods = array(); while ($row = $smcFunc['db_fetch_assoc']($request2)) { $real_mods[] = $row['id_member']; } $smcFunc['db_free_result']($request2); // Send every moderator an email. while ($row = $smcFunc['db_fetch_assoc']($request)) { // 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' . $_POST['msg'] . '#msg' . $_POST['msg'], '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); } $smcFunc['db_free_result']($request); // 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' . $_POST['msg'] . '#msg' . $_POST['msg']); }
/** * Show and manage all group requests. */ public function action_requests() { global $txt, $context, $scripturl, $user_info, $modSettings; // Set up the template stuff... $context['page_title'] = $txt['mc_group_requests']; $context['sub_template'] = 'show_list'; $context[$context['moderation_menu_name']]['tab_data'] = array('title' => $txt['mc_group_requests']); // Verify we can be here. if ($user_info['mod_cache']['gq'] == '0=1') { isAllowedTo('manage_membergroups'); } // Normally, we act normally... $where = $user_info['mod_cache']['gq'] == '1=1' || $user_info['mod_cache']['gq'] == '0=1' ? $user_info['mod_cache']['gq'] : 'lgr.' . $user_info['mod_cache']['gq']; $where_parameters = array(); // We've submitted? if (isset($_POST[$context['session_var']]) && !empty($_POST['groupr']) && !empty($_POST['req_action'])) { checkSession('post'); validateToken('mod-gr'); require_once SUBSDIR . '/Membergroups.subs.php'; // Clean the values. foreach ($_POST['groupr'] as $k => $request) { $_POST['groupr'][$k] = (int) $request; } // If we are giving a reason (And why shouldn't we?), then we don't actually do much. if ($_POST['req_action'] == 'reason') { // Different sub template... $context['sub_template'] = 'group_request_reason'; // And a limitation. We don't care that the page number bit makes no sense, as we don't need it! $where .= ' AND lgr.id_request IN ({array_int:request_ids})'; $where_parameters['request_ids'] = $_POST['groupr']; $context['group_requests'] = list_getGroupRequests(0, $modSettings['defaultMaxMessages'], 'lgr.id_request', $where, $where_parameters); createToken('mod-gr'); // Let obExit etc sort things out. obExit(); } else { // Get the details of all the members concerned... require_once SUBSDIR . '/Members.subs.php'; $concerned = getConcernedMembers($_POST['groupr'], $where); // Cleanup old group requests.. deleteGroupRequests($_POST['groupr']); // Ensure everyone who is online gets their changes right away. updateSettings(array('settings_updated' => time())); if (!empty($concerned['email_details'])) { require_once SUBSDIR . '/Mail.subs.php'; // They are being approved? if ($_POST['req_action'] == 'approve') { // Make the group changes. foreach ($concerned['group_changes'] as $id => $groups) { // Sanity check! foreach ($groups['add'] as $key => $value) { if ($value == 0 || trim($value) == '') { unset($groups['add'][$key]); } } assignGroupsToMember($id, $groups['primary'], $groups['add']); } foreach ($concerned['email_details'] as $email) { $replacements = array('USERNAME' => $email['member_name'], 'GROUPNAME' => $email['group_name']); $emaildata = loadEmailTemplate('mc_group_approve', $replacements, $email['language']); sendmail($email['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 2); } } else { // Same as for approving, kind of. foreach ($concerned['email_details'] as $email) { $custom_reason = isset($_POST['groupreason']) && isset($_POST['groupreason'][$email['rid']]) ? $_POST['groupreason'][$email['rid']] : ''; $replacements = array('USERNAME' => $email['member_name'], 'GROUPNAME' => $email['group_name']); if (!empty($custom_reason)) { $replacements['REASON'] = $custom_reason; } $emaildata = loadEmailTemplate(empty($custom_reason) ? 'mc_group_reject' : 'mc_group_reject_reason', $replacements, $email['language']); sendmail($email['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 2); } } } // Restore the current language. loadLanguage('ModerationCenter'); } } // We're going to want this for making our list. require_once SUBSDIR . '/GenericList.class.php'; require_once SUBSDIR . '/Membergroups.subs.php'; // This is all the information required for a group listing. $listOptions = array('id' => 'group_request_list', 'width' => '100%', 'items_per_page' => $modSettings['defaultMaxMessages'], 'no_items_label' => $txt['mc_groupr_none_found'], 'base_href' => $scripturl . '?action=groups;sa=requests', 'default_sort_col' => 'member', 'get_items' => array('function' => 'list_getGroupRequests', 'params' => array($where, $where_parameters)), 'get_count' => array('function' => 'list_getGroupRequestCount', 'params' => array($where, $where_parameters)), 'columns' => array('member' => array('header' => array('value' => $txt['mc_groupr_member']), 'data' => array('db' => 'member_link'), 'sort' => array('default' => 'mem.member_name', 'reverse' => 'mem.member_name DESC')), 'group' => array('header' => array('value' => $txt['mc_groupr_group']), 'data' => array('db' => 'group_link'), 'sort' => array('default' => 'mg.group_name', 'reverse' => 'mg.group_name DESC')), 'reason' => array('header' => array('value' => $txt['mc_groupr_reason']), 'data' => array('db' => 'reason')), 'date' => array('header' => array('value' => $txt['date'], 'style' => 'width: 18%; white-space:nowrap;'), 'data' => array('db' => 'time_submitted')), 'action' => array('header' => array('value' => '<input type="checkbox" class="input_check" onclick="invertAll(this, this.form);" />', 'style' => 'width: 4%;text-align: center;'), 'data' => array('sprintf' => array('format' => '<input type="checkbox" name="groupr[]" value="%1$d" class="input_check" />', 'params' => array('id' => false)), 'class' => 'centertext'))), 'form' => array('href' => $scripturl . '?action=groups;sa=requests', 'include_sort' => true, 'include_start' => true, 'hidden_fields' => array($context['session_var'] => $context['session_id']), 'token' => 'mod-gr'), 'additional_rows' => array(array('position' => 'bottom_of_list', 'value' => ' <select name="req_action" onchange="if (this.value != 0 && (this.value == \'reason\' || confirm(\'' . $txt['mc_groupr_warning'] . '\'))) this.form.submit();"> <option value="0">' . $txt['with_selected'] . ':</option> <option value="0" disabled="disabled">' . str_repeat('—', strlen($txt['mc_groupr_approve'])) . '</option> <option value="approve">' . (isBrowser('ie8') ? '»' : '➤') . ' ' . $txt['mc_groupr_approve'] . '</option> <option value="reject">' . (isBrowser('ie8') ? '»' : '➤') . ' ' . $txt['mc_groupr_reject'] . '</option> <option value="reason">' . (isBrowser('ie8') ? '»' : '➤') . ' ' . $txt['mc_groupr_reject_w_reason'] . '</option> </select> <input type="submit" name="go" value="' . $txt['go'] . '" onclick="var sel = document.getElementById(\'req_action\'); if (sel.value != 0 && sel.value != \'reason\' && !confirm(\'' . $txt['mc_groupr_warning'] . '\')) return false;" class="right_submit" />', 'class' => 'floatright'))); // Create the request list. createToken('mod-gr'); createList($listOptions); $context['default_list'] = 'group_request_list'; }
/** * Generates a random password for a user and emails it to them. * - called by Profile.php when changing someone's username. * - checks the validity of the new username. * - generates and sets a new password for the given user. * - mails the new password to the email address of the user. * - if username is not set, only a new password is generated and sent. * * @param int $memID * @param string $username = null */ function resetPassword($memID, $username = null) { global $scripturl, $context, $txt, $sourcedir, $modSettings, $smcFunc, $language; // Language... and a required file. loadLanguage('Login'); require_once $sourcedir . '/Subs-Post.php'; // Get some important details. $request = $smcFunc['db_query']('', ' SELECT member_name, email_address, lngfile FROM {db_prefix}members WHERE id_member = {int:id_member}', array('id_member' => $memID)); list($user, $email, $lngfile) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); if ($username !== null) { $old_user = $user; $user = trim($username); } // Generate a random password. $newPassword = substr(preg_replace('/\\W/', '', md5(mt_rand())), 0, 10); $newPassword_sha1 = sha1(strtolower($user) . $newPassword); // Do some checks on the username if needed. if ($username !== null) { validateUsername($memID, $user); // Update the database... updateMemberData($memID, array('member_name' => $user, 'passwd' => $newPassword_sha1)); } else { updateMemberData($memID, array('passwd' => $newPassword_sha1)); } call_integration_hook('integrate_reset_pass', array($old_user, $user, $newPassword)); $replacements = array('USERNAME' => $user, 'PASSWORD' => $newPassword); $emaildata = loadEmailTemplate('change_password', $replacements, empty($lngfile) || empty($modSettings['userLanguage']) ? $language : $lngfile); // Send them the email informing them of the change - then we're done! sendmail($email, $emaildata['subject'], $emaildata['body'], null, null, false, 0); }
function AdminApprove() { global $txt, $context, $scripturl, $modSettings, $sourcedir, $language, $user_info, $smcFunc; // First, check our session. checkSession(); require_once $sourcedir . '/Subs-Post.php'; // We also need to the login languages here - for emails. loadLanguage('Login'); // Sort out where we are going... $browse_type = isset($_REQUEST['type']) ? $_REQUEST['type'] : (!empty($modSettings['registration_method']) && $modSettings['registration_method'] == 1 ? 'activate' : 'approve'); $current_filter = (int) $_REQUEST['orig_filter']; // If we are applying a filter do just that - then redirect. if (isset($_REQUEST['filter']) && $_REQUEST['filter'] != $_REQUEST['orig_filter']) { redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $_REQUEST['filter'] . ';start=' . $_REQUEST['start']); } // Nothing to do? if (!isset($_POST['todoAction']) && !isset($_POST['time_passed'])) { redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $current_filter . ';start=' . $_REQUEST['start']); } // Are we dealing with members who have been waiting for > set amount of time? if (isset($_POST['time_passed'])) { $timeBefore = time() - 86400 * (int) $_POST['time_passed']; $condition = ' AND date_registered < {int:time_before}'; } else { $members = array(); foreach ($_POST['todoAction'] as $id) { $members[] = (int) $id; } $condition = ' AND id_member IN ({array_int:members})'; } // Get information on each of the members, things that are important to us, like email address... $request = $smcFunc['db_query']('', ' SELECT id_member, member_name, real_name, email_address, validation_code, lngfile FROM {db_prefix}members WHERE is_activated = {int:activated_status}' . $condition . ' ORDER BY lngfile', array('activated_status' => $current_filter, 'time_before' => empty($timeBefore) ? 0 : $timeBefore, 'members' => empty($members) ? array() : $members)); $member_count = $smcFunc['db_num_rows']($request); // If no results then just return! if ($member_count == 0) { redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $current_filter . ';start=' . $_REQUEST['start']); } $member_info = array(); $members = array(); // Fill the info array. while ($row = $smcFunc['db_fetch_assoc']($request)) { $members[] = $row['id_member']; $member_info[] = array('id' => $row['id_member'], 'username' => $row['member_name'], 'name' => $row['real_name'], 'email' => $row['email_address'], 'language' => empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile'], 'code' => $row['validation_code']); } $smcFunc['db_free_result']($request); // Are we activating or approving the members? if ($_POST['todo'] == 'ok' || $_POST['todo'] == 'okemail') { // Approve/activate this member. $smcFunc['db_query']('', ' UPDATE {db_prefix}members SET validation_code = {string:blank_string}, is_activated = {int:is_activated} WHERE is_activated = {int:activated_status}' . $condition, array('is_activated' => 1, 'time_before' => empty($timeBefore) ? 0 : $timeBefore, 'members' => empty($members) ? array() : $members, 'activated_status' => $current_filter, 'blank_string' => '')); // Do we have to let the integration code know about the activations? if (!empty($modSettings['integrate_activate'])) { foreach ($member_info as $member) { call_integration_hook('integrate_activate', array($member['username'])); } } // Check for email. if ($_POST['todo'] == 'okemail') { foreach ($member_info as $member) { $replacements = array('NAME' => $member['name'], 'USERNAME' => $member['username'], 'PROFILELINK' => $scripturl . '?action=profile;u=' . $member['id'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder'); $emaildata = loadEmailTemplate('admin_approve_accept', $replacements, $member['language']); sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } } } elseif ($_POST['todo'] == 'require_activation') { require_once $sourcedir . '/Subs-Members.php'; // We have to do this for each member I'm afraid. foreach ($member_info as $member) { // Generate a random activation code. $validation_code = generateValidationCode(); // Set these members for activation - I know this includes two id_member checks but it's safer than bodging $condition ;). $smcFunc['db_query']('', ' UPDATE {db_prefix}members SET validation_code = {string:validation_code}, is_activated = {int:not_activated} WHERE is_activated = {int:activated_status} ' . $condition . ' AND id_member = {int:selected_member}', array('not_activated' => 0, 'activated_status' => $current_filter, 'selected_member' => $member['id'], 'validation_code' => $validation_code, 'time_before' => empty($timeBefore) ? 0 : $timeBefore, 'members' => empty($members) ? array() : $members)); $replacements = array('USERNAME' => $member['name'], 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $member['id'] . ';code=' . $validation_code, 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $member['id'], 'ACTIVATIONCODE' => $validation_code); $emaildata = loadEmailTemplate('admin_approve_activation', $replacements, $member['language']); sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } } elseif ($_POST['todo'] == 'reject' || $_POST['todo'] == 'rejectemail') { require_once $sourcedir . '/Subs-Members.php'; deleteMembers($members); // Send email telling them they aren't welcome? if ($_POST['todo'] == 'rejectemail') { foreach ($member_info as $member) { $replacements = array('USERNAME' => $member['name']); $emaildata = loadEmailTemplate('admin_approve_reject', $replacements, $member['language']); sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 1); } } } elseif ($_POST['todo'] == 'delete' || $_POST['todo'] == 'deleteemail') { require_once $sourcedir . '/Subs-Members.php'; deleteMembers($members); // Send email telling them they aren't welcome? if ($_POST['todo'] == 'deleteemail') { foreach ($member_info as $member) { $replacements = array('USERNAME' => $member['name']); $emaildata = loadEmailTemplate('admin_approve_delete', $replacements, $member['language']); sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 1); } } } elseif ($_POST['todo'] == 'remind') { foreach ($member_info as $member) { $replacements = array('USERNAME' => $member['name'], 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $member['id'] . ';code=' . $member['code'], 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $member['id'], 'ACTIVATIONCODE' => $member['code']); $emaildata = loadEmailTemplate('admin_approve_remind', $replacements, $member['language']); sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 1); } } // Back to the user's language! if (isset($current_language) && $current_language != $user_info['language']) { loadLanguage('index'); loadLanguage('ManageMembers'); } // Log what we did? if (!empty($modSettings['modlog_enabled']) && in_array($_POST['todo'], array('ok', 'okemail', 'require_activation', 'remind'))) { $log_action = $_POST['todo'] == 'remind' ? 'remind_member' : 'approve_member'; $log_inserts = array(); foreach ($member_info as $member) { $log_inserts[] = array(time(), 3, $user_info['id'], $user_info['ip'], $log_action, 0, 0, 0, serialize(array('member' => $member['id']))); } $smcFunc['db_insert']('', '{db_prefix}log_actions', array('log_time' => 'int', 'id_log' => 'int', 'id_member' => 'int', 'ip' => 'string-16', 'action' => 'string', 'id_board' => 'int', 'id_topic' => 'int', 'id_msg' => 'int', 'extra' => 'string-65534'), $log_inserts, array('id_action')); } // Although updateStats *may* catch this, best to do it manually just in case (Doesn't always sort out unapprovedMembers). if (in_array($current_filter, array(3, 4))) { updateSettings(array('unapprovedMembers' => $modSettings['unapprovedMembers'] > $member_count ? $modSettings['unapprovedMembers'] - $member_count : 0)); } // Update the member's stats. (but, we know the member didn't change their name.) updateStats('member', false); // If they haven't been deleted, update the post group statistics on them... if (!in_array($_POST['todo'], array('delete', 'deleteemail', 'reject', 'rejectemail', 'remind'))) { updateStats('postgroups', $members); } redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $current_filter . ';start=' . $_REQUEST['start']); }
function RemindPick() { global $context, $txt, $scripturl, $sourcedir, $user_info, $webmaster_email, $smcFunc, $language, $modSettings; checkSession(); // Coming with a known ID? if (!empty($_REQUEST['uid'])) { $where = 'id_member = {int:id_member}'; $where_params['id_member'] = (int) $_REQUEST['uid']; } elseif (isset($_POST['user']) && $_POST['user'] != '') { $where = 'member_name = {string:member_name}'; $where_params['member_name'] = $_POST['user']; $where_params['email_address'] = $_POST['user']; } // You must enter a username/email address. if (empty($where)) { fatal_lang_error('username_no_exist', false); } // Find the user! $request = $smcFunc['db_query']('', ' SELECT id_member, real_name, member_name, email_address, is_activated, validation_code, lngfile, openid_uri, secret_question FROM {db_prefix}members WHERE ' . $where . ' LIMIT 1', array_merge($where_params, array())); // Maybe email? if ($smcFunc['db_num_rows']($request) == 0 && empty($_REQUEST['uid'])) { $smcFunc['db_free_result']($request); $request = $smcFunc['db_query']('', ' SELECT id_member, real_name, member_name, email_address, is_activated, validation_code, lngfile, openid_uri, secret_question FROM {db_prefix}members WHERE email_address = {string:email_address} LIMIT 1', array_merge($where_params, array())); if ($smcFunc['db_num_rows']($request) == 0) { fatal_lang_error('no_user_with_email', false); } } $row = $smcFunc['db_fetch_assoc']($request); $smcFunc['db_free_result']($request); $context['account_type'] = !empty($row['openid_uri']) ? 'openid' : 'password'; // If the user isn't activated/approved, give them some feedback on what to do next. if ($row['is_activated'] != 1) { // Awaiting approval... if (trim($row['validation_code']) == '') { fatal_error($txt['registration_not_approved'] . ' <a href="' . $scripturl . '?action=activate;user='******'user'] . '">' . $txt['here'] . '</a>.', false); } else { fatal_error($txt['registration_not_activated'] . ' <a href="' . $scripturl . '?action=activate;user='******'user'] . '">' . $txt['here'] . '</a>.', false); } } // You can't get emailed if you have no email address. $row['email_address'] = trim($row['email_address']); if ($row['email_address'] == '') { fatal_error($txt['no_reminder_email'] . '<br />' . $txt['send_email'] . ' <a href="mailto:' . $webmaster_email . '">webmaster</a> ' . $txt['to_ask_password'] . '.'); } // If they have no secret question then they can only get emailed the item, or they are requesting the email, send them an email. if (empty($row['secret_question']) || isset($_POST['reminder_type']) && $_POST['reminder_type'] == 'email') { // Randomly generate a new password, with only alpha numeric characters that is a max length of 10 chars. require_once $sourcedir . '/Subs-Members.php'; $password = generateValidationCode(); require_once $sourcedir . '/Subs-Post.php'; $replacements = array('REALNAME' => $row['real_name'], 'REMINDLINK' => $scripturl . '?action=reminder;sa=setpassword;u=' . $row['id_member'] . ';code=' . $password, 'IP' => $user_info['ip'], 'MEMBERNAME' => $row['member_name'], 'OPENID' => $row['openid_uri']); $emaildata = loadEmailTemplate('forgot_' . $context['account_type'], $replacements, empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']); $context['description'] = $txt['reminder_' . (!empty($row['openid_uri']) ? 'openid_' : '') . 'sent']; // If they were using OpenID simply email them their OpenID identity. sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); if (empty($row['openid_uri'])) { // Set the password in the database. updateMemberData($row['id_member'], array('validation_code' => substr(md5($password), 0, 10))); } // Set up the template. $context['sub_template'] = 'sent'; // Dont really. return; } elseif (isset($_POST['reminder_type']) && $_POST['reminder_type'] == 'secret') { return SecretAnswerInput(); } // No we're here setup the context for template number 2! $context['sub_template'] = 'reminder_pick'; $context['current_member'] = array('id' => $row['id_member'], 'name' => $row['member_name']); }
/** * This function handles the approval, rejection, activation or deletion of members. * * What it does: * - Called by ?action=admin;area=viewmembers;sa=approve. * - Requires the moderate_forum permission. * - Redirects to ?action=admin;area=viewmembers;sa=browse * with the same parameters as the calling page. */ public function action_approve() { global $scripturl, $modSettings; // First, check our session. checkSession(); require_once SUBSDIR . '/Mail.subs.php'; require_once SUBSDIR . '/Members.subs.php'; // We also need to the login languages here - for emails. loadLanguage('Login'); // Start off clean $conditions = array(); // Sort out where we are going... $current_filter = $conditions['activated_status'] = (int) $_REQUEST['orig_filter']; // If we are applying a filter do just that - then redirect. if (isset($_REQUEST['filter']) && $_REQUEST['filter'] != $_REQUEST['orig_filter']) { redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $_REQUEST['filter'] . ';start=' . $_REQUEST['start']); } // Nothing to do? if (!isset($_POST['todoAction']) && !isset($_POST['time_passed'])) { redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $current_filter . ';start=' . $_REQUEST['start']); } // Are we dealing with members who have been waiting for > set amount of time? if (isset($_POST['time_passed'])) { $conditions['time_before'] = time() - 86400 * (int) $_POST['time_passed']; } else { $conditions['members'] = array(); foreach ($_POST['todoAction'] as $id) { $conditions['members'][] = (int) $id; } } $data = retrieveMemberData($conditions); if ($data['member_count'] == 0) { redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $current_filter . ';start=' . $_REQUEST['start']); } $member_info = $data['member_info']; $conditions['members'] = $data['members']; // Are we activating or approving the members? if ($_POST['todo'] == 'ok' || $_POST['todo'] == 'okemail') { // Approve / activate this member. approveMembers($conditions); // Check for email. if ($_POST['todo'] == 'okemail') { foreach ($member_info as $member) { $replacements = array('NAME' => $member['name'], 'USERNAME' => $member['username'], 'PROFILELINK' => $scripturl . '?action=profile;u=' . $member['id'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder'); $emaildata = loadEmailTemplate('admin_approve_accept', $replacements, $member['language']); sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } } // Update the menu action cache so its forced to refresh cache_put_data('num_menu_errors', null, 900); } elseif ($_POST['todo'] == 'require_activation') { require_once SUBSDIR . '/Auth.subs.php'; // We have to do this for each member I'm afraid. foreach ($member_info as $member) { $conditions['selected_member'] = $member['id']; // Generate a random activation code. $conditions['validation_code'] = generateValidationCode(); // Set these members for activation - I know this includes two id_member checks but it's safer than bodging $condition ;). enforceReactivation($conditions); $replacements = array('USERNAME' => $member['name'], 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $member['id'] . ';code=' . $conditions['validation_code'], 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $member['id'], 'ACTIVATIONCODE' => $conditions['validation_code']); $emaildata = loadEmailTemplate('admin_approve_activation', $replacements, $member['language']); sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } } elseif ($_POST['todo'] == 'reject' || $_POST['todo'] == 'rejectemail') { deleteMembers($conditions['members']); // Send email telling them they aren't welcome? if ($_POST['todo'] == 'rejectemail') { foreach ($member_info as $member) { $replacements = array('USERNAME' => $member['name']); $emaildata = loadEmailTemplate('admin_approve_reject', $replacements, $member['language']); sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 1); } } } elseif ($_POST['todo'] == 'delete' || $_POST['todo'] == 'deleteemail') { deleteMembers($conditions['members']); // Send email telling them they aren't welcome? if ($_POST['todo'] == 'deleteemail') { foreach ($member_info as $member) { $replacements = array('USERNAME' => $member['name']); $emaildata = loadEmailTemplate('admin_approve_delete', $replacements, $member['language']); sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 1); } } } elseif ($_POST['todo'] == 'remind') { foreach ($member_info as $member) { $replacements = array('USERNAME' => $member['name'], 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $member['id'] . ';code=' . $member['code'], 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $member['id'], 'ACTIVATIONCODE' => $member['code']); $emaildata = loadEmailTemplate('admin_approve_remind', $replacements, $member['language']); sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 1); } } // Log what we did? if (!empty($modSettings['modlog_enabled']) && in_array($_POST['todo'], array('ok', 'okemail', 'require_activation', 'remind'))) { $log_action = $_POST['todo'] == 'remind' ? 'remind_member' : 'approve_member'; foreach ($member_info as $member) { logAction($log_action, array('member' => $member['id']), 'admin'); } } // Although updateStats *may* catch this, best to do it manually just in case (Doesn't always sort out unapprovedMembers). if (in_array($current_filter, array(3, 4))) { updateSettings(array('unapprovedMembers' => $modSettings['unapprovedMembers'] > $data['member_count'] ? $modSettings['unapprovedMembers'] - $data['member_count'] : 0)); } // Update the member's stats. (but, we know the member didn't change their name.) updateStats('member', false); // If they haven't been deleted, update the post group statistics on them... if (!in_array($_POST['todo'], array('delete', 'deleteemail', 'reject', 'rejectemail', 'remind'))) { updateStats('postgroups', $conditions['members']); } redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $current_filter . ';start=' . $_REQUEST['start']); }
/** * Pick a reminder type. * Accessed by sa=picktype */ public function action_picktype() { global $context, $txt, $scripturl, $user_info, $webmaster_email, $language, $modSettings; checkSession(); validateToken('remind'); createToken('remind'); require_once SUBSDIR . '/Auth.subs.php'; // No where params just yet $where_params = array(); // Coming with a known ID? if (!empty($_REQUEST['uid'])) { $where = 'id_member = {int:id_member}'; $where_params['id_member'] = (int) $_REQUEST['uid']; } elseif (isset($_POST['user']) && $_POST['user'] != '') { $where = 'member_name = {string:member_name}'; $where_params['member_name'] = $_POST['user']; $where_params['email_address'] = $_POST['user']; } // You must enter a username/email address. if (empty($where)) { fatal_lang_error('username_no_exist', false); } // Make sure we are not being slammed // Don't call this if you're coming from the "Choose a reminder type" page - otherwise you'll likely get an error if (!isset($_POST['reminder_type']) || !in_array($_POST['reminder_type'], array('email', 'secret'))) { spamProtection('remind'); } $member = findUser($where, $where_params); $context['account_type'] = !empty($member['openid_uri']) ? 'openid' : 'password'; // If the user isn't activated/approved, give them some feedback on what to do next. if ($member['is_activated'] != 1) { // Awaiting approval... if (trim($member['validation_code']) == '') { fatal_error($txt['registration_not_approved'] . ' <a href="' . $scripturl . '?action=activate;user='******'user'] . '">' . $txt['here'] . '</a>.', false); } else { fatal_error($txt['registration_not_activated'] . ' <a href="' . $scripturl . '?action=activate;user='******'user'] . '">' . $txt['here'] . '</a>.', false); } } // You can't get emailed if you have no email address. $member['email_address'] = trim($member['email_address']); if ($member['email_address'] == '') { fatal_error($txt['no_reminder_email'] . '<br />' . $txt['send_email'] . ' <a href="mailto:' . $webmaster_email . '">webmaster</a> ' . $txt['to_ask_password'] . '.'); } // If they have no secret question then they can only get emailed the item, or they are requesting the email, send them an email. if (empty($member['secret_question']) || isset($_POST['reminder_type']) && $_POST['reminder_type'] == 'email') { // Randomly generate a new password, with only alpha numeric characters that is a max length of 10 chars. $password = generateValidationCode(); require_once SUBSDIR . '/Mail.subs.php'; $replacements = array('REALNAME' => $member['real_name'], 'REMINDLINK' => $scripturl . '?action=reminder;sa=setpassword;u=' . $member['id_member'] . ';code=' . $password, 'IP' => $user_info['ip'], 'MEMBERNAME' => $member['member_name'], 'OPENID' => $member['openid_uri']); $emaildata = loadEmailTemplate('forgot_' . $context['account_type'], $replacements, empty($member['lngfile']) || empty($modSettings['userLanguage']) ? $language : $member['lngfile']); $context['description'] = $txt['reminder_' . (!empty($member['openid_uri']) ? 'openid_' : '') . 'sent']; // If they were using OpenID simply email them their OpenID identity. sendmail($member['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 1); if (empty($member['openid_uri'])) { // Set the password in the database. updateMemberData($member['id_member'], array('validation_code' => substr(md5($password), 0, 10))); } // Set up the template. $context['sub_template'] = 'sent'; // Dont really. return; } elseif (isset($_POST['reminder_type']) && $_POST['reminder_type'] == 'secret') { return secretAnswerInput(); } // No we're here setup the context for template number 2! $context['sub_template'] = 'reminder_pick'; $context['current_member'] = array('id' => $member['id_member'], 'name' => $member['member_name']); }
/** * 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); }
/** * Send the announcement in chunks. * * splits the members to be sent a topic announcement into chunks. * composes notification messages in all languages needed. * does the actual sending of the topic announcements in chunks. * calculates a rough estimate of the percentage items sent. * Accessed by action=announce;sa=send * @uses announcement template announcement_send sub template */ public function action_send() { global $topic, $board, $board_info, $context, $modSettings, $language, $scripturl; checkSession(); $context['start'] = empty($_REQUEST['start']) ? 0 : (int) $_REQUEST['start']; $groups = array_merge($board_info['groups'], array(1)); $who = array(); // Load any supplied membergroups (from announcement_send template pause loop) if (isset($_POST['membergroups'])) { $_POST['who'] = explode(',', $_POST['membergroups']); } // Check that at least one membergroup was selected (set from announce sub template) if (empty($_POST['who'])) { fatal_lang_error('no_membergroup_selected'); } // Make sure all membergroups are integers and can access the board of the announcement. foreach ($_POST['who'] as $id => $mg) { $who[$id] = in_array((int) $mg, $groups) ? (int) $mg : 0; } // Get the topic details that we are going to send require_once SUBSDIR . '/Topic.subs.php'; $topic_info = getTopicInfo($topic, 'message'); // Prepare a plain text (markdown) body for email use, does the censoring as well require_once SUBSDIR . '/Emailpost.subs.php'; pbe_prepare_text($topic_info['body'], $topic_info['subject']); // We need this in order to be able send emails. require_once SUBSDIR . '/Mail.subs.php'; require_once SUBSDIR . '/Members.subs.php'; // Select the email addresses for this batch. $conditions = array('activated_status' => 1, 'member_greater' => $context['start'], 'group_list' => $who, 'order_by' => 'id_member', 'limit' => empty($modSettings['mail_queue']) ? 25 : 500); // Have we allowed members to opt out of announcements? if (!empty($modSettings['allow_disableAnnounce'])) { $conditions['notify_announcements'] = 1; } $data = retrieveMemberData($conditions); // All members have received a mail. Go to the next screen. if (empty($data) || $data['member_count'] === 0) { logAction('announce_topic', array('topic' => $topic), 'user'); if (!empty($_REQUEST['move']) && allowedTo('move_any')) { redirectexit('action=movetopic;topic=' . $topic . '.0' . (empty($_REQUEST['goback']) ? '' : ';goback')); } elseif (!empty($_REQUEST['goback'])) { redirectexit('topic=' . $topic . '.new;boardseen#new', isBrowser('ie')); } else { redirectexit('board=' . $board . '.0'); } } // Loop through all members that'll receive an announcement in this batch. $announcements = array(); foreach ($data['member_info'] as $row) { $cur_language = empty($row['language']) || empty($modSettings['userLanguage']) ? $language : $row['language']; // If the language wasn't defined yet, load it and compose a notification message. if (!isset($announcements[$cur_language])) { $replacements = array('TOPICSUBJECT' => $topic_info['subject'], 'MESSAGE' => $topic_info['body'], 'TOPICLINK' => $scripturl . '?topic=' . $topic . '.0'); $emaildata = loadEmailTemplate('new_announcement', $replacements, $cur_language); $announcements[$cur_language] = array('subject' => $emaildata['subject'], 'body' => $emaildata['body'], 'recipients' => array()); } $announcements[$cur_language]['recipients'][$row['id']] = $row['email']; $context['start'] = $row['id']; } // For each language send a different mail - low priority... foreach ($announcements as $lang => $mail) { sendmail($mail['recipients'], $mail['subject'], $mail['body'], null, null, false, 5); } // Provide an overall indication of progress, this is not strictly correct if ($data['member_count'] < $conditions['limit']) { $context['percentage_done'] = 100; } else { $context['percentage_done'] = round(100 * $context['start'] / $modSettings['latestMember'], 1); } // Prepare for the template $context['move'] = empty($_REQUEST['move']) ? 0 : 1; $context['go_back'] = empty($_REQUEST['goback']) ? 0 : 1; $context['membergroups'] = implode(',', $who); $context['topic_subject'] = $topic_info['subject']; $context['sub_template'] = 'announcement_send'; // Go back to the correct language for the user ;) if (!empty($modSettings['userLanguage'])) { loadLanguage('Post'); } }
/** * Generates a random password for a user and emails it to them. * * What it does: * - called by ProfileOptions controller when changing someone's username. * - checks the validity of the new username. * - generates and sets a new password for the given user. * - mails the new password to the email address of the user. * - if username is not set, only a new password is generated and sent. * * @package Authorization * @param int $memID * @param string|null $username = null */ function resetPassword($memID, $username = null) { global $modSettings, $language, $user_info; // Language... and a required file. loadLanguage('Login'); require_once SUBSDIR . '/Mail.subs.php'; // Get some important details. require_once SUBSDIR . '/Members.subs.php'; $result = getBasicMemberData($memID, array('preferences' => true)); $user = $result['member_name']; $email = $result['email_address']; $lngfile = $result['lngfile']; if ($username !== null) { $old_user = $user; $user = trim($username); } // Generate a random password. require_once EXTDIR . '/PasswordHash.php'; $t_hasher = new PasswordHash(8, false); $newPassword = substr(preg_replace('/\\W/', '', md5(mt_rand())), 0, 10); $newPassword_sha256 = hash('sha256', strtolower($user) . $newPassword); $db_hash = $t_hasher->HashPassword($newPassword_sha256); // Do some checks on the username if needed. if ($username !== null) { $errors = Error_Context::context('reset_pwd', 0); validateUsername($memID, $user, 'reset_pwd'); // 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 = $errors->hasErrors(1) && !$user_info['is_admin'] ? 1 : null; foreach ($errors->prepareErrors($error_severity) as $error) { fatal_error($error, $error_severity === null ? false : 'general'); } // Update the database... updateMemberData($memID, array('member_name' => $user, 'passwd' => $db_hash)); } else { updateMemberData($memID, array('passwd' => $db_hash)); } call_integration_hook('integrate_reset_pass', array($old_user, $user, $newPassword)); $replacements = array('USERNAME' => $user, 'PASSWORD' => $newPassword); $emaildata = loadEmailTemplate('change_password', $replacements, empty($lngfile) || empty($modSettings['userLanguage']) ? $language : $lngfile); // Send them the email informing them of the change - then we're done! sendmail($email, $emaildata['subject'], $emaildata['body'], null, null, false, 0); }
/** * 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; }
function adminNotify($type, $memberID, $member_name = null, $actid = 0, $atype = 0) { global $txt, $modSettings, $language, $scripturl, $user_info, $sourcedir; // If the setting isn't enabled then just exit. if (empty($modSettings['notify_new_registration'])) { return; } if ($member_name == null) { // Get the new user's name.... $request = smf_db_query(' SELECT real_name FROM {db_prefix}members WHERE id_member = {int:id_member} LIMIT 1', array('id_member' => $memberID)); list($member_name) = mysql_fetch_row($request); mysql_free_result($request); } $toNotify = array(); $groups = array(); // All membergroups who can approve members. $request = smf_db_query(' SELECT id_group FROM {db_prefix}permissions WHERE permission = {string:moderate_forum} AND add_deny = {int:add_deny} AND id_group != {int:id_group}', array('add_deny' => 1, 'id_group' => 0, 'moderate_forum' => 'moderate_forum')); while ($row = mysql_fetch_assoc($request)) { $groups[] = $row['id_group']; } mysql_free_result($request); // Add administrators too... $groups[] = 1; $groups = array_unique($groups); // Get a list of all members who have ability to approve accounts - these are the people who we inform. $request = smf_db_query(' SELECT id_member, lngfile, email_address FROM {db_prefix}members WHERE (id_group IN ({array_int:group_list}) OR FIND_IN_SET({raw:group_array_implode}, additional_groups) != 0) AND notify_types != {int:notify_types} ORDER BY lngfile', array('group_list' => $groups, 'notify_types' => 4, 'group_array_implode' => implode(', additional_groups) != 0 OR FIND_IN_SET(', $groups))); $notify_users = array(); while ($row = mysql_fetch_assoc($request)) { $replacements = array('USERNAME' => $member_name, 'PROFILELINK' => $scripturl . '?action=profile;u=' . $memberID); $emailtype = 'admin_notify'; // If they need to be approved add more info... if ($type == 'approval') { $replacements['APPROVALLINK'] = $scripturl . '?action=admin;area=viewmembers;sa=browse;type=approve'; $emailtype .= '_approval'; } $emaildata = loadEmailTemplate($emailtype, $replacements, empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']); // And do the actual sending... sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); $notify_users[] = $row['id_member']; } mysql_free_result($request); if ((int) $actid > 0 && $atype && $modSettings['astream_active'] && count($notify_users)) { require_once $sourcedir . '/lib/Subs-Activities.php'; aStreamAddNotification($notify_users, $actid, $atype); } if (isset($current_language) && $current_language != $user_info['language']) { loadLanguage('Login'); } }
/** * Send the user a new activation email if they need to reactivate! */ function profileSendActivation() { global $profile_vars, $txt, $context, $scripturl, $cookiename, $cur_profile, $language, $modSettings; require_once SUBSDIR . '/Mail.subs.php'; // Shouldn't happen but just in case. if (empty($profile_vars['email_address'])) { return; } $replacements = array('ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $context['id_member'] . ';code=' . $profile_vars['validation_code'], 'ACTIVATIONCODE' => $profile_vars['validation_code'], 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $context['id_member']); // Send off the email. $emaildata = loadEmailTemplate('activate_reactivate', $replacements, empty($cur_profile['lngfile']) || empty($modSettings['userLanguage']) ? $language : $cur_profile['lngfile']); sendmail($profile_vars['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); // Log the user out. require_once SUBSDIR . '/Auth.subs.php'; logOnline($context['id_member'], false); $_SESSION['log_time'] = 0; $_SESSION['login_' . $cookiename] = serialize(array(0, '', 0)); if (isset($_COOKIE[$cookiename])) { $_COOKIE[$cookiename] = ''; } loadUserSettings(); $context['user']['is_logged'] = false; $context['user']['is_guest'] = true; // Send them to the done-with-registration-login screen. loadTemplate('Register'); $context['page_title'] = $txt['profile']; $context['sub_template'] = 'after'; $context['title'] = $txt['activate_changed_email_title']; $context['description'] = $txt['activate_changed_email_desc']; // We're gone! obExit(); }
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 groupMembership2($profile_vars, $post_errors, $memID) { global $user_info, $sourcedir, $context, $user_profile, $modSettings, $txt, $smcFunc, $scripturl, $language; // Let's be extra cautious... if (!$context['user']['is_owner'] || empty($modSettings['show_group_membership'])) { isAllowedTo('manage_membergroups'); } if (!isset($_REQUEST['gid']) && !isset($_POST['primary'])) { fatal_lang_error('no_access', false); } checkSession(isset($_GET['gid']) ? 'get' : 'post'); $old_profile =& $user_profile[$memID]; $context['can_manage_membergroups'] = allowedTo('manage_membergroups'); $context['can_manage_protected'] = allowedTo('admin_forum'); // By default the new primary is the old one. $newPrimary = $old_profile['id_group']; $addGroups = array_flip(explode(',', $old_profile['additional_groups'])); $canChangePrimary = $old_profile['id_group'] == 0 ? 1 : 0; $changeType = isset($_POST['primary']) ? 'primary' : (isset($_POST['req']) ? 'request' : 'free'); // One way or another, we have a target group in mind... $group_id = isset($_REQUEST['gid']) ? (int) $_REQUEST['gid'] : (int) $_POST['primary']; $foundTarget = $changeType == 'primary' && $group_id == 0 ? true : false; // Sanity check!! if ($group_id == 1) { isAllowedTo('admin_forum'); } else { $request = $smcFunc['db_query']('', ' SELECT group_type FROM {db_prefix}membergroups WHERE id_group = {int:current_group} LIMIT {int:limit}', array('current_group' => $group_id, 'limit' => 1)); list($is_protected) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); if ($is_protected == 1) { isAllowedTo('admin_forum'); } } // What ever we are doing, we need to determine if changing primary is possible! $request = $smcFunc['db_query']('', ' SELECT id_group, group_type, hidden, group_name FROM {db_prefix}membergroups WHERE id_group IN ({int:group_list}, {int:current_group})', array('group_list' => $group_id, 'current_group' => $old_profile['id_group'])); while ($row = $smcFunc['db_fetch_assoc']($request)) { // Is this the new group? if ($row['id_group'] == $group_id) { $foundTarget = true; $group_name = $row['group_name']; // Does the group type match what we're doing - are we trying to request a non-requestable group? if ($changeType == 'request' && $row['group_type'] != 2) { fatal_lang_error('no_access', false); } elseif ($changeType == 'free' && $row['group_type'] == 2 && $old_profile['id_group'] != $row['id_group'] && !isset($addGroups[$row['id_group']])) { fatal_lang_error('no_access', false); } elseif ($changeType == 'free' && $row['group_type'] != 3 && $row['group_type'] != 2) { fatal_lang_error('no_access', false); } // We can't change the primary group if this is hidden! if ($row['hidden'] == 2) { $canChangePrimary = false; } } // If this is their old primary, can we change it? if ($row['id_group'] == $old_profile['id_group'] && ($row['group_type'] > 1 || $context['can_manage_membergroups']) && $canChangePrimary !== false) { $canChangePrimary = 1; } // If we are not doing a force primary move, don't do it automatically if current primary is not 0. if ($changeType != 'primary' && $old_profile['id_group'] != 0) { $canChangePrimary = false; } // If this is the one we are acting on, can we even act? if (!$context['can_manage_protected'] && $row['group_type'] == 1 || !$context['can_manage_membergroups'] && $row['group_type'] == 0) { $canChangePrimary = false; } } $smcFunc['db_free_result']($request); // Didn't find the target? if (!$foundTarget) { fatal_lang_error('no_access', false); } // Final security check, don't allow users to promote themselves to admin. if ($context['can_manage_membergroups'] && !allowedTo('admin_forum')) { $request = $smcFunc['db_query']('', ' SELECT COUNT(permission) FROM {db_prefix}permissions WHERE id_group = {int:selected_group} AND permission = {string:admin_forum} AND add_deny = {int:not_denied}', array('selected_group' => $group_id, 'not_denied' => 1, 'admin_forum' => 'admin_forum')); list($disallow) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); if ($disallow) { isAllowedTo('admin_forum'); } } // If we're requesting, add the note then return. if ($changeType == 'request') { $request = $smcFunc['db_query']('', ' SELECT id_member FROM {db_prefix}log_group_requests WHERE id_member = {int:selected_member} AND id_group = {int:selected_group}', array('selected_member' => $memID, 'selected_group' => $group_id)); if ($smcFunc['db_num_rows']($request) != 0) { fatal_lang_error('profile_error_already_requested_group'); } $smcFunc['db_free_result']($request); // Log the request. $smcFunc['db_insert']('', '{db_prefix}log_group_requests', array('id_member' => 'int', 'id_group' => 'int', 'time_applied' => 'int', 'reason' => 'string-65534'), array($memID, $group_id, time(), $_POST['reason']), array('id_request')); // Send an email to all group moderators etc. require_once $sourcedir . '/Subs-Post.php'; // Do we have any group moderators? $request = $smcFunc['db_query']('', ' SELECT id_member FROM {db_prefix}group_moderators WHERE id_group = {int:selected_group}', array('selected_group' => $group_id)); $moderators = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { $moderators[] = $row['id_member']; } $smcFunc['db_free_result']($request); // Otherwise this is the backup! if (empty($moderators)) { require_once $sourcedir . '/Subs-Members.php'; $moderators = membersAllowedTo('manage_membergroups'); } if (!empty($moderators)) { $request = $smcFunc['db_query']('', ' SELECT id_member, email_address, lngfile, member_name, mod_prefs FROM {db_prefix}members WHERE id_member IN ({array_int:moderator_list}) AND notify_types != {int:no_notifications} ORDER BY lngfile', array('moderator_list' => $moderators, 'no_notifications' => 4)); while ($row = $smcFunc['db_fetch_assoc']($request)) { // Check whether they are interested. if (!empty($row['mod_prefs'])) { list(, , $pref_binary) = explode('|', $row['mod_prefs']); if (!($pref_binary & 4)) { continue; } } $replacements = array('RECPNAME' => $row['member_name'], 'APPYNAME' => $old_profile['member_name'], 'GROUPNAME' => $group_name, 'REASON' => $_POST['reason'], 'MODLINK' => $scripturl . '?action=moderate;area=groups;sa=requests'); $emaildata = loadEmailTemplate('request_membership', $replacements, empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']); sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 2); } $smcFunc['db_free_result']($request); } return $changeType; } elseif ($changeType == 'free') { // Are we leaving? if ($old_profile['id_group'] == $group_id || isset($addGroups[$group_id])) { if ($old_profile['id_group'] == $group_id) { $newPrimary = 0; } else { unset($addGroups[$group_id]); } } else { // Can we change the primary, and do we want to? if ($canChangePrimary) { if ($old_profile['id_group'] != 0) { $addGroups[$old_profile['id_group']] = -1; } $newPrimary = $group_id; } else { $addGroups[$group_id] = -1; } } } elseif ($canChangePrimary) { if ($old_profile['id_group'] != 0) { $addGroups[$old_profile['id_group']] = -1; } if (isset($addGroups[$group_id])) { unset($addGroups[$group_id]); } $newPrimary = $group_id; } // Finally, we can make the changes! foreach ($addGroups as $id => $dummy) { if (empty($id)) { unset($addGroups[$id]); } } $addGroups = implode(',', array_flip($addGroups)); // Ensure that we don't cache permissions if the group is changing. if ($context['user']['is_owner']) { $_SESSION['mc']['time'] = 0; } else { updateSettings(array('settings_updated' => time())); } updateMemberData($memID, array('id_group' => $newPrimary, 'additional_groups' => $addGroups)); return $changeType; }
/** * This simple function gets a list of all administrators and sends them an email * to let them know a new member has joined. * Called by registerMember() function in subs/Members.subs.php. * Email is sent to all groups that have the moderate_forum permission. * The language set by each member is being used (if available). * * @param string $type types supported are 'approval', 'activation', and 'standard'. * @param int $memberID * @param string|null $member_name = null * @uses the Login language file. */ function sendAdminNotifications($type, $memberID, $member_name = null) { global $modSettings, $language, $scripturl, $user_info; $db = database(); // If the setting isn't enabled then just exit. if (empty($modSettings['notify_new_registration'])) { return; } // Needed to notify admins, or anyone require_once SUBSDIR . '/Mail.subs.php'; if ($member_name == null) { require_once SUBSDIR . '/Members.subs.php'; // Get the new user's name.... $member_info = getBasicMemberData($memberID); $member_name = $member_info['real_name']; } $groups = array(); // All membergroups who can approve members. $request = $db->query('', ' SELECT id_group FROM {db_prefix}permissions WHERE permission = {string:moderate_forum} AND add_deny = {int:add_deny} AND id_group != {int:id_group}', array('add_deny' => 1, 'id_group' => 0, 'moderate_forum' => 'moderate_forum')); while ($row = $db->fetch_assoc($request)) { $groups[] = $row['id_group']; } $db->free_result($request); // Add administrators too... $groups[] = 1; $groups = array_unique($groups); // Get a list of all members who have ability to approve accounts - these are the people who we inform. $request = $db->query('', ' SELECT id_member, lngfile, email_address FROM {db_prefix}members WHERE (id_group IN ({array_int:group_list}) OR FIND_IN_SET({raw:group_array_implode}, additional_groups) != 0) AND notify_types != {int:notify_types} ORDER BY lngfile', array('group_list' => $groups, 'notify_types' => 4, 'group_array_implode' => implode(', additional_groups) != 0 OR FIND_IN_SET(', $groups))); $current_language = $user_info['language']; while ($row = $db->fetch_assoc($request)) { $replacements = array('USERNAME' => $member_name, 'PROFILELINK' => $scripturl . '?action=profile;u=' . $memberID); $emailtype = 'admin_notify'; // If they need to be approved add more info... if ($type == 'approval') { $replacements['APPROVALLINK'] = $scripturl . '?action=admin;area=viewmembers;sa=browse;type=approve'; $emailtype .= '_approval'; } $emaildata = loadEmailTemplate($emailtype, $replacements, empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']); // And do the actual sending... sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } $db->free_result($request); if (isset($current_language) && $current_language != $user_info['language']) { loadLanguage('Login'); } }
/** * Sends a personal message from the specified person to the specified people * ($from defaults to the user) * * @package PersonalMessage * @param mixed[] $recipients - an array containing the arrays 'to' and 'bcc', both containing id_member's. * @param string $subject - should have no slashes and no html entities * @param string $message - should have no slashes and no html entities * @param bool $store_outbox * @param mixed[]|null $from - an array with the id, name, and username of the member. * @param int $pm_head - the ID of the chain being replied to - if any. * @return mixed[] an array with log entries telling how many recipients were successful and which recipients it failed to send to. */ function sendpm($recipients, $subject, $message, $store_outbox = true, $from = null, $pm_head = 0) { global $scripturl, $txt, $user_info, $language, $modSettings, $webmaster_email; $db = database(); // Make sure the PM language file is loaded, we might need something out of it. loadLanguage('PersonalMessage'); // Needed for our email and post functions require_once SUBSDIR . '/Mail.subs.php'; require_once SUBSDIR . '/Post.subs.php'; // Initialize log array. $log = array('failed' => array(), 'sent' => array()); if ($from === null) { $from = array('id' => $user_info['id'], 'name' => $user_info['name'], 'username' => $user_info['username']); } else { $user_info['name'] = $from['name']; } // This is the one that will go in their inbox. $htmlmessage = Util::htmlspecialchars($message, ENT_QUOTES, 'UTF-8', true); preparsecode($htmlmessage); $htmlsubject = strtr(Util::htmlspecialchars($subject), array("\r" => '', "\n" => '', "\t" => '')); if (Util::strlen($htmlsubject) > 100) { $htmlsubject = Util::substr($htmlsubject, 0, 100); } // Make sure is an array if (!is_array($recipients)) { $recipients = array($recipients); } // Integrated PMs call_integration_hook('integrate_personal_message', array(&$recipients, &$from, &$subject, &$message)); // Get a list of usernames and convert them to IDs. $usernames = array(); foreach ($recipients as $rec_type => $rec) { foreach ($rec as $id => $member) { if (!is_numeric($recipients[$rec_type][$id])) { $recipients[$rec_type][$id] = Util::strtolower(trim(preg_replace('/[<>&"\'=\\\\]/', '', $recipients[$rec_type][$id]))); $usernames[$recipients[$rec_type][$id]] = 0; } } } if (!empty($usernames)) { $request = $db->query('pm_find_username', ' SELECT id_member, member_name FROM {db_prefix}members WHERE ' . (defined('DB_CASE_SENSITIVE') ? 'LOWER(member_name)' : 'member_name') . ' IN ({array_string:usernames})', array('usernames' => array_keys($usernames))); while ($row = $db->fetch_assoc($request)) { if (isset($usernames[Util::strtolower($row['member_name'])])) { $usernames[Util::strtolower($row['member_name'])] = $row['id_member']; } } $db->free_result($request); // Replace the usernames with IDs. Drop usernames that couldn't be found. foreach ($recipients as $rec_type => $rec) { foreach ($rec as $id => $member) { if (is_numeric($recipients[$rec_type][$id])) { continue; } if (!empty($usernames[$member])) { $recipients[$rec_type][$id] = $usernames[$member]; } else { $log['failed'][$id] = sprintf($txt['pm_error_user_not_found'], $recipients[$rec_type][$id]); unset($recipients[$rec_type][$id]); } } } } // Make sure there are no duplicate 'to' members. $recipients['to'] = array_unique($recipients['to']); // Only 'bcc' members that aren't already in 'to'. $recipients['bcc'] = array_diff(array_unique($recipients['bcc']), $recipients['to']); // Combine 'to' and 'bcc' recipients. $all_to = array_merge($recipients['to'], $recipients['bcc']); // Check no-one will want it deleted right away! $request = $db->query('', ' SELECT id_member, criteria, is_or FROM {db_prefix}pm_rules WHERE id_member IN ({array_int:to_members}) AND delete_pm = {int:delete_pm}', array('to_members' => $all_to, 'delete_pm' => 1)); $deletes = array(); // Check whether we have to apply anything... while ($row = $db->fetch_assoc($request)) { $criteria = unserialize($row['criteria']); // Note we don't check the buddy status, cause deletion from buddy = madness! $delete = false; foreach ($criteria as $criterium) { if ($criterium['t'] == 'mid' && $criterium['v'] == $from['id'] || $criterium['t'] == 'gid' && in_array($criterium['v'], $user_info['groups']) || $criterium['t'] == 'sub' && strpos($subject, $criterium['v']) !== false || $criterium['t'] == 'msg' && strpos($message, $criterium['v']) !== false) { $delete = true; } elseif (!$row['is_or']) { $delete = false; break; } } if ($delete) { $deletes[$row['id_member']] = 1; } } $db->free_result($request); // Load the membergrounp message limits. static $message_limit_cache = array(); if (!allowedTo('moderate_forum') && empty($message_limit_cache)) { $request = $db->query('', ' SELECT id_group, max_messages FROM {db_prefix}membergroups', array()); while ($row = $db->fetch_assoc($request)) { $message_limit_cache[$row['id_group']] = $row['max_messages']; } $db->free_result($request); } // Load the groups that are allowed to read PMs. // @todo move into a separate function on $permission. $allowed_groups = array(); $disallowed_groups = array(); $request = $db->query('', ' SELECT id_group, add_deny FROM {db_prefix}permissions WHERE permission = {string:read_permission}', array('read_permission' => 'pm_read')); while ($row = $db->fetch_assoc($request)) { if (empty($row['add_deny'])) { $disallowed_groups[] = $row['id_group']; } else { $allowed_groups[] = $row['id_group']; } } $db->free_result($request); if (empty($modSettings['permission_enable_deny'])) { $disallowed_groups = array(); } $request = $db->query('', ' SELECT member_name, real_name, id_member, email_address, lngfile, pm_email_notify, personal_messages,' . (allowedTo('moderate_forum') ? ' 0' : ' (receive_from = {int:admins_only}' . (empty($modSettings['enable_buddylist']) ? '' : ' OR (receive_from = {int:buddies_only} AND FIND_IN_SET({string:from_id}, buddy_list) = 0) OR (receive_from = {int:not_on_ignore_list} AND FIND_IN_SET({string:from_id}, pm_ignore_list) != 0)') . ')') . ' AS ignored, FIND_IN_SET({string:from_id}, buddy_list) != 0 AS is_buddy, is_activated, additional_groups, id_group, id_post_group FROM {db_prefix}members WHERE id_member IN ({array_int:recipients}) ORDER BY lngfile LIMIT {int:count_recipients}', array('not_on_ignore_list' => 1, 'buddies_only' => 2, 'admins_only' => 3, 'recipients' => $all_to, 'count_recipients' => count($all_to), 'from_id' => $from['id'])); $notifications = array(); while ($row = $db->fetch_assoc($request)) { // Don't do anything for members to be deleted! if (isset($deletes[$row['id_member']])) { continue; } // We need to know this members groups. $groups = explode(',', $row['additional_groups']); $groups[] = $row['id_group']; $groups[] = $row['id_post_group']; $message_limit = -1; // For each group see whether they've gone over their limit - assuming they're not an admin. if (!in_array(1, $groups)) { foreach ($groups as $id) { if (isset($message_limit_cache[$id]) && $message_limit != 0 && $message_limit < $message_limit_cache[$id]) { $message_limit = $message_limit_cache[$id]; } } if ($message_limit > 0 && $message_limit <= $row['personal_messages']) { $log['failed'][$row['id_member']] = sprintf($txt['pm_error_data_limit_reached'], $row['real_name']); unset($all_to[array_search($row['id_member'], $all_to)]); continue; } // Do they have any of the allowed groups? if (count(array_intersect($allowed_groups, $groups)) == 0 || count(array_intersect($disallowed_groups, $groups)) != 0) { $log['failed'][$row['id_member']] = sprintf($txt['pm_error_user_cannot_read'], $row['real_name']); unset($all_to[array_search($row['id_member'], $all_to)]); continue; } } // Note that PostgreSQL can return a lowercase t/f for FIND_IN_SET if (!empty($row['ignored']) && $row['ignored'] != 'f' && $row['id_member'] != $from['id']) { $log['failed'][$row['id_member']] = sprintf($txt['pm_error_ignored_by_user'], $row['real_name']); unset($all_to[array_search($row['id_member'], $all_to)]); continue; } // If the receiving account is banned (>=10) or pending deletion (4), refuse to send the PM. if ($row['is_activated'] >= 10 || $row['is_activated'] == 4 && !$user_info['is_admin']) { $log['failed'][$row['id_member']] = sprintf($txt['pm_error_user_cannot_read'], $row['real_name']); unset($all_to[array_search($row['id_member'], $all_to)]); continue; } // Send a notification, if enabled - taking the buddy list into account. if (!empty($row['email_address']) && ($row['pm_email_notify'] == 1 || $row['pm_email_notify'] > 1 && (!empty($modSettings['enable_buddylist']) && $row['is_buddy'])) && $row['is_activated'] == 1) { $notifications[empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']][] = $row['email_address']; } $log['sent'][$row['id_member']] = sprintf(isset($txt['pm_successfully_sent']) ? $txt['pm_successfully_sent'] : '', $row['real_name']); } $db->free_result($request); // Only 'send' the message if there are any recipients left. if (empty($all_to)) { return $log; } // Track the pm count for our stats if (!empty($modSettings['trackStats'])) { trackStats(array('pm' => '+')); } // Insert the message itself and then grab the last insert id. $db->insert('', '{db_prefix}personal_messages', array('id_pm_head' => 'int', 'id_member_from' => 'int', 'deleted_by_sender' => 'int', 'from_name' => 'string-255', 'msgtime' => 'int', 'subject' => 'string-255', 'body' => 'string-65534'), array($pm_head, $from['id'], $store_outbox ? 0 : 1, $from['username'], time(), $htmlsubject, $htmlmessage), array('id_pm')); $id_pm = $db->insert_id('{db_prefix}personal_messages', 'id_pm'); // Add the recipients. if (!empty($id_pm)) { // If this is new we need to set it part of it's own conversation. if (empty($pm_head)) { $db->query('', ' UPDATE {db_prefix}personal_messages SET id_pm_head = {int:id_pm_head} WHERE id_pm = {int:id_pm_head}', array('id_pm_head' => $id_pm)); } // Some people think manually deleting personal_messages is fun... it's not. We protect against it though :) $db->query('', ' DELETE FROM {db_prefix}pm_recipients WHERE id_pm = {int:id_pm}', array('id_pm' => $id_pm)); $insertRows = array(); $to_list = array(); foreach ($all_to as $to) { $insertRows[] = array($id_pm, $to, in_array($to, $recipients['bcc']) ? 1 : 0, isset($deletes[$to]) ? 1 : 0, 1); if (!in_array($to, $recipients['bcc'])) { $to_list[] = $to; } } $db->insert('insert', '{db_prefix}pm_recipients', array('id_pm' => 'int', 'id_member' => 'int', 'bcc' => 'int', 'deleted' => 'int', 'is_new' => 'int'), $insertRows, array('id_pm', 'id_member')); } $maillist = !empty($modSettings['maillist_enabled']) && !empty($modSettings['pbe_pm_enabled']); // If they have post by email enabled, override disallow_sendBody if (!$maillist && !empty($modSettings['disallow_sendBody'])) { $message = ''; censorText($subject); } else { require_once SUBSDIR . '/Emailpost.subs.php'; pbe_prepare_text($message, $subject); } $to_names = array(); if (count($to_list) > 1) { require_once SUBSDIR . '/Members.subs.php'; $result = getBasicMemberData($to_list); foreach ($result as $row) { $to_names[] = un_htmlspecialchars($row['real_name']); } } $replacements = array('SUBJECT' => $subject, 'MESSAGE' => $message, 'SENDER' => un_htmlspecialchars($from['name']), 'READLINK' => $scripturl . '?action=pm;pmsg=' . $id_pm . '#msg' . $id_pm, 'REPLYLINK' => $scripturl . '?action=pm;sa=send;f=inbox;pmsg=' . $id_pm . ';quote;u=' . $from['id'], 'TOLIST' => implode(', ', $to_names)); // Select the right template $email_template = ($maillist && empty($modSettings['disallow_sendBody']) ? 'pbe_' : '') . 'new_pm' . (empty($modSettings['disallow_sendBody']) ? '_body' : '') . (!empty($to_names) ? '_tolist' : ''); foreach ($notifications as $lang => $notification_list) { // Using maillist functionality if ($maillist) { $sender_details = query_sender_wrapper($from['id']); $from_wrapper = !empty($modSettings['maillist_mail_from']) ? $modSettings['maillist_mail_from'] : (empty($modSettings['maillist_sitename_address']) ? $webmaster_email : $modSettings['maillist_sitename_address']); // Add in the signature $replacements['SIGNATURE'] = $sender_details['signature']; // And off it goes, looking a bit more personal $mail = loadEmailTemplate($email_template, $replacements, $lang); $reference = !empty($pm_head) ? $pm_head : null; sendmail($notification_list, $mail['subject'], $mail['body'], $from['name'], 'p' . $id_pm, false, 2, null, true, $from_wrapper, $reference); } else { // Off the notification email goes! $mail = loadEmailTemplate($email_template, $replacements, $lang); sendmail($notification_list, $mail['subject'], $mail['body'], null, 'p' . $id_pm, false, 2, null, true); } } // Integrated After PMs call_integration_hook('integrate_personal_message_after', array(&$id_pm, &$log, &$recipients, &$from, &$subject, &$message)); // Back to what we were on before! loadLanguage('index+PersonalMessage'); // Add one to their unread and read message counts. foreach ($all_to as $k => $id) { if (isset($deletes[$id])) { unset($all_to[$k]); } } if (!empty($all_to)) { updateMemberData($all_to, array('personal_messages' => '+', 'unread_messages' => '+', 'new_pm' => 1)); } return $log; }
function scheduled_paid_subscriptions() { global $txt, $sourcedir, $scripturl, $modSettings, $language; // Start off by checking for removed subscriptions. $request = smf_db_query(' SELECT id_subscribe, id_member FROM {db_prefix}log_subscribed WHERE status = {int:is_active} AND end_time < {int:time_now}', array('is_active' => 1, 'time_now' => time())); while ($row = mysql_fetch_assoc($request)) { require_once $sourcedir . '/ManagePaid.php'; removeSubscription($row['id_subscribe'], $row['id_member']); } mysql_free_result($request); // Get all those about to expire that have not had a reminder sent. $request = smf_db_query(' SELECT ls.id_sublog, m.id_member, m.member_name, m.email_address, m.lngfile, s.name, ls.end_time FROM {db_prefix}log_subscribed AS ls INNER JOIN {db_prefix}subscriptions AS s ON (s.id_subscribe = ls.id_subscribe) INNER JOIN {db_prefix}members AS m ON (m.id_member = ls.id_member) WHERE ls.status = {int:is_active} AND ls.reminder_sent = {int:reminder_sent} AND s.reminder > {int:reminder_wanted} AND ls.end_time < ({int:time_now} + s.reminder * 86400)', array('is_active' => 1, 'reminder_sent' => 0, 'reminder_wanted' => 0, 'time_now' => time())); $subs_reminded = array(); while ($row = mysql_fetch_assoc($request)) { // If this is the first one load the important bits. if (empty($subs_reminded)) { require_once $sourcedir . '/lib/Subs-Post.php'; // Need the below for loadLanguage to work! loadEssentialThemeData(); } $subs_reminded[] = $row['id_sublog']; $replacements = array('PROFILE_LINK' => $scripturl . '?action=profile;area=subscriptions;u=' . $row['id_member'], 'REALNAME' => $row['member_name'], 'SUBSCRIPTION' => $row['name'], 'END_DATE' => strip_tags(timeformat($row['end_time']))); $emaildata = loadEmailTemplate('paid_subscription_reminder', $replacements, empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']); // Send the actual email. sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 2); } mysql_free_result($request); // Mark the reminder as sent. if (!empty($subs_reminded)) { smf_db_query(' UPDATE {db_prefix}log_subscribed SET reminder_sent = {int:reminder_sent} WHERE id_sublog IN ({array_int:subscription_list})', array('subscription_list' => $subs_reminded, 'reminder_sent' => 1)); } return true; }
/** * Send all the administrators a lovely email. * * What it does: * - It loads all users who are admins or have the admin forum permission. * - It uses the email template and replacements passed in the parameters. * - It sends them an email. * * @package Admin * @param string $template * @param mixed[] $replacements * @param int[] $additional_recipients */ function emailAdmins($template, $replacements = array(), $additional_recipients = array()) { global $language, $modSettings; $db = database(); // We certainly want this. require_once SUBSDIR . '/Mail.subs.php'; // Load all groups which are effectively admins. $request = $db->query('', ' SELECT id_group FROM {db_prefix}permissions WHERE permission = {string:admin_forum} AND add_deny = {int:add_deny} AND id_group != {int:id_group}', array('add_deny' => 1, 'id_group' => 0, 'admin_forum' => 'admin_forum')); $groups = array(1); while ($row = $db->fetch_assoc($request)) { $groups[] = $row['id_group']; } $db->free_result($request); $request = $db->query('', ' SELECT id_member, member_name, real_name, lngfile, email_address FROM {db_prefix}members WHERE (id_group IN ({array_int:group_list}) OR FIND_IN_SET({raw:group_array_implode}, additional_groups) != 0) AND notify_types != {int:notify_types} ORDER BY lngfile', array('group_list' => $groups, 'notify_types' => 4, 'group_array_implode' => implode(', additional_groups) != 0 OR FIND_IN_SET(', $groups))); $emails_sent = array(); while ($row = $db->fetch_assoc($request)) { // Stick their particulars in the replacement data. $replacements['IDMEMBER'] = $row['id_member']; $replacements['REALNAME'] = $row['member_name']; $replacements['USERNAME'] = $row['real_name']; // Load the data from the template. $emaildata = loadEmailTemplate($template, $replacements, empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']); // Then send the actual email. sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 1); // Track who we emailed so we don't do it twice. $emails_sent[] = $row['email_address']; } $db->free_result($request); // Any additional users we must email this to? if (!empty($additional_recipients)) { foreach ($additional_recipients as $recipient) { if (in_array($recipient['email'], $emails_sent)) { continue; } $replacements['IDMEMBER'] = $recipient['id']; $replacements['REALNAME'] = $recipient['name']; $replacements['USERNAME'] = $recipient['name']; // Load the template again. $emaildata = loadEmailTemplate($template, $replacements, empty($recipient['lang']) || empty($modSettings['userLanguage']) ? $language : $recipient['lang']); // Send off the email. sendmail($recipient['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 1); } } }
function GroupRequests() { global $txt, $context, $scripturl, $user_info, $sourcedir, $smcFunc, $modSettings, $language; // Set up the template stuff... $context['page_title'] = $txt['mc_group_requests']; $context['sub_template'] = 'show_list'; // Verify we can be here. if ($user_info['mod_cache']['gq'] == '0=1') { isAllowedTo('manage_membergroups'); } // Normally, we act normally... $where = $user_info['mod_cache']['gq'] == '1=1' || $user_info['mod_cache']['gq'] == '0=1' ? $user_info['mod_cache']['gq'] : 'lgr.' . $user_info['mod_cache']['gq']; $where_parameters = array(); // We've submitted? if (isset($_POST[$context['session_var']]) && !empty($_POST['groupr']) && !empty($_POST['req_action'])) { checkSession('post'); // Clean the values. foreach ($_POST['groupr'] as $k => $request) { $_POST['groupr'][$k] = (int) $request; } // If we are giving a reason (And why shouldn't we?), then we don't actually do much. if ($_POST['req_action'] == 'reason') { // Different sub template... $context['sub_template'] = 'group_request_reason'; // And a limitation. We don't care that the page number bit makes no sense, as we don't need it! $where .= ' AND lgr.id_request IN ({array_int:request_ids})'; $where_parameters['request_ids'] = $_POST['groupr']; $context['group_requests'] = list_getGroupRequests(0, $modSettings['defaultMaxMessages'], 'lgr.id_request', $where, $where_parameters); // Let obExit etc sort things out. obExit(); } else { // Get the details of all the members concerned... $request = $smcFunc['db_query']('', ' SELECT lgr.id_request, lgr.id_member, lgr.id_group, mem.email_address, mem.id_group AS primary_group, mem.additional_groups AS additional_groups, mem.lngfile, mem.member_name, mem.notify_types, mg.hidden, mg.group_name FROM {db_prefix}log_group_requests AS lgr INNER JOIN {db_prefix}members AS mem ON (mem.id_member = lgr.id_member) INNER JOIN {db_prefix}membergroups AS mg ON (mg.id_group = lgr.id_group) WHERE ' . $where . ' AND lgr.id_request IN ({array_int:request_list}) ORDER BY mem.lngfile', array('request_list' => $_POST['groupr'])); $email_details = array(); $group_changes = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { $row['lngfile'] = empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']; // If we are approving work out what their new group is. if ($_POST['req_action'] == 'approve') { // For people with more than one request at once. if (isset($group_changes[$row['id_member']])) { $row['additional_groups'] = $group_changes[$row['id_member']]['add']; $row['primary_group'] = $group_changes[$row['id_member']]['primary']; } else { $row['additional_groups'] = explode(',', $row['additional_groups']); } // Don't have it already? if ($row['primary_group'] == $row['id_group'] || in_array($row['id_group'], $row['additional_groups'])) { continue; } // Should it become their primary? if ($row['primary_group'] == 0 && $row['hidden'] == 0) { $row['primary_group'] = $row['id_group']; } else { $row['additional_groups'][] = $row['id_group']; } // Add them to the group master list. $group_changes[$row['id_member']] = array('primary' => $row['primary_group'], 'add' => $row['additional_groups']); } // Add required information to email them. if ($row['notify_types'] != 4) { $email_details[] = array('rid' => $row['id_request'], 'member_id' => $row['id_member'], 'member_name' => $row['member_name'], 'group_id' => $row['id_group'], 'group_name' => $row['group_name'], 'email' => $row['email_address'], 'language' => $row['lngfile']); } } $smcFunc['db_free_result']($request); // Remove the evidence... $smcFunc['db_query']('', ' DELETE FROM {db_prefix}log_group_requests WHERE id_request IN ({array_int:request_list})', array('request_list' => $_POST['groupr'])); // Ensure everyone who is online gets their changes right away. updateSettings(array('settings_updated' => time())); if (!empty($email_details)) { require_once $sourcedir . '/Subs-Post.php'; // They are being approved? if ($_POST['req_action'] == 'approve') { // Make the group changes. foreach ($group_changes as $id => $groups) { // Sanity check! foreach ($groups['add'] as $key => $value) { if ($value == 0 || trim($value) == '') { unset($groups['add'][$key]); } } $smcFunc['db_query']('', ' UPDATE {db_prefix}members SET id_group = {int:primary_group}, additional_groups = {string:additional_groups} WHERE id_member = {int:selected_member}', array('primary_group' => $groups['primary'], 'selected_member' => $id, 'additional_groups' => implode(',', $groups['add']))); } $lastLng = $user_info['language']; foreach ($email_details as $email) { $replacements = array('USERNAME' => $email['member_name'], 'GROUPNAME' => $email['group_name']); $emaildata = loadEmailTemplate('mc_group_approve', $replacements, $email['language']); sendmail($email['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 2); } } else { // Same as for approving, kind of. $lastLng = $user_info['language']; foreach ($email_details as $email) { $custom_reason = isset($_POST['groupreason']) && isset($_POST['groupreason'][$email['rid']]) ? $_POST['groupreason'][$email['rid']] : ''; $replacements = array('USERNAME' => $email['member_name'], 'GROUPNAME' => $email['group_name']); if (!empty($custom_reason)) { $replacements['REASON'] = $custom_reason; } $emaildata = loadEmailTemplate(empty($custom_reason) ? 'mc_group_reject' : 'mc_group_reject_reason', $replacements, $email['language']); sendmail($email['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 2); } } } // Restore the current language. loadLanguage('ModerationCenter'); } } // We're going to want this for making our list. require_once $sourcedir . '/Subs-List.php'; // This is all the information required for a group listing. $listOptions = array('id' => 'group_request_list', 'title' => $txt['mc_group_requests'], 'width' => '100%', 'items_per_page' => $modSettings['defaultMaxMessages'], 'no_items_label' => $txt['mc_groupr_none_found'], 'base_href' => $scripturl . '?action=groups;sa=requests', 'default_sort_col' => 'member', 'get_items' => array('function' => 'list_getGroupRequests', 'params' => array($where, $where_parameters)), 'get_count' => array('function' => 'list_getGroupRequestCount', 'params' => array($where, $where_parameters)), 'columns' => array('member' => array('header' => array('value' => $txt['mc_groupr_member']), 'data' => array('db' => 'member_link'), 'sort' => array('default' => 'mem.member_name', 'reverse' => 'mem.member_name DESC')), 'group' => array('header' => array('value' => $txt['mc_groupr_group']), 'data' => array('db' => 'group_link'), 'sort' => array('default' => 'mg.group_name', 'reverse' => 'mg.group_name DESC')), 'reason' => array('header' => array('value' => $txt['mc_groupr_reason']), 'data' => array('db' => 'reason')), 'action' => array('header' => array('value' => '<input type="checkbox" class="input_check" onclick="invertAll(this, this.form);" />', 'style' => 'width: 4%;'), 'data' => array('sprintf' => array('format' => '<input type="checkbox" name="groupr[]" value="%1$d" class="input_check" />', 'params' => array('id' => false)), 'style' => 'text-align: center;'))), 'form' => array('href' => $scripturl . '?action=groups;sa=requests', 'include_sort' => true, 'include_start' => true, 'hidden_fields' => array($context['session_var'] => $context['session_id'])), 'additional_rows' => array(array('position' => 'bottom_of_list', 'value' => ' <select name="req_action" onchange="if (this.value != 0 && (this.value == \'reason\' || confirm(\'' . $txt['mc_groupr_warning'] . '\'))) this.form.submit();"> <option value="0">' . $txt['with_selected'] . ':</option> <option value="0">---------------------</option> <option value="approve">' . $txt['mc_groupr_approve'] . '</option> <option value="reject">' . $txt['mc_groupr_reject'] . '</option> <option value="reason">' . $txt['mc_groupr_reject_w_reason'] . '</option> </select> <input type="submit" name="go" value="' . $txt['go'] . '" onclick="var sel = document.getElementById(\'req_action\'); if (sel.value != 0 && sel.value != \'reason\' && !confirm(\'' . $txt['mc_groupr_warning'] . '\')) return false;" class="button_submit" />', 'align' => 'right'))); // Create the request list. createList($listOptions); $context['default_list'] = 'group_request_list'; }
function arcadeEvent($id_event, $data = array()) { global $smcFunc, $db_prefix, $scripturl, $txt, $user_info, $sourcedir, $modSettings, $language; if ($id_event == 'get' && empty($data)) { return arcadeGetEventTypes(); } else { $event = arcadeGetEventTypes($id_event); } $replacements = array('ARCADE_SETTINGS_URL' => $scripturl . '?action=profile;area=arcadeSettings'); $pms = array(); $event['func']($event, $replacements, $pms, $data); if (empty($pms)) { return true; } require_once $sourcedir . '/Subs-Post.php'; $request = $smcFunc['db_query']('', ' SELECT mem.id_member, mem.email_address, mem.notify_regularity, mem.notify_send_body, mem.lngfile FROM {db_prefix}members AS mem WHERE mem.id_member IN({array_int:members}) ORDER BY mem.lngfile', array('members' => array_keys($pms))); while ($rowmember = $smcFunc['db_fetch_assoc']($request)) { $replacements['USERID'] = $rowmember['id_member']; $replacements['PROFILE'] = $scripturl . '?action=profile;u=' . $rowmember['id_member']; $emailtype = 'notification_arcade_' . $pms[$rowmember['id_member']]; loadLanguage('ArcadeEmail', empty($rowmember['lngfile']) || empty($modSettings['userLanguage']) ? $language : $rowmember['lngfile'], false); $emaildata = loadEmailTemplate($emailtype, $replacements, '', false); sendmail($rowmember['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 4); unset($notification); } return true; }