ManageRegistration.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. <?php
  2. /**
  3. * This file helps the administrator setting registration settings and policy
  4. * as well as allow the administrator to register new members themselves.
  5. *
  6. * Simple Machines Forum (SMF)
  7. *
  8. * @package SMF
  9. * @author Simple Machines http://www.simplemachines.org
  10. * @copyright 2014 Simple Machines and individual contributors
  11. * @license http://www.simplemachines.org/about/smf/license.php BSD
  12. *
  13. * @version 2.1 Alpha 1
  14. */
  15. if (!defined('SMF'))
  16. die('No direct access...');
  17. /**
  18. * Entrance point for the registration center, it checks permissions and forwards
  19. * to the right function based on the subaction.
  20. * Accessed by ?action=admin;area=regcenter.
  21. * Requires either the moderate_forum or the admin_forum permission.
  22. *
  23. * @uses Login language file
  24. * @uses Register template.
  25. */
  26. function RegCenter()
  27. {
  28. global $context, $txt, $scripturl;
  29. // Old templates might still request this.
  30. if (isset($_REQUEST['sa']) && $_REQUEST['sa'] == 'browse')
  31. redirectexit('action=admin;area=viewmembers;sa=browse' . (isset($_REQUEST['type']) ? ';type=' . $_REQUEST['type'] : ''));
  32. $subActions = array(
  33. 'register' => array('AdminRegister', 'moderate_forum'),
  34. 'agreement' => array('EditAgreement', 'admin_forum'),
  35. 'reservednames' => array('SetReserved', 'admin_forum'),
  36. 'settings' => array('ModifyRegistrationSettings', 'admin_forum'),
  37. );
  38. call_integration_hook('integrate_manage_registrations', array(&$subActions));
  39. // Work out which to call...
  40. $context['sub_action'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : (allowedTo('moderate_forum') ? 'register' : 'settings');
  41. // Must have sufficient permissions.
  42. isAllowedTo($subActions[$context['sub_action']][1]);
  43. // Loading, always loading.
  44. loadLanguage('Login');
  45. loadTemplate('Register');
  46. // Next create the tabs for the template.
  47. $context[$context['admin_menu_name']]['tab_data'] = array(
  48. 'title' => $txt['registration_center'],
  49. 'help' => 'registrations',
  50. 'description' => $txt['admin_settings_desc'],
  51. 'tabs' => array(
  52. 'register' => array(
  53. 'description' => $txt['admin_register_desc'],
  54. ),
  55. 'agreement' => array(
  56. 'description' => $txt['registration_agreement_desc'],
  57. ),
  58. 'reservednames' => array(
  59. 'description' => $txt['admin_reserved_desc'],
  60. ),
  61. 'settings' => array(
  62. 'description' => $txt['admin_settings_desc'],
  63. )
  64. )
  65. );
  66. // Finally, get around to calling the function...
  67. $subActions[$context['sub_action']][0]();
  68. }
  69. /**
  70. * This function allows the admin to register a new member by hand.
  71. * It also allows assigning a primary group to the member being registered.
  72. * Accessed by ?action=admin;area=regcenter;sa=register
  73. * Requires the moderate_forum permission.
  74. *
  75. * @uses Register template, admin_register sub-template.
  76. */
  77. function AdminRegister()
  78. {
  79. global $txt, $context, $sourcedir, $scripturl, $smcFunc;
  80. // Are there any custom profile fields required during registration?
  81. require_once($sourcedir . '/Profile.php');
  82. loadCustomFields(0, 'register');
  83. if (!empty($_POST['regSubmit']))
  84. {
  85. checkSession();
  86. validateToken('admin-regc');
  87. foreach ($_POST as $key => $value)
  88. if (!is_array($_POST[$key]))
  89. $_POST[$key] = htmltrim__recursive(str_replace(array("\n", "\r"), '', $_POST[$key]));
  90. $regOptions = array(
  91. 'interface' => 'admin',
  92. 'username' => $_POST['user'],
  93. 'email' => $_POST['email'],
  94. 'password' => $_POST['password'],
  95. 'password_check' => $_POST['password'],
  96. 'check_reserved_name' => true,
  97. 'check_password_strength' => false,
  98. 'check_email_ban' => false,
  99. 'send_welcome_email' => isset($_POST['emailPassword']) || empty($_POST['password']),
  100. 'require' => isset($_POST['emailActivate']) ? 'activation' : 'nothing',
  101. 'memberGroup' => empty($_POST['group']) || !allowedTo('manage_membergroups') ? 0 : (int) $_POST['group'],
  102. );
  103. require_once($sourcedir . '/Subs-Members.php');
  104. $memberID = registerMember($regOptions);
  105. if (!empty($memberID))
  106. {
  107. // We'll do custom fields after as then we get to use the helper function!
  108. if (!empty($_POST['customfield']))
  109. {
  110. require_once($sourcedir . '/Profile-Modify.php');
  111. makeCustomFieldChanges($memberID, 'register');
  112. }
  113. $context['new_member'] = array(
  114. 'id' => $memberID,
  115. 'name' => $_POST['user'],
  116. 'href' => $scripturl . '?action=profile;u=' . $memberID,
  117. 'link' => '<a href="' . $scripturl . '?action=profile;u=' . $memberID . '">' . $_POST['user'] . '</a>',
  118. );
  119. $context['registration_done'] = sprintf($txt['admin_register_done'], $context['new_member']['link']);
  120. }
  121. }
  122. // Load the assignable member groups.
  123. if (allowedTo('manage_membergroups'))
  124. {
  125. $request = $smcFunc['db_query']('', '
  126. SELECT group_name, id_group
  127. FROM {db_prefix}membergroups
  128. WHERE id_group != {int:moderator_group}
  129. AND min_posts = {int:min_posts}' . (allowedTo('admin_forum') ? '' : '
  130. AND id_group != {int:admin_group}
  131. AND group_type != {int:is_protected}') . '
  132. AND hidden != {int:hidden_group}
  133. ORDER BY min_posts, CASE WHEN id_group < {int:newbie_group} THEN id_group ELSE 4 END, group_name',
  134. array(
  135. 'moderator_group' => 3,
  136. 'min_posts' => -1,
  137. 'admin_group' => 1,
  138. 'is_protected' => 1,
  139. 'hidden_group' => 2,
  140. 'newbie_group' => 4,
  141. )
  142. );
  143. $context['member_groups'] = array(0 => $txt['admin_register_group_none']);
  144. while ($row = $smcFunc['db_fetch_assoc']($request))
  145. $context['member_groups'][$row['id_group']] = $row['group_name'];
  146. $smcFunc['db_free_result']($request);
  147. }
  148. else
  149. $context['member_groups'] = array();
  150. // Basic stuff.
  151. $context['sub_template'] = 'admin_register';
  152. $context['page_title'] = $txt['registration_center'];
  153. createToken('admin-regc');
  154. loadJavascriptFile('register.js', array('default_theme' => true, 'defer' => false), 'smf_register');
  155. }
  156. /**
  157. * Allows the administrator to edit the registration agreement, and choose whether
  158. * it should be shown or not. It writes and saves the agreement to the agreement.txt
  159. * file.
  160. * Accessed by ?action=admin;area=regcenter;sa=agreement.
  161. * Requires the admin_forum permission.
  162. *
  163. * @uses Admin template and the edit_agreement sub template.
  164. */
  165. function EditAgreement()
  166. {
  167. // I hereby agree not to be a lazy bum.
  168. global $txt, $boarddir, $context, $modSettings, $smcFunc;
  169. // By default we look at agreement.txt.
  170. $context['current_agreement'] = '';
  171. // Is there more than one to edit?
  172. $context['editable_agreements'] = array(
  173. '' => $txt['admin_agreement_default'],
  174. );
  175. // Get our languages.
  176. getLanguages();
  177. // Try to figure out if we have more agreements.
  178. foreach ($context['languages'] as $lang)
  179. {
  180. if (file_exists($boarddir . '/agreement.' . $lang['filename'] . '.txt'))
  181. {
  182. $context['editable_agreements']['.' . $lang['filename']] = $lang['name'];
  183. // Are we editing this?
  184. if (isset($_POST['agree_lang']) && $_POST['agree_lang'] == '.' . $lang['filename'])
  185. $context['current_agreement'] = '.' . $lang['filename'];
  186. }
  187. }
  188. if (isset($_POST['agreement']))
  189. {
  190. checkSession();
  191. validateToken('admin-rega');
  192. // Off it goes to the agreement file.
  193. $to_write = str_replace("\r", '', $_POST['agreement']);
  194. $bytes = file_put_contents($boarddir . '/agreement' . $context['current_agreement'] . '.txt', $to_write, LOCK_EX);
  195. updateSettings(array('requireAgreement' => !empty($_POST['requireAgreement'])));
  196. if ($bytes == strlen($to_write))
  197. $context['saved_successful'] = true;
  198. else
  199. $context['could_not_save'] = true;
  200. }
  201. $context['agreement'] = file_exists($boarddir . '/agreement' . $context['current_agreement'] . '.txt') ? $smcFunc['htmlspecialchars'](file_get_contents($boarddir . '/agreement' . $context['current_agreement'] . '.txt')) : '';
  202. $context['warning'] = is_writable($boarddir . '/agreement' . $context['current_agreement'] . '.txt') ? '' : $txt['agreement_not_writable'];
  203. $context['require_agreement'] = !empty($modSettings['requireAgreement']);
  204. $context['sub_template'] = 'edit_agreement';
  205. $context['page_title'] = $txt['registration_agreement'];
  206. createToken('admin-rega');
  207. }
  208. /**
  209. * Set the names under which users are not allowed to register.
  210. * Accessed by ?action=admin;area=regcenter;sa=reservednames.
  211. * Requires the admin_forum permission.
  212. *
  213. * @uses Register template, reserved_words sub-template.
  214. */
  215. function SetReserved()
  216. {
  217. global $txt, $context, $modSettings;
  218. // Submitting new reserved words.
  219. if (!empty($_POST['save_reserved_names']))
  220. {
  221. checkSession();
  222. validateToken('admin-regr');
  223. // Set all the options....
  224. updateSettings(array(
  225. 'reserveWord' => (isset($_POST['matchword']) ? '1' : '0'),
  226. 'reserveCase' => (isset($_POST['matchcase']) ? '1' : '0'),
  227. 'reserveUser' => (isset($_POST['matchuser']) ? '1' : '0'),
  228. 'reserveName' => (isset($_POST['matchname']) ? '1' : '0'),
  229. 'reserveNames' => str_replace("\r", '', $_POST['reserved'])
  230. ));
  231. $context['saved_successful'] = true;
  232. }
  233. // Get the reserved word options and words.
  234. $modSettings['reserveNames'] = str_replace('\n', "\n", $modSettings['reserveNames']);
  235. $context['reserved_words'] = explode("\n", $modSettings['reserveNames']);
  236. $context['reserved_word_options'] = array();
  237. $context['reserved_word_options']['match_word'] = $modSettings['reserveWord'] == '1';
  238. $context['reserved_word_options']['match_case'] = $modSettings['reserveCase'] == '1';
  239. $context['reserved_word_options']['match_user'] = $modSettings['reserveUser'] == '1';
  240. $context['reserved_word_options']['match_name'] = $modSettings['reserveName'] == '1';
  241. // Ready the template......
  242. $context['sub_template'] = 'edit_reserved_words';
  243. $context['page_title'] = $txt['admin_reserved_set'];
  244. createToken('admin-regr');
  245. }
  246. /**
  247. * This function handles registration settings, and provides a few pretty stats too while it's at it.
  248. * General registration settings and Coppa compliance settings.
  249. * Accessed by ?action=admin;area=regcenter;sa=settings.
  250. * Requires the admin_forum permission.
  251. *
  252. * @param bool $return_config = false
  253. */
  254. function ModifyRegistrationSettings($return_config = false)
  255. {
  256. global $txt, $context, $scripturl, $modSettings, $sourcedir;
  257. // This is really quite wanting.
  258. require_once($sourcedir . '/ManageServer.php');
  259. $config_vars = array(
  260. array('select', 'registration_method', array($txt['setting_registration_standard'], $txt['setting_registration_activate'], $txt['setting_registration_approval'], $txt['setting_registration_disabled'])),
  261. array('select', 'enableOpenID', array(0 => $txt['enableOpenID_disabled'], 1 => $txt['enableOpenID_enabled'], 2 => $txt['enableOpenID_enabled_login'])),
  262. array('check', 'send_welcomeEmail'),
  263. '',
  264. array('int', 'coppaAge', 'subtext' => $txt['setting_coppaAge_desc'], 'onchange' => 'checkCoppa();', 'onkeyup' => 'checkCoppa();'),
  265. array('select', 'coppaType', array($txt['setting_coppaType_reject'], $txt['setting_coppaType_approval']), 'onchange' => 'checkCoppa();'),
  266. array('large_text', 'coppaPost', 'subtext' => $txt['setting_coppaPost_desc']),
  267. array('text', 'coppaFax'),
  268. array('text', 'coppaPhone'),
  269. );
  270. call_integration_hook('integrate_modify_registration_settings', array(&$config_vars));
  271. if ($return_config)
  272. return $config_vars;
  273. // Setup the template
  274. $context['sub_template'] = 'show_settings';
  275. $context['page_title'] = $txt['registration_center'];
  276. if (isset($_GET['save']))
  277. {
  278. checkSession();
  279. // Are there some contacts missing?
  280. if (!empty($_POST['coppaAge']) && !empty($_POST['coppaType']) && empty($_POST['coppaPost']) && empty($_POST['coppaFax']))
  281. fatal_lang_error('admin_setting_coppa_require_contact');
  282. // Post needs to take into account line breaks.
  283. $_POST['coppaPost'] = str_replace("\n", '<br>', empty($_POST['coppaPost']) ? '' : $_POST['coppaPost']);
  284. call_integration_hook('integrate_save_registration_settings');
  285. saveDBSettings($config_vars);
  286. $_SESSION['adm-save'] = true;
  287. redirectexit('action=admin;area=regcenter;sa=settings');
  288. }
  289. $context['post_url'] = $scripturl . '?action=admin;area=regcenter;save;sa=settings';
  290. $context['settings_title'] = $txt['settings'];
  291. // Define some javascript for COPPA.
  292. $context['settings_post_javascript'] = '
  293. function checkCoppa()
  294. {
  295. var coppaDisabled = document.getElementById(\'coppaAge\').value == 0;
  296. document.getElementById(\'coppaType\').disabled = coppaDisabled;
  297. var disableContacts = coppaDisabled || document.getElementById(\'coppaType\').options[document.getElementById(\'coppaType\').selectedIndex].value != 1;
  298. document.getElementById(\'coppaPost\').disabled = disableContacts;
  299. document.getElementById(\'coppaFax\').disabled = disableContacts;
  300. document.getElementById(\'coppaPhone\').disabled = disableContacts;
  301. }
  302. checkCoppa();';
  303. // Turn the postal address into something suitable for a textbox.
  304. $modSettings['coppaPost'] = !empty($modSettings['coppaPost']) ? preg_replace('~<br ?/?' . '>~', "\n", $modSettings['coppaPost']) : '';
  305. prepareDBSettingContext($config_vars);
  306. }
  307. ?>