PageRenderTime 57ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/forum/Sources/Register.php

https://github.com/leftnode/nooges.com
PHP | 855 lines | 579 code | 129 blank | 147 comment | 187 complexity | 4f5368ca2c09bdf581b82411664bdaa2 MD5 | raw file
  1. <?php
  2. /**********************************************************************************
  3. * Register.php *
  4. ***********************************************************************************
  5. * SMF: Simple Machines Forum *
  6. * Open-Source Project Inspired by Zef Hemel (zef@zefhemel.com) *
  7. * =============================================================================== *
  8. * Software Version: SMF 2.0 RC2 *
  9. * Software by: Simple Machines (http://www.simplemachines.org) *
  10. * Copyright 2006-2009 by: Simple Machines LLC (http://www.simplemachines.org) *
  11. * 2001-2006 by: Lewis Media (http://www.lewismedia.com) *
  12. * Support, News, Updates at: http://www.simplemachines.org *
  13. ***********************************************************************************
  14. * This program is free software; you may redistribute it and/or modify it under *
  15. * the terms of the provided license as published by Simple Machines LLC. *
  16. * *
  17. * This program is distributed in the hope that it is and will be useful, but *
  18. * WITHOUT ANY WARRANTIES; without even any implied warranty of MERCHANTABILITY *
  19. * or FITNESS FOR A PARTICULAR PURPOSE. *
  20. * *
  21. * See the "license.txt" file for details of the Simple Machines license. *
  22. * The latest version can always be found at http://www.simplemachines.org. *
  23. **********************************************************************************/
  24. if (!defined('SMF'))
  25. die('Hacking attempt...');
  26. /* This file has two main jobs, but they really are one. It registers new
  27. members, and it helps the administrator moderate member registrations.
  28. Similarly, it handles account activation as well.
  29. void Register()
  30. // !!!
  31. void Register2()
  32. // !!!
  33. void Activate()
  34. // !!!
  35. void CoppaForm()
  36. // !!!
  37. void RegisterCheckUsername()
  38. // !!!
  39. */
  40. // Begin the registration process.
  41. function Register($reg_errors = array())
  42. {
  43. global $txt, $boarddir, $context, $settings, $modSettings, $user_info;
  44. global $language, $scripturl, $smcFunc, $sourcedir, $smcFunc, $cur_profile;
  45. // Is this an incoming AJAX check?
  46. if (isset($_GET['sa']) && $_GET['sa'] == 'usernamecheck')
  47. return RegisterCheckUsername();
  48. // Check if the administrator has it disabled.
  49. if (!empty($modSettings['registration_method']) && $modSettings['registration_method'] == 3)
  50. fatal_lang_error('registration_disabled', false);
  51. // If this user is an admin - redirect them to the admin registration page.
  52. if (allowedTo('moderate_forum') && !$user_info['is_guest'])
  53. redirectexit('action=admin;area=regcenter;sa=register');
  54. // You are not a guest, so you are a member - and members don't get to register twice!
  55. elseif (empty($user_info['is_guest']))
  56. redirectexit();
  57. loadLanguage('Login');
  58. loadTemplate('Register');
  59. // Do we need them to agree to the registration agreement, first?
  60. $context['require_agreement'] = !empty($modSettings['requireAgreement']);
  61. $context['registration_passed_agreement'] = !empty($_SESSION['registration_agreed']);
  62. $context['show_coppa'] = !empty($modSettings['coppaAge']);
  63. // Under age restrictions?
  64. if ($context['show_coppa'])
  65. {
  66. $context['skip_coppa'] = false;
  67. $context['coppa_agree_above'] = sprintf($txt['agreement_agree_coppa_above'], $modSettings['coppaAge']);
  68. $context['coppa_agree_below'] = sprintf($txt['agreement_agree_coppa_below'], $modSettings['coppaAge']);
  69. }
  70. // What step are we at?
  71. $current_step = isset($_REQUEST['step']) ? (int) $_REQUEST['step'] : ($context['require_agreement'] ? 1 : 2);
  72. // Does this user agree to the registation agreement?
  73. if ($current_step == 1 && (isset($_POST['accept_agreement']) || isset($_POST['accept_agreement_coppa'])))
  74. {
  75. $context['registration_passed_agreement'] = $_SESSION['registration_agreed'] = true;
  76. $current_step = 2;
  77. // Skip the coppa procedure if the user says he's old enough.
  78. if ($context['show_coppa'])
  79. {
  80. $_SESSION['skip_coppa'] = !empty($_POST['accept_agreement']);
  81. // Are they saying they're under age, while under age registration is disabled?
  82. if (empty($modSettings['coppaType']) && empty($_SESSION['skip_coppa']))
  83. {
  84. loadLanguage('Login');
  85. fatal_lang_error('under_age_registration_prohibited', false, array($modSettings['coppaAge']));
  86. }
  87. }
  88. }
  89. // Make sure they don't squeeze through without agreeing.
  90. elseif ($current_step > 1 && $context['require_agreement'] && !$context['registration_passed_agreement'])
  91. $current_step = 1;
  92. // Show the user the right form.
  93. $context['sub_template'] = $current_step == 1 ? 'registration_agreement' : 'registration_form';
  94. $context['page_title'] = $current_step == 1 ? $txt['registration_agreement'] : $txt['registration_form'];
  95. // Add the register chain to the link tree.
  96. $context['linktree'][] = array(
  97. 'url' => $scripturl . '?action=register',
  98. 'name' => $txt['register'],
  99. );
  100. // If you have to agree to the agreement, it needs to be fetched from the file.
  101. if ($context['require_agreement'])
  102. {
  103. // Have we got a localized one?
  104. if (file_exists($boarddir . '/agreement.' . $user_info['language'] . '.txt'))
  105. $context['agreement'] = parse_bbc(file_get_contents($boarddir . '/agreement.' . $user_info['language'] . '.txt'), true, 'agreement_' . $user_info['language']);
  106. elseif (file_exists($boarddir . '/agreement.txt'))
  107. $context['agreement'] = parse_bbc(file_get_contents($boarddir . '/agreement.txt'), true, 'agreement');
  108. else
  109. $context['agreement'] = '';
  110. }
  111. if (!empty($modSettings['userLanguage']))
  112. {
  113. $selectedLanguage = empty($_SESSION['language']) ? $language : $_SESSION['language'];
  114. // Do we have any languages?
  115. if (empty($context['languages']))
  116. getLanguages();
  117. // Try to find our selected language.
  118. foreach ($context['languages'] as $key => $lang)
  119. {
  120. $context['languages'][$key]['name'] = strtr($lang['name'], array('-utf8' => ''));
  121. // Found it!
  122. if ($selectedLanguage == $lang['filename'])
  123. $context['languages'][$key]['selected'] = true;
  124. }
  125. }
  126. // Any custom fields we want filled in?
  127. require_once($sourcedir . '/Profile.php');
  128. loadCustomFields(0, 'register');
  129. // Or any standard ones?
  130. if (!empty($modSettings['registration_fields']))
  131. {
  132. require_once($sourcedir . '/Profile-Modify.php');
  133. // Setup some important context.
  134. loadLanguage('Profile');
  135. loadTemplate('Profile');
  136. $context['user']['is_owner'] = true;
  137. // Here, and here only, emulate the permissions the user would have to do this.
  138. $user_info['permissions'] = array_merge($user_info['permissions'], array('profile_account_own', 'profile_extra_own'));
  139. $reg_fields = explode(',', $modSettings['registration_fields']);
  140. // We might have had some submissions on this front - go check.
  141. foreach ($reg_fields as $field)
  142. if (isset($_POST[$field]))
  143. $cur_profile[$field] = $smcFunc['htmlspecialchars']($_POST[$field]);
  144. // Load all the fields in question.
  145. setupProfileContext($reg_fields);
  146. }
  147. // Generate a visual verification code to make sure the user is no bot.
  148. if (!empty($modSettings['reg_verification']))
  149. {
  150. require_once($sourcedir . '/Subs-Editor.php');
  151. $verificationOptions = array(
  152. 'id' => 'register',
  153. );
  154. $context['visual_verification'] = create_control_verification($verificationOptions);
  155. $context['visual_verification_id'] = $verificationOptions['id'];
  156. }
  157. // Otherwise we have nothing to show.
  158. else
  159. $context['visual_verification'] = false;
  160. // Are they coming from an OpenID login attempt?
  161. if (!empty($_SESSION['openid']['verified']) && !empty($_SESSION['openid']['openid_uri']))
  162. {
  163. $context['openid'] = $_SESSION['openid']['openid_uri'];
  164. $context['username'] = $smcFunc['htmlspecialchars'](!empty($_POST['user']) ? $_POST['user'] : $_SESSION['openid']['nickname']);
  165. $context['email'] = $smcFunc['htmlspecialchars'](!empty($_POST['email']) ? $_POST['email'] : $_SESSION['openid']['email']);
  166. }
  167. // See whether we have some prefiled values.
  168. else
  169. {
  170. $context += array(
  171. 'openid' => isset($_POST['openid_identifier']) ? $_POST['openid_identifier'] : '',
  172. 'username' => isset($_POST['user']) ? $smcFunc['htmlspecialchars']($_POST['user']) : '',
  173. 'email' => isset($_POST['email']) ? $smcFunc['htmlspecialchars']($_POST['email']) : '',
  174. );
  175. }
  176. // !!! Why isn't this a simple set operation?
  177. // Were there any errors?
  178. $context['registration_errors'] = array();
  179. if (!empty($reg_errors))
  180. foreach ($reg_errors as $error)
  181. $context['registration_errors'][] = $error;
  182. }
  183. // Actually register the member.
  184. function Register2($verifiedOpenID = false)
  185. {
  186. global $scripturl, $txt, $modSettings, $context, $sourcedir;
  187. global $user_info, $options, $settings, $smcFunc;
  188. // Start collecting together any errors.
  189. $reg_errors = array();
  190. // Did we save some open ID fields?
  191. if ($verifiedOpenID && !empty($context['openid_save_fields']))
  192. {
  193. foreach ($context['openid_save_fields'] as $id => $value)
  194. $_POST[$id] = $value;
  195. }
  196. // You can't register if it's disabled.
  197. if (!empty($modSettings['registration_method']) && $modSettings['registration_method'] == 3)
  198. fatal_lang_error('registration_disabled', false);
  199. // Things we don't do for people who have already confirmed their OpenID allegances via register.
  200. if (!$verifiedOpenID)
  201. {
  202. // Well, if you don't agree, you can't register.
  203. if (!empty($modSettings['requireAgreement']) && empty($_SESSION['registration_agreed']))
  204. redirectexit();
  205. // Make sure they came from *somewhere*, have a session.
  206. if (!isset($_SESSION['old_url']))
  207. redirectexit('action=register');
  208. // Are they under age, and under age users are banned?
  209. if (!empty($modSettings['coppaAge']) && empty($modSettings['coppaType']) && empty($_SESSION['skip_coppa']))
  210. {
  211. // !!! This should be put in Errors, imho.
  212. loadLanguage('Login');
  213. fatal_lang_error('under_age_registration_prohibited', false, array($modSettings['coppaAge']));
  214. }
  215. // Check whether the visual verification code was entered correctly.
  216. if (!empty($modSettings['reg_verification']))
  217. {
  218. require_once($sourcedir . '/Subs-Editor.php');
  219. $verificationOptions = array(
  220. 'id' => 'register',
  221. );
  222. $context['visual_verification'] = create_control_verification($verificationOptions, true);
  223. if (is_array($context['visual_verification']))
  224. {
  225. loadLanguage('Errors');
  226. foreach ($context['visual_verification'] as $error)
  227. $reg_errors[] = $txt['error_' . $error];
  228. }
  229. }
  230. }
  231. foreach ($_POST as $key => $value)
  232. {
  233. if (!is_array($_POST[$key]))
  234. $_POST[$key] = htmltrim__recursive(str_replace(array("\n", "\r"), '', $_POST[$key]));
  235. }
  236. // Collect all extra registration fields someone might have filled in.
  237. $possible_strings = array(
  238. 'website_url', 'website_title',
  239. 'aim', 'yim',
  240. 'location', 'birthdate',
  241. 'time_format',
  242. 'buddy_list',
  243. 'pm_ignore_list',
  244. 'smiley_set',
  245. 'signature', 'personal_text', 'avatar',
  246. 'lngfile',
  247. 'secret_question', 'secret_answer',
  248. );
  249. $possible_ints = array(
  250. 'pm_email_notify',
  251. 'notify_types',
  252. 'icq',
  253. 'gender',
  254. 'id_theme',
  255. );
  256. $possible_floats = array(
  257. 'time_offset',
  258. );
  259. $possible_bools = array(
  260. 'notify_announcements', 'notify_regularity', 'notify_send_body',
  261. 'hide_email', 'show_online',
  262. );
  263. if (isset($_POST['secret_answer']) && $_POST['secret_answer'] != '')
  264. $_POST['secret_answer'] = md5($_POST['secret_answer']);
  265. // Needed for isReservedName() and registerMember().
  266. require_once($sourcedir . '/Subs-Members.php');
  267. // Validation... even if we're not a mall.
  268. if (isset($_POST['real_name']) && (!empty($modSettings['allow_editDisplayName']) || allowedTo('moderate_forum')))
  269. {
  270. $_POST['real_name'] = trim(preg_replace('~[\s]~' . ($context['utf8'] ? 'u' : ''), ' ', $_POST['real_name']));
  271. if (trim($_POST['real_name']) != '' && !isReservedName($_POST['real_name']) && $smcFunc['strlen']($_POST['real_name']) < 60)
  272. $possible_strings[] = 'real_name';
  273. }
  274. if (isset($_POST['msn']) && preg_match('~^[0-9A-Za-z=_+\-/][0-9A-Za-z=_\'+\-/\.]*@[\w\-]+(\.[\w\-]+)*(\.[\w]{2,6})$~', $_POST['msn']) != 0)
  275. $profile_strings[] = 'msn';
  276. // Handle a string as a birthdate...
  277. if (isset($_POST['birthdate']) && $_POST['birthdate'] != '')
  278. $_POST['birthdate'] = strftime('%Y-%m-%d', strtotime($_POST['birthdate']));
  279. // Or birthdate parts...
  280. elseif (!empty($_POST['bday1']) && !empty($_POST['bday2']))
  281. $_POST['birthdate'] = sprintf('%04d-%02d-%02d', empty($_POST['bday3']) ? 0 : (int) $_POST['bday3'], (int) $_POST['bday1'], (int) $_POST['bday2']);
  282. // By default assume email is hidden, only show it if we tell it to.
  283. $_POST['hide_email'] = !empty($_POST['allow_email']) ? 0 : 1;
  284. // Validate the passed language file.
  285. if (isset($_POST['lngfile']) && !empty($modSettings['userLanguage']))
  286. {
  287. // Do we have any languages?
  288. if (empty($context['languages']))
  289. getLanguages();
  290. // Did we find it?
  291. if (isset($context['languages'][$_POST['lngfile']]))
  292. $_SESSION['language'] = $_POST['lngfile'];
  293. else
  294. unset($_POST['lngfile']);
  295. }
  296. else
  297. unset($_POST['lngfile']);
  298. // Set the options needed for registration.
  299. $regOptions = array(
  300. 'interface' => 'guest',
  301. 'username' => !empty($_POST['user']) ? $_POST['user'] : '',
  302. 'email' => !empty($_POST['email']) ? $_POST['email'] : '',
  303. 'password' => !empty($_POST['passwrd1']) ? $_POST['passwrd1'] : '',
  304. 'password_check' => !empty($_POST['passwrd2']) ? $_POST['passwrd2'] : '',
  305. 'openid' => !empty($_POST['openid_identifier']) ? $_POST['openid_identifier'] : '',
  306. 'auth_method' => !empty($_POST['authenticate']) ? $_POST['authenticate'] : '',
  307. 'check_reserved_name' => true,
  308. 'check_password_strength' => true,
  309. 'check_email_ban' => true,
  310. 'send_welcome_email' => !empty($modSettings['send_welcomeEmail']),
  311. 'require' => !empty($modSettings['coppaAge']) && !$verifiedOpenID && empty($_SESSION['skip_coppa']) ? 'coppa' : (empty($modSettings['registration_method']) ? 'nothing' : ($modSettings['registration_method'] == 1 ? 'activation' : 'approval')),
  312. 'extra_register_vars' => array(),
  313. 'theme_vars' => array(),
  314. );
  315. // Include the additional options that might have been filled in.
  316. foreach ($possible_strings as $var)
  317. if (isset($_POST[$var]))
  318. $regOptions['extra_register_vars'][$var] = $smcFunc['htmlspecialchars']($_POST[$var], ENT_QUOTES);
  319. foreach ($possible_ints as $var)
  320. if (isset($_POST[$var]))
  321. $regOptions['extra_register_vars'][$var] = (int) $_POST[$var];
  322. foreach ($possible_floats as $var)
  323. if (isset($_POST[$var]))
  324. $regOptions['extra_register_vars'][$var] = (float) $_POST[$var];
  325. foreach ($possible_bools as $var)
  326. if (isset($_POST[$var]))
  327. $regOptions['extra_register_vars'][$var] = empty($_POST[$var]) ? 0 : 1;
  328. // Registration options are always default options...
  329. if (isset($_POST['default_options']))
  330. $_POST['options'] = isset($_POST['options']) ? $_POST['options'] + $_POST['default_options'] : $_POST['default_options'];
  331. $regOptions['theme_vars'] = isset($_POST['options']) && is_array($_POST['options']) ? $_POST['options'] : array();
  332. // Make sure they are clean, dammit!
  333. $regOptions['theme_vars'] = htmlspecialchars__recursive($regOptions['theme_vars']);
  334. // If Quick Reply hasn't been set then set it to be shown but collapsed.
  335. if (!isset($regOptions['theme_vars']['display_quick_reply']))
  336. $regOptions['theme_vars']['display_quick_reply'] = 1;
  337. // Check whether we have fields that simply MUST be displayed?
  338. $request = $smcFunc['db_query']('', '
  339. SELECT col_name, field_name, field_type, field_length, mask, show_reg
  340. FROM {db_prefix}custom_fields
  341. WHERE active = {int:is_active}',
  342. array(
  343. 'is_active' => 1,
  344. )
  345. );
  346. $custom_field_errors = array();
  347. while ($row = $smcFunc['db_fetch_assoc']($request))
  348. {
  349. // Don't allow overriding of the theme variables.
  350. if (isset($regOptions['theme_vars'][$row['col_name']]))
  351. unset($regOptions['theme_vars'][$row['col_name']]);
  352. // Not actually showing it then?
  353. if (!$row['show_reg'])
  354. continue;
  355. // We only care for text fields as the others are valid to be empty.
  356. if (!in_array($row['field_type'], array('check', 'select', 'radio')))
  357. {
  358. $value = isset($_POST['customfield'][$row['col_name']]) ? trim($_POST['customfield'][$row['col_name']]) : '';
  359. // Is it too long?
  360. if ($row['field_length'] && $row['field_length'] < $smcFunc['strlen']($value))
  361. $custom_field_errors[] = array('custom_field_too_long', array($row['field_name'], $row['field_length']));
  362. // Any masks to apply?
  363. if ($row['field_type'] == 'text' && !empty($row['mask']) && $row['mask'] != 'none')
  364. {
  365. //!!! We never error on this - just ignore it at the moment...
  366. if ($row['mask'] == 'email' && (preg_match('~^[0-9A-Za-z=_+\-/][0-9A-Za-z=_\'+\-/\.]*@[\w\-]+(\.[\w\-]+)*(\.[\w]{2,6})$~', $value) === 0 || strlen($value) > 255))
  367. $custom_field_errors[] = array('custom_field_invalid_email', array($row['field_name']));
  368. elseif ($row['mask'] == 'number' && preg_match('~[^\d]~', $value))
  369. $custom_field_errors[] = array('custom_field_not_number', array($row['field_name']));
  370. elseif (substr($row['mask'], 0, 5) == 'regex' && preg_match(substr($row['mask'], 5), $value) === 0)
  371. $custom_field_errors[] = array('custom_field_inproper_format', array($row['field_name']));
  372. }
  373. // Is this required but not there?
  374. if (trim($value) == '' && $row['show_reg'] > 1)
  375. $custom_field_errors[] = array('custom_field_empty', array($row['field_name']));
  376. }
  377. }
  378. $smcFunc['db_free_result']($request);
  379. // Process any errors.
  380. if (!empty($custom_field_errors))
  381. {
  382. loadLanguage('Errors');
  383. foreach ($custom_field_errors as $error)
  384. $reg_errors[] = vsprintf($txt['error_' . $error[0]], $error[1]);
  385. }
  386. // Lets check for other errors before trying to register the member.
  387. if (!empty($reg_errors))
  388. {
  389. $_REQUEST['step'] = 2;
  390. return Register($reg_errors);
  391. }
  392. // If they're wanting to use OpenID we need to validate them first.
  393. if (empty($_SESSION['openid']['verified']) && !empty($_POST['authenticate']) && $_POST['authenticate'] == 'openid')
  394. {
  395. // What do we need to save?
  396. $save_variables = array();
  397. foreach ($_POST as $k => $v)
  398. if (!in_array($k, array('sc', 'sesc', $context['session_var'], 'passwrd1', 'passwrd2', 'regSubmit')))
  399. $save_variables[$k] = $v;
  400. require_once($sourcedir . '/Subs-OpenID.php');
  401. smf_openID_validate($_POST['openid_identifier'], false, $save_variables);
  402. }
  403. // If we've come from OpenID set up some default stuff.
  404. elseif ($verifiedOpenID || (!empty($_POST['openid_identifier']) && $_POST['authenticate'] == 'openid'))
  405. {
  406. $regOptions['username'] = !empty($_POST['user']) && trim($_POST['user']) != '' ? $_POST['user'] : $_SESSION['openid']['nickname'];
  407. $regOptions['email'] = !empty($_POST['email']) && trim($_POST['email']) != '' ? $_POST['email'] : $_SESSION['openid']['email'];
  408. $regOptions['auth_method'] = 'openid';
  409. $regOptions['openid'] = !empty($_POST['openid_identifier']) ? $_POST['openid_identifier'] : $_SESSION['openid']['openid_uri'];
  410. }
  411. $memberID = registerMember($regOptions, true);
  412. // What there actually an error of some kind dear boy?
  413. if (is_array($memberID))
  414. {
  415. $reg_errors = array_merge($reg_errors, $memberID);
  416. $_REQUEST['step'] = 2;
  417. return Register($reg_errors);
  418. }
  419. // Do our spam protection now.
  420. spamProtection('register');
  421. // We'll do custom fields after as then we get to use the helper function!
  422. if (!empty($_POST['customfield']))
  423. {
  424. require_once($sourcedir . '/Profile.php');
  425. require_once($sourcedir . '/Profile-Modify.php');
  426. makeCustomFieldChanges($memberID, 'register');
  427. }
  428. // If COPPA has been selected then things get complicated, setup the template.
  429. if (!empty($modSettings['coppaAge']) && empty($_SESSION['skip_coppa']))
  430. redirectexit('action=coppa;member=' . $memberID);
  431. // Basic template variable setup.
  432. elseif (!empty($modSettings['registration_method']))
  433. {
  434. loadTemplate('Register');
  435. $context += array(
  436. 'page_title' => $txt['register'],
  437. 'sub_template' => 'after',
  438. 'description' => $modSettings['registration_method'] == 2 ? $txt['approval_after_registration'] : $txt['activate_after_registration']
  439. );
  440. }
  441. else
  442. {
  443. if (isset($modSettings['integrate_login']) && function_exists($modSettings['integrate_login']))
  444. $modSettings['integrate_login']($regOptions['register_vars']['member_name'], $regOptions['register_vars']['passwd'], $modSettings['cookieTime']);
  445. setLoginCookie(60 * $modSettings['cookieTime'], $memberID, sha1(sha1(strtolower($regOptions['username']) . $regOptions['password']) . $regOptions['register_vars']['password_salt']));
  446. redirectexit('action=login2;sa=check;member=' . $memberID, $context['server']['needs_login_fix']);
  447. }
  448. }
  449. function Activate()
  450. {
  451. global $context, $txt, $modSettings, $scripturl, $sourcedir, $smcFunc, $language;
  452. loadLanguage('Login');
  453. loadTemplate('Login');
  454. if (empty($_REQUEST['u']) && empty($_POST['user']))
  455. {
  456. if (empty($modSettings['registration_method']) || $modSettings['registration_method'] == 3)
  457. fatal_lang_error('no_access', false);
  458. $context['member_id'] = 0;
  459. $context['sub_template'] = 'resend';
  460. $context['page_title'] = $txt['invalid_activation_resend'];
  461. $context['can_activate'] = empty($modSettings['registration_method']) || $modSettings['registration_method'] == 1;
  462. $context['default_username'] = isset($_GET['user']) ? $_GET['user'] : '';
  463. return;
  464. }
  465. // Get the code from the database...
  466. $request = $smcFunc['db_query']('', '
  467. SELECT id_member, validation_code, member_name, real_name, email_address, is_activated, passwd, lngfile
  468. FROM {db_prefix}members' . (empty($_REQUEST['u']) ? '
  469. WHERE member_name = {string:email_address} OR email_address = {string:email_address}' : '
  470. WHERE id_member = {int:id_member}') . '
  471. LIMIT 1',
  472. array(
  473. 'id_member' => isset($_REQUEST['u']) ? $_REQUEST['u'] : 0,
  474. 'email_address' => isset($_POST['user']) ? $_POST['user'] : '',
  475. )
  476. );
  477. // Does this user exist at all?
  478. if ($smcFunc['db_num_rows']($request) == 0)
  479. {
  480. $context['sub_template'] = 'retry_activate';
  481. $context['page_title'] = $txt['invalid_userid'];
  482. $context['member_id'] = 0;
  483. return;
  484. }
  485. $row = $smcFunc['db_fetch_assoc']($request);
  486. $smcFunc['db_free_result']($request);
  487. // Change their email address? (they probably tried a fake one first :P.)
  488. if (isset($_POST['new_email'], $_REQUEST['passwd']) && sha1(strtolower($row['member_name']) . $_REQUEST['passwd']) == $row['passwd'])
  489. {
  490. if (empty($modSettings['registration_method']) || $modSettings['registration_method'] == 3)
  491. fatal_lang_error('no_access', false);
  492. // !!! Separate the sprintf?
  493. if (preg_match('~^[0-9A-Za-z=_+\-/][0-9A-Za-z=_\'+\-/\.]*@[\w\-]+(\.[\w\-]+)*(\.[\w]{2,6})$~', $_POST['new_email']) == 0)
  494. fatal_error(sprintf($txt['valid_email_needed'], htmlspecialchars($_POST['new_email'])), false);
  495. // Make sure their email isn't banned.
  496. isBannedEmail($_POST['new_email'], 'cannot_register', $txt['ban_register_prohibited']);
  497. // Ummm... don't even dare try to take someone else's email!!
  498. $request = $smcFunc['db_query']('', '
  499. SELECT id_member
  500. FROM {db_prefix}members
  501. WHERE email_address = {string:email_address}
  502. LIMIT 1',
  503. array(
  504. 'email_address' => $_POST['new_email'],
  505. )
  506. );
  507. // !!! Separate the sprintf?
  508. if ($smcFunc['db_num_rows']($request) != 0)
  509. fatal_lang_error('email_in_use', false, array(htmlspecialchars($_POST['new_email'])));
  510. $smcFunc['db_free_result']($request);
  511. updateMemberData($row['id_member'], array('email_address' => $_POST['new_email']));
  512. $row['email_address'] = $_POST['new_email'];
  513. $email_change = true;
  514. }
  515. // Resend the password, but only if the account wasn't activated yet.
  516. if (!empty($_REQUEST['sa']) && $_REQUEST['sa'] == 'resend' && ($row['is_activated'] == 0 || $row['is_activated'] == 2) && (!isset($_REQUEST['code']) || $_REQUEST['code'] == ''))
  517. {
  518. require_once($sourcedir . '/Subs-Post.php');
  519. $replacements = array(
  520. 'REALNAME' => $row['real_name'],
  521. 'USERNAME' => $row['member_name'],
  522. 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $row['id_member'] . ';code=' . $row['validation_code'],
  523. 'ACTIVATIONCODE' => $row['validation_code'],
  524. 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder',
  525. );
  526. $emaildata = loadEmailTemplate('resend_activate_message', $replacements, empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']);
  527. sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 0);
  528. $context['page_title'] = $txt['invalid_activation_resend'];
  529. // This will ensure we don't actually get an error message if it works!
  530. $context['error_title'] = '';
  531. fatal_lang_error(!empty($email_change) ? 'change_email_success' : 'resend_email_success', false);
  532. }
  533. // Quit if this code is not right.
  534. if (empty($_REQUEST['code']) || $row['validation_code'] != $_REQUEST['code'])
  535. {
  536. if (!empty($row['is_activated']))
  537. fatal_lang_error('already_activated', false);
  538. elseif ($row['validation_code'] == '')
  539. {
  540. loadLanguage('Profile');
  541. fatal_error($txt['registration_not_approved'] . ' <a href="' . $scripturl . '?action=activate;user=' . $row['member_name'] . '">' . $txt['here'] . '</a>.', false);
  542. }
  543. $context['sub_template'] = 'retry_activate';
  544. $context['page_title'] = $txt['invalid_activation_code'];
  545. $context['member_id'] = $row['id_member'];
  546. return;
  547. }
  548. // Let the integration know that they've been activated!
  549. if (isset($modSettings['integrate_activate']) && function_exists($modSettings['integrate_activate']))
  550. call_user_func($modSettings['integrate_activate'], $row['member_name']);
  551. // Validation complete - update the database!
  552. updateMemberData($row['id_member'], array('is_activated' => 1, 'validation_code' => ''));
  553. // Also do a proper member stat re-evaluation.
  554. updateStats('member', false);
  555. if (!isset($_POST['new_email']))
  556. {
  557. require_once($sourcedir . '/Subs-Post.php');
  558. adminNotify('activation', $row['id_member'], $row['member_name']);
  559. }
  560. $context += array(
  561. 'page_title' => $txt['registration_successful'],
  562. 'sub_template' => 'login',
  563. 'default_username' => $row['member_name'],
  564. 'default_password' => '',
  565. 'never_expire' => false,
  566. 'description' => $txt['activate_success']
  567. );
  568. }
  569. // This function will display the contact information for the forum, as well a form to fill in.
  570. function CoppaForm()
  571. {
  572. global $context, $modSettings, $txt, $smcFunc;
  573. loadLanguage('Login');
  574. loadTemplate('Register');
  575. // No User ID??
  576. if (!isset($_GET['member']))
  577. fatal_lang_error('no_access', false);
  578. // Get the user details...
  579. $request = $smcFunc['db_query']('', '
  580. SELECT member_name
  581. FROM {db_prefix}members
  582. WHERE id_member = {int:id_member}
  583. AND is_activated = {int:is_coppa}',
  584. array(
  585. 'id_member' => (int) $_GET['member'],
  586. 'is_coppa' => 5,
  587. )
  588. );
  589. if ($smcFunc['db_num_rows']($request) == 0)
  590. fatal_lang_error('no_access', false);
  591. list ($username) = $smcFunc['db_fetch_row']($request);
  592. $smcFunc['db_free_result']($request);
  593. if (isset($_GET['form']))
  594. {
  595. // Some simple contact stuff for the forum.
  596. $context['forum_contacts'] = (!empty($modSettings['coppaPost']) ? $modSettings['coppaPost'] . '<br /><br />' : '') . (!empty($modSettings['coppaFax']) ? $modSettings['coppaFax'] . '<br />' : '');
  597. $context['forum_contacts'] = !empty($context['forum_contacts']) ? $context['forum_name_html_safe'] . '<br />' . $context['forum_contacts'] : '';
  598. // Showing template?
  599. if (!isset($_GET['dl']))
  600. {
  601. // Shortcut for producing underlines.
  602. $context['ul'] = '<u>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</u>';
  603. $context['template_layers'] = array();
  604. $context['sub_template'] = 'coppa_form';
  605. $context['page_title'] = $txt['coppa_form_title'];
  606. $context['coppa_body'] = str_replace(array('{PARENT_NAME}', '{CHILD_NAME}', '{USER_NAME}'), array($context['ul'], $context['ul'], $username), $txt['coppa_form_body']);
  607. }
  608. // Downloading.
  609. else
  610. {
  611. // The data.
  612. $ul = ' ';
  613. $crlf = "\r\n";
  614. $data = $context['forum_contacts'] . $crlf . $txt['coppa_form_address'] . ':' . $crlf . $txt['coppa_form_date'] . ':' . $crlf . $crlf . $crlf . $txt['coppa_form_body'];
  615. $data = str_replace(array('{PARENT_NAME}', '{CHILD_NAME}', '{USER_NAME}', '<br>', '<br />'), array($ul, $ul, $username, $crlf, $crlf), $data);
  616. // Send the headers.
  617. header('Connection: close');
  618. header('Content-Disposition: attachment; filename="approval.txt"');
  619. header('Content-Type: ' . ($context['browser']['is_ie'] || $context['browser']['is_opera'] ? 'application/octetstream' : 'application/octet-stream'));
  620. header('Content-Length: ' . count($data));
  621. echo $data;
  622. obExit(false);
  623. }
  624. }
  625. else
  626. {
  627. $context += array(
  628. 'page_title' => $txt['coppa_title'],
  629. 'sub_template' => 'coppa',
  630. );
  631. $context['coppa'] = array(
  632. 'body' => str_replace('{MINIMUM_AGE}', $modSettings['coppaAge'], $txt['coppa_after_registration']),
  633. 'many_options' => !empty($modSettings['coppaPost']) && !empty($modSettings['coppaFax']),
  634. 'post' => empty($modSettings['coppaPost']) ? '' : $modSettings['coppaPost'],
  635. 'fax' => empty($modSettings['coppaFax']) ? '' : $modSettings['coppaFax'],
  636. 'phone' => empty($modSettings['coppaPhone']) ? '' : str_replace('{PHONE_NUMBER}', $modSettings['coppaPhone'], $txt['coppa_send_by_phone']),
  637. 'id' => $_GET['member'],
  638. );
  639. }
  640. }
  641. // Show the verification code or let it hear.
  642. function VerificationCode()
  643. {
  644. global $sourcedir, $modSettings, $context, $scripturl;
  645. $verification_id = isset($_GET['vid']) ? $_GET['vid'] : '';
  646. $code = $verification_id && isset($_SESSION[$verification_id . '_vv']) ? $_SESSION[$verification_id . '_vv']['code'] : (isset($_SESSION['visual_verification_code']) ? $_SESSION['visual_verification_code'] : '');
  647. // Somehow no code was generated or the session was lost.
  648. if (empty($code))
  649. {
  650. header('Content-Type: image/gif');
  651. die("\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x21\xF9\x04\x01\x00\x00\x00\x00\x2C\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x44\x01\x00\x3B");
  652. }
  653. // Show a window that will play the verification code.
  654. elseif (isset($_REQUEST['sound']))
  655. {
  656. loadLanguage('Login');
  657. loadTemplate('Register');
  658. $context['verification_sound_href'] = $scripturl . '?action=verificationcode;rand=' . md5(mt_rand()) . ($verification_id ? ';vid=' . $verification_id : '') . ';format=.wav';
  659. $context['sub_template'] = 'verification_sound';
  660. $context['template_layers'] = array();
  661. obExit();
  662. }
  663. // If we have GD, try the nice code.
  664. elseif (empty($_REQUEST['format']))
  665. {
  666. require_once($sourcedir . '/Subs-Graphics.php');
  667. if (in_array('gd', get_loaded_extensions()) && !showCodeImage($code))
  668. header('HTTP/1.1 400 Bad Request');
  669. // Otherwise just show a pre-defined letter.
  670. elseif (isset($_REQUEST['letter']))
  671. {
  672. $_REQUEST['letter'] = (int) $_REQUEST['letter'];
  673. if ($_REQUEST['letter'] > 0 && $_REQUEST['letter'] <= strlen($code) && !showLetterImage(strtolower($code{$_REQUEST['letter'] - 1})))
  674. {
  675. header('Content-Type: image/gif');
  676. die("\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x21\xF9\x04\x01\x00\x00\x00\x00\x2C\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x44\x01\x00\x3B");
  677. }
  678. }
  679. // You must be up to no good.
  680. else
  681. {
  682. header('Content-Type: image/gif');
  683. die("\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x21\xF9\x04\x01\x00\x00\x00\x00\x2C\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x44\x01\x00\x3B");
  684. }
  685. }
  686. elseif ($_REQUEST['format'] === '.wav')
  687. {
  688. require_once($sourcedir . '/Subs-Sound.php');
  689. if (!createWaveFile($code))
  690. header('HTTP/1.1 400 Bad Request');
  691. }
  692. // We all die one day...
  693. die();
  694. }
  695. // See if a username already exists.
  696. function RegisterCheckUsername()
  697. {
  698. global $sourcedir, $smcFunc, $context, $txt;
  699. // This is XML!
  700. loadTemplate('Xml');
  701. $context['sub_template'] = 'check_username';
  702. $context['checked_username'] = isset($_GET['username']) ? $_GET['username'] : '';
  703. $context['valid_username'] = true;
  704. // Clean it up like mother would.
  705. $context['checked_username'] = preg_replace('~[\t\n\r\x0B\0' . ($context['utf8'] ? ($context['server']['complex_preg_chars'] ? '\x{A0}' : "\xC2\xA0") : '\xA0') . ']+~' . ($context['utf8'] ? 'u' : ''), ' ', $context['checked_username']);
  706. if ($smcFunc['strlen']($context['checked_username']) > 25)
  707. $context['checked_username'] = $smcFunc['htmltrim']($smcFunc['substr']($context['checked_username'], 0, 25));
  708. // Only these characters are permitted.
  709. if (preg_match('~[<>&"\'=\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $context['checked_username'])) != 0 || $context['checked_username'] == '_' || $context['checked_username'] == '|' || strpos($context['checked_username'], '[code') !== false || strpos($context['checked_username'], '[/code') !== false)
  710. $context['valid_username'] = false;
  711. if (stristr($context['checked_username'], $txt['guest_title']) !== false)
  712. $context['valid_username'] = false;
  713. if (trim($context['checked_username']) == '')
  714. $context['valid_username'] = false;
  715. else
  716. {
  717. require_once($sourcedir . '/Subs-Members.php');
  718. $context['valid_username'] &= isReservedName($context['checked_username'], 0, false, false) ? 0 : 1;
  719. }
  720. }
  721. ?>