attach(build_keep_post_fields(($_lead_source_description == '') ? [] : ['_lead_source_description'])); $hidden->attach(form_input_hidden('_joining', '1')); if ($_lead_source_description != '') { $hidden->attach(form_input_hidden('_lead_source_description', $_lead_source_description)); } $groups = cns_get_all_default_groups(true); $primary_group = either_param_integer('primary_group', null); if (($primary_group !== null) && (!in_array($primary_group, $groups))) { // Check security $test = $GLOBALS['FORUM_DB']->query_select_value('f_groups', 'g_is_presented_at_install', ['id' => $primary_group]); if ($test == 1) { $groups = cns_get_all_default_groups(false); $hidden->attach(form_input_hidden('primary_group', strval($primary_group))); $groups[] = $primary_group; } } url_default_parameters__enable(); list($fields, $_hidden, $added_section) = cns_get_member_fields(true, '', null, '', '', null, $groups, null, null, null, null, null, null, null, null, 0, 1, 1, null, null, null, 1, null, 1, 1, 0, '*', '', 1, null, '0', 0, $adjusted_config_options); url_default_parameters__disable(); $hidden->attach($_hidden); if ($intro_message_if_enabled && addon_installed('cns_forum')) { $forum_id = get_option('intro_forum_id'); if ($forum_id != '') { $fields->attach(do_template('FORM_SCREEN_FIELD_SPACER', ['_GUID' => 'b8197832e4467b08e953535202235501', 'TITLE' => do_lang_tempcode('INTRODUCE_YOURSELF')])); $fields->attach(form_input_line(do_lang_tempcode('TITLE'), '', 'intro_title', do_lang('INTRO_POST_DEFAULT', '___'), false)); $fields->attach(form_input_text_comcode(do_lang_tempcode('POST_COMMENT'), do_lang_tempcode('DESCRIPTION_INTRO_POST'), 'intro_post', '', false)); } } if (($captcha_if_enabled) && (get_option('recaptcha_site_key') == '') && ($added_section)) { $fields->attach(do_template('FORM_SCREEN_FIELD_SPACER', ['_GUID' => 'a8197832e4467b08e953535202235501', 'TITLE' => do_lang_tempcode('SPECIAL_REGISTRATION_FIELDS')])); } /*PSEUDO-HOOK: cns_join_form special fields*/ $text = do_lang_tempcode('ENTER_PROFILE_DETAILS'); if ($captcha_if_enabled) { if (addon_installed('captcha')) { require_code('captcha'); if (use_captcha()) { $fields->attach(form_input_captcha($hidden)); $text->attach(' '); $text->attach(do_lang_tempcode('captcha:FORM_TIME_SECURITY')); } } } $submit_name = do_lang_tempcode('PROCEED'); return do_template('CNS_JOIN_FORM', [ '_GUID' => 'f6dba5638ae50a04562df50b1f217311', 'TEXT' => '', 'HIDDEN' => $hidden, 'FIELDS' => $fields, 'SUBMIT_ICON' => 'menu/site_meta/user_actions/join', 'SUBMIT_NAME' => $submit_name, 'URL' => $url, 'ANALYTIC_EVENT_CATEGORY' => do_lang('_JOIN'), 'USERNAME_CHECK_SCRIPT' => find_script('username_check'), 'SNIPPET_SCRIPT' => find_script('snippet'), 'INVITES_ENABLED' => $invites_if_enabled && (get_option_with_overrides('is_on_invites', $adjusted_config_options) == '1'), 'ONE_PER_EMAIL_ADDRESS' => (get_option_with_overrides('one_per_email_address', $adjusted_config_options) != '0'), 'USE_CAPTCHA' => $captcha_if_enabled && addon_installed('captcha') && use_captcha(), ]); } /** * Actualise the join form. * * @param LONG_TEXT $declarations_made A list of declarations to which the member agreed separated by a newline (blank: member did not agree to any declarations yet) * @param boolean $captcha_if_enabled Whether to handle CAPTCHA (if enabled at all) * @param boolean $intro_message_if_enabled Whether to ask for intro messages (if enabled at all) * @param boolean $invites_if_enabled Whether to check for invites (if enabled at all) * @param boolean $instant_login Whether to instantly log the user in * @param ?ID_TEXT $username Username (null: read from environment) * @param ?EMAIL $email_address E-mail address (null: read from environment) * @param ?string $password Password (null: read from environment) * @param ?array $actual_custom_fields Custom fields to save (null: read from environment) * @param array $adjusted_config_options A map of adjusted config options * @return array A tuple: Messages to show, member ID of new member, whether the account is ready */ function cns_join_actual(string $declarations_made = '', bool $captcha_if_enabled = true, bool $intro_message_if_enabled = true, bool $invites_if_enabled = true, bool $instant_login = true, ?string $username = null, ?string $email_address = null, ?string $password = null, ?array $actual_custom_fields = null, array $adjusted_config_options = []) : array { cns_require_all_forum_stuff(); require_css('cns'); require_code('cns_members_action'); require_code('cns_members_action2'); // Load parental controls require_code('cns_parental_controls'); $pc = object_factory('Source_parental_controls', false, [false], true); // Read in data require_code('temporal2'); list($dob_year, $dob_month, $dob_day) = post_param_date_components('birthday'); if (($dob_year === null) || ($dob_month === null) || ($dob_day === null)) { if (member_field_is_required(null, 'dob', null, null, $adjusted_config_options)) { warn_exit(do_lang_tempcode('NO_PARAMETER_SENT', 'birthday')); } $dob_day = null; $dob_month = null; $dob_year = null; } $reveal_age = post_param_integer('reveal_age', 0); $timezone = post_param_string('timezone', null); if ($timezone === null) { if (member_field_is_required(null, 'timezone_offset', null, null, $adjusted_config_options)) { warn_exit(do_lang_tempcode('NO_PARAMETER_SENT', 'timezone')); } $timezone = get_users_timezone(); } require_code('locations'); $region = post_param_region('region', ''); if ($region == '') { if (member_field_is_required(null, 'region', null, null, $adjusted_config_options)) { warn_exit(do_lang_tempcode('NO_PARAMETER_SENT', 'region')); } $region = get_region(); } // Run a lockout check to see if this member is allowed to create an account given the provided information $age = to_epoch_interval_index(utctime_to_usertime(time()), 'years', utctime_to_usertime(cms_gmmktime(0, 0, 0, $dob_month, $dob_day, $dob_year))); $lockout_info = $pc->run('lockout', $age, $region, ['check_join' => true]); if ($lockout_info !== null) { warn_exit($lockout_info['message']); } if ($username === null) { $username = post_param_string('username', false, INPUT_FILTER_POST_IDENTIFIER); } cns_check_name_valid($username, null, null, null, null, true); // Adjusts username if needed; other errors are ignored and will be picked up in cns_make_member's call to cns_check_name_valid if ($password === null) { $password = post_param_string('password', false, INPUT_FILTER_PASSWORD); $password_confirm = post_param_string('password_confirm', false, INPUT_FILTER_PASSWORD); if ($password != $password_confirm) { warn_exit(make_string_tempcode(escape_html(do_lang('PASSWORD_MISMATCH')))); } } if ($email_address === null) { $confirm_email_address = post_param_string('email_address_confirm', null); $email_address = post_param_string('email', member_field_is_required(null, 'email_address', null, null, $adjusted_config_options) ? false : '', INPUT_FILTER_POST_IDENTIFIER); if ($confirm_email_address !== null) { if (trim($confirm_email_address) != $email_address) { warn_exit(make_string_tempcode(escape_html(do_lang('EMAIL_ADDRESS_MISMATCH')))); } } require_code('type_sanitisation'); if (!is_valid_email_address($email_address)) { warn_exit(do_lang_tempcode('INVALID_EMAIL_ADDRESS')); } } // Check e-mail domain, if applicable $email_address = post_param_string('email', false, INPUT_FILTER_POST_IDENTIFIER); if ($email_address != '') { $valid_email_domains = get_option_with_overrides('valid_email_domains', $adjusted_config_options); if ($valid_email_domains != '') { $domains = explode(',', $valid_email_domains); $ok = false; foreach ($domains as $domain) { if (substr($email_address, -strlen('@' . $domain)) == '@' . $domain) { $ok = true; } } if (!$ok) { warn_exit(do_lang_tempcode('_MUST_BE_EMAIL_DOMAIN', escape_html($valid_email_domains))); } } } if ($invites_if_enabled) { // code branch also triggers general tracking of referrals if (get_option_with_overrides('is_on_invites', $adjusted_config_options) == '1') { $test = $GLOBALS['FORUM_DB']->query_select_value_if_there('f_invites', 'i_invite_member', ['i_email_address' => $email_address, 'i_taken' => 0]); if ($test === null) { warn_exit(do_lang_tempcode('NO_INVITE')); } } /*PSEUDO-HOOK: cns_join_actual referrals*/ $GLOBALS['FORUM_DB']->query_update('f_invites', ['i_taken' => 1], ['i_email_address' => $email_address, 'i_taken' => 0], '', 1); } $language = post_param_string('language', user_lang()); if (get_option_with_overrides('member_email_receipt_configurability', $adjusted_config_options) == '0') { $allow_emails = 1; } else { $allow_emails = post_param_integer('allow_emails', 0); } if (get_option_with_overrides('staff_email_receipt_configurability', $adjusted_config_options) == '0') { $allow_emails_from_staff = 1; } else { $allow_emails_from_staff = post_param_integer('allow_emails_from_staff', 0); } $groups = cns_get_all_default_groups(true); // $groups will contain the built-in default primary group too (it is not $secondary_groups) $primary_group = post_param_integer('primary_group', null); if (($primary_group !== null) && (!in_array($primary_group, $groups)/*= not built-in default, which is automatically ok to join without extra security*/)) { // Check security $test = $GLOBALS['FORUM_DB']->query_select_value('f_groups', 'g_is_presented_at_install', ['id' => $primary_group]); if ($test == 1) { $groups = cns_get_all_default_groups(false); // Get it so it does not include the built-in default primary group $groups[] = $primary_group; // And add in the *chosen* primary group } else { $primary_group = null; } } else { $primary_group = null; } if ($primary_group === null) { // Security error, or built-in default (which will already be in $groups) $primary_group = get_first_default_group(); } $custom_fields = cns_get_all_custom_fields_match( $groups, // groups null, // public view null, // owner view null, // owner set null, // required null, // show in posts null, // show in post previews null, // special start true, // show on join form $adjusted_config_options ); if ($actual_custom_fields === null) { $actual_custom_fields = cns_read_in_custom_fields($custom_fields); } // Check that the given address isn't already used (if one_per_email_address on) $member_id = null; if (get_option_with_overrides('one_per_email_address', $adjusted_config_options) != '0') { $test = $GLOBALS['FORUM_DB']->query_select('f_members', ['id', 'm_username'], ['m_email_address' => $email_address], '', 1); if (array_key_exists(0, $test)) { if ($test[0]['m_username'] != $username) { $reset_url = build_url(['page' => 'lost_password', 'email' => $email_address], get_module_zone('lost_password')); warn_exit(do_lang_tempcode('EMAIL_ADDRESS_IN_USE', escape_html(get_site_name()), escape_html($reset_url->evaluate()))); } $member_id = $test[0]['id']; } } // Check RBL's/stopforumspam $spam_check_level = get_option_with_overrides('spam_check_level', $adjusted_config_options); if (($spam_check_level == 'EVERYTHING') || ($spam_check_level == 'ACTIONS') || ($spam_check_level == 'GUESTACTIONS') || ($spam_check_level == 'JOINING')) { require_code('antispam'); check_for_spam($username, $email_address, false); } if ($captcha_if_enabled) { if (addon_installed('captcha')) { require_code('captcha'); enforce_captcha(); } } if (addon_installed('ldap')) { require_code('cns_ldap'); if (cns_is_ldap_member_potential($username)) { warn_exit(do_lang_tempcode('DUPLICATE_JOIN_AUTH')); } } if (addon_installed('stats')) { require_code('stats'); log_stats_event('_JOIN'); } require_code('temporal'); // Add member require_code('crypt'); $email_validation = (get_option_with_overrides('email_confirm_join', $adjusted_config_options) == '1'); $validated_email_confirm_code = $email_validation ? strval(get_secure_random_number()) : ''; $staff_validation = (get_option_with_overrides('require_new_member_validation', $adjusted_config_options) == '1'); $validated = (($staff_validation) ? 0 : 1); if ($member_id === null) { $member_id = cns_make_member( $username, // username $password, // password $email_address, // email_address $primary_group, // primary_group $groups, // secondary_groups $dob_day, // dob_day $dob_month, // dob_month $dob_year, // dob_year $actual_custom_fields, // custom_fields $timezone, // timezone $region, // Region $language, // language '', // theme '', // title '', // photo_url null, // avatar_url '', // signature null, // preview_posts $reveal_age, // reveal_age 1, // views_signatures null, // auto_monitor_contrib_content null, // smart_topic_notification null, // mailing_list_style 1, // auto_mark_read null, // sound_enabled $allow_emails, // allow_emails $allow_emails_from_staff, // allow_emails_from_staff 0, // highlighted_name '*', // pt_allow '', // pt_rules_text $validated, // validated $validated_email_confirm_code, // validated_email_confirm_code null, // probation_expiration_time '0', // is_perm_banned true // check_correctness ); } else { attach_message(do_lang_tempcode('ALREADY_EXISTS', escape_html($username)), 'notice'); } // Save declarations $GLOBALS['FORUM_DRIVER']->set_custom_field($member_id, 'agreed_declarations', $declarations_made); // Run parental consent checks and notification when necessary $age = to_epoch_interval_index(utctime_to_usertime(time()), 'years', utctime_to_usertime(cms_gmmktime(0, 0, 0, $dob_month, $dob_day, $dob_year))); $parental_consent_info = $pc->run('parental_consent', $age, $region, ['member_id' => $member_id]); // Send confirm mail if ($email_validation) { $zone = get_module_zone('join'); $_url = build_url(['page' => 'join', 'type' => 'step4', 'email' => $email_address, 'code' => $validated_email_confirm_code], $zone, [], false, false, true); $url = $_url->evaluate(); $_url_simple = build_url(['page' => 'join', 'type' => 'step4'], $zone, [], false, false, true); $url_simple = $_url_simple->evaluate(); $redirect = get_param_string('redirect', '', INPUT_FILTER_URL_INTERNAL); if ($redirect != '') { $url .= '&redirect=' . cms_urlencode(static_evaluate_tempcode(protect_url_parameter($redirect))); } $message = do_lang('CNS_SIGNUP_TEXT', comcode_escape(get_site_name()), comcode_escape($url), [$url_simple, $email_address, $validated_email_confirm_code], $language); require_code('mail'); if ($parental_consent_info === null) { dispatch_mail(do_lang('CONFIRM_EMAIL_SUBJECT', get_site_name(), null, null, $language), $message, do_lang('mail:NO_MAIL_WEB_VERSION__SENSITIVE'), [$email_address], $username, '', '', ['bypass_queue' => true]); } } // Run form handlers for joining $hook_obs = find_all_hook_obs('form_handlers', 'join', 'Hook_form_handlers_join_'); foreach ($hook_obs as $hook => $ob) { $ob->run($member_id, $username, $email_address, $dob_day, $dob_month, $dob_year, $actual_custom_fields, $timezone, $validated, $language, $allow_emails, $allow_emails_from_staff, get_ip_address()); } // Send 'validate this member' notification if ($staff_validation) { require_code('notifications'); $_validation_url = build_url(['page' => 'members', 'type' => 'view', 'id' => $member_id, 'validated' => 1], get_module_zone('members'), [], false, false, true, 'tab--edit'); $validation_url = $_validation_url->evaluate(); $message = do_notification_lang('VALIDATE_NEW_MEMBER_MAIL', comcode_escape($username), comcode_escape($validation_url), comcode_escape(strval($member_id)), get_site_default_lang()); Source_notification_dispatcher::dispatch_notification('cns_member_needs_validation', null, do_lang('VALIDATE_NEW_MEMBER_SUBJECT', $username, null, null, get_site_default_lang()), $message, null, A_FROM_SYSTEM_PRIVILEGED); } // Send new member notification require_code('notifications'); $_member_url = build_url(['page' => 'members', 'type' => 'view', 'id' => $member_id], get_module_zone('members'), [], false, false, true); $member_url = $_member_url->evaluate(); $message = do_notification_lang('NEW_MEMBER_NOTIFICATION_MAIL', comcode_escape($username), comcode_escape(get_site_name()), [comcode_escape($member_url), comcode_escape(strval($member_id))], get_site_default_lang()); Source_notification_dispatcher::dispatch_notification('cns_new_member', null, do_lang('NEW_MEMBER_NOTIFICATION_MAIL_SUBJECT', $username, get_site_name(), null, get_site_default_lang()), $message, null, A_FROM_SYSTEM_PRIVILEGED); // Intro post if ($intro_message_if_enabled && addon_installed('cns_forum')) { $forum_id = get_option('intro_forum_id'); if ($forum_id != '') { if (!is_numeric($forum_id)) { $_forum_id = $GLOBALS['FORUM_DB']->query_select_value('f_forums', 'id', ['f_name' => $forum_id]); if ($_forum_id === null) { $forum_id = strval(db_get_first_id()); } else { $forum_id = strval($_forum_id); } } $intro_title = post_param_string('intro_title', ''); $intro_post = post_param_string('intro_post', ''); if ($intro_post != '') { require_code('cns_topics_action'); $initial_validated = 1; if ($intro_title == '') { $intro_title = do_lang('INTRO_POST_DEFAULT', $username); } $topic_id = cns_make_topic(intval($forum_id), '', '', $initial_validated, 1, 0, 0, null, null, false); require_code('cns_posts_action'); cns_make_post($topic_id, $intro_title, $intro_post, 0, true, $initial_validated, 0, null, null, null, $member_id, null, null, null, false); } } } // Alert user to situation $message = new Tempcode(); $ready = false; if ($parental_consent_info !== null) { if ($email_validation) { $message->attach(do_lang_tempcode('CNS_WAITING_CONFIRM_MAIL')); } $message->attach(do_lang_tempcode('CNS_WAITING_CONFIRM_MAIL_PARENTAL_CONSENT')); } elseif ($staff_validation) { if ($email_validation) { $message->attach(do_lang_tempcode('CNS_WAITING_CONFIRM_MAIL')); } $message->attach(do_lang_tempcode('CNS_WAITING_CONFIRM_MAIL_VALIDATED', escape_html(get_custom_base_url()))); } elseif (!$email_validation) { if (($instant_login) && (!$GLOBALS['IS_ACTUALLY_ADMIN'])) { // Automatic instant log in require_code('users_active_actions'); handle_active_login($username); // The auto-login simulates a real login, i.e. actually checks the password from the form against the real account. So no security hole when "re-registering" a real user $message->attach(do_lang_tempcode('CNS_LOGIN_AUTO')); } else { // Invite them to explicitly instant log in $redirect = get_param_string('redirect', (get_page_name() == 'join') ? null : get_self_url(true), INPUT_FILTER_URL_INTERNAL); $_login_url = build_url(['page' => 'login', 'type' => 'browse', 'redirect' => protect_url_parameter($redirect)], get_module_zone('login')); $login_url = $_login_url->evaluate(); $message->attach(do_lang_tempcode('CNS_LOGIN_INSTANT', escape_html($login_url))); } $ready = true; } else { if ($email_validation) { $message->attach(do_lang_tempcode('CNS_WAITING_CONFIRM_MAIL')); } $message->attach(do_lang_tempcode('CNS_WAITING_CONFIRM_MAIL_INSTANT')); } $message = protect_from_escaping($message); /*PSEUDO-HOOK: cns_join_actual ends*/ return [$message, $member_id, $ready]; }