1<?php 2/** 3 * webtrees: online genealogy 4 * Copyright (C) 2019 webtrees development team 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16namespace Fisharebest\Webtrees; 17 18use Fisharebest\Webtrees\Controller\PageController; 19use Fisharebest\Webtrees\Functions\Functions; 20use Rhumsaa\Uuid\Uuid; 21 22/** 23 * Defined in session.php 24 * 25 * @global Tree $WT_TREE 26 */ 27global $WT_TREE; 28 29define('WT_SCRIPT_NAME', 'login.php'); 30require './includes/session.php'; 31 32// If we are already logged in, then go to the “Home page” 33if (Auth::check() && $WT_TREE) { 34 header('Location: ' . WT_BASE_URL); 35 36 return; 37} 38 39$controller = new PageController; 40 41$action = Filter::post('action'); 42$user_realname = Filter::post('user_realname'); 43$user_name = Filter::post('user_name'); 44$user_email = Filter::postEmail('user_email'); 45$user_password01 = Filter::post('user_password01', WT_REGEX_PASSWORD); 46$user_password02 = Filter::post('user_password02', WT_REGEX_PASSWORD); 47$user_comments = Filter::post('user_comments'); 48$user_password = Filter::post('user_password'); 49$user_hashcode = Filter::post('user_hashcode'); 50$url = Filter::post('url'); // Not actually a URL - just a path 51$username = Filter::post('username'); 52$password = Filter::post('password'); 53 54// These parameters may come from the URL which is emailed to users. 55if (!$action) { 56 $action = Filter::get('action'); 57} 58if (!$user_name) { 59 $user_name = Filter::get('user_name'); 60} 61if (!$user_hashcode) { 62 $user_hashcode = Filter::get('user_hashcode'); 63} 64if (!$url) { 65 $url = Filter::get('url'); 66} 67 68$message = ''; 69 70switch ($action) { 71 case 'login': 72 try { 73 if (!$_COOKIE) { 74 Log::addAuthenticationLog('Login failed (no session cookies): ' . $username); 75 throw new \Exception(I18N::translate('You cannot sign in because your browser does not accept cookies.')); 76 } 77 78 $user = User::findByIdentifier($username); 79 80 if (!$user) { 81 Log::addAuthenticationLog('Login failed (no such user/email): ' . $username); 82 throw new \Exception(I18N::translate('The username or password is incorrect.')); 83 } 84 85 if (!$user->checkPassword($password)) { 86 Log::addAuthenticationLog('Login failed (incorrect password): ' . $username); 87 throw new \Exception(I18N::translate('The username or password is incorrect.')); 88 } 89 90 if (!$user->getPreference('verified')) { 91 Log::addAuthenticationLog('Login failed (not verified by user): ' . $username); 92 throw new \Exception(I18N::translate('This account has not been verified. Please check your email for a verification message.')); 93 } 94 95 if (!$user->getPreference('verified_by_admin')) { 96 Log::addAuthenticationLog('Login failed (not approved by admin): ' . $username); 97 throw new \Exception(I18N::translate('This account has not been approved. Please wait for an administrator to approve it.')); 98 } 99 100 Auth::login($user); 101 Log::addAuthenticationLog('Login: ' . Auth::user()->getUserName() . '/' . Auth::user()->getRealName()); 102 Auth::user()->setPreference('sessiontime', WT_TIMESTAMP); 103 104 Session::put('locale', Auth::user()->getPreference('language')); 105 Session::put('theme_id', Auth::user()->getPreference('theme')); 106 I18N::init(Auth::user()->getPreference('language')); 107 108 // We're logging in as an administrator 109 if (Auth::isAdmin()) { 110 // Check for updates 111 $latest_version_txt = Functions::fetchLatestVersion(); 112 if (preg_match('/^[0-9.]+\|[0-9.]+\|/', $latest_version_txt)) { 113 list($latest_version, $earliest_version, $download_url) = explode('|', $latest_version_txt); 114 if (version_compare(WT_VERSION, $latest_version) < 0) { 115 FlashMessages::addMessage( 116 I18N::translate('A new version of webtrees is available.') . 117 ' <a href="admin_site_upgrade.php"><b>' . 118 I18N::translate('Upgrade to webtrees %s.', '<span dir="ltr">' . $latest_version . '</span>') . 119 '</b></a>' 120 ); 121 } 122 } 123 } 124 125 // If we were on a "home page", redirect to "my page" 126 if ($url === '' || strpos($url, 'index.php?ctype=gedcom') === 0) { 127 $url = 'index.php?ctype=user'; 128 // Switch to a tree where we have a genealogy record (or keep to the current/default). 129 $tree = Database::prepare( 130 "SELECT gedcom_name FROM `##gedcom` JOIN `##user_gedcom_setting` USING (gedcom_id)" . 131 " WHERE setting_name = 'gedcomid' AND user_id = :user_id" . 132 " ORDER BY gedcom_id = :tree_id DESC" 133 )->execute(array( 134 'user_id' => Auth::user()->getUserId(), 135 'tree_id' => $WT_TREE->getTreeId(), 136 ))->fetchOne(); 137 $url .= '&ged=' . Filter::escapeUrl($tree); 138 } 139 140 // Redirect to the target URL 141 header('Location: ' . WT_BASE_URL . $url); 142 143 return; 144 } catch (\Exception $ex) { 145 $message = $ex->getMessage(); 146 } 147 // No break; 148 149 default: 150 $controller 151 ->setPageTitle(I18N::translate('Sign in')) 152 ->pageHeader() 153 ->addInlineJavascript(' 154 jQuery("#new_passwd_form").hide(); 155 jQuery("#passwd_click").click(function() { 156 jQuery("#new_passwd_form").slideToggle(100, function() { 157 jQuery("#new_passwd_username").focus() 158 }); 159 return false; 160 }); 161 '); 162 163 echo '<div id="login-page">'; 164 echo '<div id="login-text">'; 165 166 echo '<p class="center"><strong>' . I18N::translate('Welcome to this genealogy website') . '</strong></p>'; 167 168 switch (Site::getPreference('WELCOME_TEXT_AUTH_MODE')) { 169 case 1: 170 echo '<p>' . I18N::translate('Anyone with a user account can access this website.') . ' ' . I18N::translate('You can apply for an account using the link below.') . '</p>'; 171 break; 172 case 2: 173 echo '<p>' . I18N::translate('You need to be an authorized user to access this website.') . ' ' . I18N::translate('You can apply for an account using the link below.') . '</p>'; 174 break; 175 case 3: 176 echo '<p>' . I18N::translate('You need to be a family member to access this website.') . ' ' . I18N::translate('You can apply for an account using the link below.') . '</p>'; 177 break; 178 case 4: 179 echo '<p style="white-space: pre-wrap;">', Site::getPreference('WELCOME_TEXT_AUTH_MODE_' . WT_LOCALE), '</p>'; 180 break; 181 } 182 183 echo '</div>'; 184 echo '<div id="login-box">'; 185 if ($message) { 186 echo '<p class="error">', $message, '</p>'; 187 } 188 echo '<form id="login-form" name="login-form" method="post" action="', WT_LOGIN_URL, '"> 189 <input type="hidden" name="action" value="login"> 190 <input type="hidden" name="url" value="', Filter::escapeHtml($url), '">'; 191 echo '<div> 192 <label for="username">', I18N::translate('Username'), 193 '<input type="text" id="username" name="username" value="', Filter::escapeHtml($username), '" class="formField" autofocus> 194 </label> 195 </div> 196 <div> 197 <label for="password">', I18N::translate('Password'), 198 '<input type="password" id="password" name="password" class="formField"> 199 </label> 200 </div> 201 <div> 202 <input type="submit" value="', /* I18N: A button label. */ I18N::translate('sign in'), '"> 203 </div> 204 '; 205 // Emails are sent from a TREE, not from a SITE. Therefore if there is no 206 // tree available (initial setup or all trees private), then we can't send email. 207 if ($WT_TREE) { 208 echo ' 209 <div> 210 <a href="#" id="passwd_click">', I18N::translate('Forgot password?'), '</a> 211 </div>'; 212 if (Site::getPreference('USE_REGISTRATION_MODULE')) { 213 echo '<div><a href="' . WT_LOGIN_URL . '?action=register">', I18N::translate('Request a new user account'), '</a></div>'; 214 } 215 } 216 echo '</form>'; 217 218 // hidden New Password block 219 echo '<div id="new_passwd"> 220 <form id="new_passwd_form" name="new_passwd_form" action="' . WT_LOGIN_URL . '" method="post"> 221 <input type="hidden" name="action" value="requestpw"> 222 <h4>', I18N::translate('Request a new password'), '</h4> 223 <div> 224 <label for="new_passwd_username">', I18N::translate('Username or email address'), 225 '<input type="text" id="new_passwd_username" name="new_passwd_username" value=""> 226 </label> 227 </div> 228 <div><input type="submit" value="', /* I18N: A button label. */ I18N::translate('continue'), '"></div> 229 </form> 230 </div>'; 231 echo '</div>'; 232 233 echo '</div>'; 234 break; 235 236 case 'requestpw': 237 $user_name = Filter::post('new_passwd_username'); 238 $user = User::findByIdentifier($user_name); 239 240 if ($user) { 241 $passchars = 'abcdefghijklmnopqrstuvqxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; 242 $user_new_pw = ''; 243 $max = strlen($passchars) - 1; 244 for ($i = 0; $i < 8; $i++) { 245 $index = rand(0, $max); 246 $user_new_pw .= $passchars[$index]; 247 } 248 249 $user->setPassword($user_new_pw); 250 Log::addAuthenticationLog('Password request was sent to user: ' . $user->getUserName()); 251 252 Mail::systemMessage( 253 $WT_TREE, 254 $user, 255 I18N::translate('Lost password request'), 256 I18N::translate('Hello %s…', $user->getRealNameHtml()) . Mail::EOL . Mail::EOL . 257 I18N::translate('A new password has been requested for your username.') . Mail::EOL . Mail::EOL . 258 I18N::translate('Username') . ": " . Filter::escapeHtml($user->getUserName()) . Mail::EOL . 259 I18N::translate('Password') . ": " . $user_new_pw . Mail::EOL . Mail::EOL . 260 I18N::translate('After you have signed in, select the “My account” link under the “My pages” menu and fill in the password fields to change your password.') . Mail::EOL . Mail::EOL . 261 '<a href="' . WT_BASE_URL . 'login.php?ged=' . $WT_TREE->getNameUrl() . '">' . WT_BASE_URL . 'login.php?ged=' . $WT_TREE->getNameUrl() . '</a>' 262 ); 263 264 FlashMessages::addMessage(I18N::translate('A new password has been created and emailed to %s. You can change this password after you sign in.', Filter::escapeHtml($user_name)), 'success'); 265 } else { 266 FlashMessages::addMessage(I18N::translate('There is no account with the username or email “%s”.', Filter::escapeHtml($user_name)), 'danger'); 267 } 268 header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); 269 270 return; 271 break; 272 273 case 'register': 274 if (!Site::getPreference('USE_REGISTRATION_MODULE')) { 275 header('Location: ' . WT_BASE_URL); 276 277 return; 278 } 279 280 $controller->setPageTitle(I18N::translate('Request a new user account')); 281 282 // The form parameters are mandatory, and the validation errors are shown in the client. 283 if (Session::get('good_to_send') && $user_name && $user_password01 && $user_password01 == $user_password02 && $user_realname && $user_email && $user_comments) { 284 285 // These validation errors cannot be shown in the client. 286 if (User::findByUserName($user_name)) { 287 FlashMessages::addMessage(I18N::translate('Duplicate username. A user with that username already exists. Please choose another username.')); 288 } elseif (User::findByEmail($user_email)) { 289 FlashMessages::addMessage(I18N::translate('Duplicate email address. A user with that email already exists.')); 290 } elseif (preg_match('/(?!' . preg_quote(WT_BASE_URL, '/') . ')(((?:ftp|http|https):\/\/)[a-zA-Z0-9.-]+)/', $user_comments, $match)) { 291 FlashMessages::addMessage( 292 I18N::translate('You are not allowed to send messages that contain external links.') . ' ' . 293 I18N::translate('You should delete the “%1$s” from “%2$s” and try again.', $match[2], $match[1]) 294 ); 295 Log::addAuthenticationLog('Possible spam registration from "' . $user_name . '"/"' . $user_email . '" comments="' . $user_comments . '"'); 296 } else { 297 // Everything looks good - create the user 298 $controller->pageHeader(); 299 Log::addAuthenticationLog('User registration requested for: ' . $user_name); 300 301 $user = User::create($user_name, $user_realname, $user_email, $user_password01); 302 $user 303 ->setPreference('language', WT_LOCALE) 304 ->setPreference('verified', '0') 305 ->setPreference('verified_by_admin', 0) 306 ->setPreference('reg_timestamp', date('U')) 307 ->setPreference('reg_hashcode', md5(Uuid::uuid4())) 308 ->setPreference('contactmethod', 'messaging2') 309 ->setPreference('comment', $user_comments) 310 ->setPreference('visibleonline', '1') 311 ->setPreference('auto_accept', '0') 312 ->setPreference('canadmin', '0') 313 ->setPreference('sessiontime', '0'); 314 315 // Generate an email in the admin’s language 316 $webmaster = User::find($WT_TREE->getPreference('WEBMASTER_USER_ID')); 317 I18N::init($webmaster->getPreference('language')); 318 319 $mail1_body = 320 I18N::translate('Hello administrator…') . Mail::EOL . Mail::EOL . 321 /* I18N: %s is a server name/URL */ 322 I18N::translate('A prospective user has registered with webtrees at %s.', WT_BASE_URL . ' ' . $WT_TREE->getTitleHtml()) . Mail::EOL . Mail::EOL . 323 I18N::translate('Username') . ' ' . Filter::escapeHtml($user->getUserName()) . Mail::EOL . 324 I18N::translate('Real name') . ' ' . $user->getRealNameHtml() . Mail::EOL . 325 I18N::translate('Email address') . ' ' . Filter::escapeHtml($user->getEmail()) . Mail::EOL . 326 I18N::translate('Comments') . ' ' . Filter::escapeHtml($user_comments) . Mail::EOL . Mail::EOL . 327 I18N::translate('The user has been sent an email with the information necessary to confirm the access request.') . Mail::EOL . Mail::EOL . 328 I18N::translate('You will be informed by email when this prospective user has confirmed the request. You can then complete the process by activating the username. The new user will not be able to sign in until you activate the account.'); 329 330 $mail1_subject = /* I18N: %s is a server name/URL */ I18N::translate('New registration at %s', WT_BASE_URL . ' ' . $WT_TREE->getTitle()); 331 I18N::init(WT_LOCALE); 332 333 echo '<div id="login-register-page">'; 334 335 // Generate an email in the user’s language 336 $mail2_body = 337 I18N::translate('Hello %s…', $user->getRealNameHtml()) . 338 Mail::EOL . Mail::EOL . 339 /* I18N: %1$s is the site URL and %2$s is an email address */ 340 I18N::translate('You (or someone claiming to be you) has requested an account at %1$s using the email address %2$s.', WT_BASE_URL . ' ' . $WT_TREE->getTitleHtml(), $user->getEmail()) . 341 Mail::EOL . Mail::EOL . 342 I18N::translate('Follow this link to verify your email address.') . 343 Mail::EOL . Mail::EOL . 344 '<a href="' . WT_LOGIN_URL . '?user_name=' . Filter::escapeUrl($user->getUserName()) . '&user_hashcode=' . $user->getPreference('reg_hashcode') . '&action=userverify&ged=' . $WT_TREE->getNameUrl() . '">' . 345 WT_LOGIN_URL . "?user_name=" . Filter::escapeHtml($user->getUserName()) . "&user_hashcode=" . urlencode($user->getPreference('reg_hashcode')) . '&action=userverify&ged=' . $WT_TREE->getNameHtml() . 346 '</a>' . Mail::EOL . Mail::EOL . 347 I18N::translate('Username') . " - " . Filter::escapeHtml($user->getUserName()) . Mail::EOL . 348 I18N::translate('Comments') . " - " . $user->getPreference('comment') . Mail::EOL . 349 I18N::translate('If you didn’t request an account, you can just delete this message.') . Mail::EOL; 350 $mail2_subject = /* I18N: %s is a server name/URL */ I18N::translate('Your registration at %s', WT_BASE_URL); 351 $mail2_to = $user->getEmail(); 352 $mail2_from = $WT_TREE->getPreference('WEBTREES_EMAIL'); 353 354 // Send user message by email only 355 Mail::send( 356 // “From:” header 357 $WT_TREE, 358 // “To:” header 359 $mail2_to, 360 $mail2_to, 361 // “Reply-To:” header 362 $mail2_from, 363 $mail2_from, 364 // Message body 365 $mail2_subject, 366 $mail2_body 367 ); 368 369 // Send admin message by email and/or internal messaging 370 Mail::send( 371 // “From:” header 372 $WT_TREE, 373 // “To:” header 374 $webmaster->getEmail(), 375 $webmaster->getRealName(), 376 // “Reply-To:” header 377 $user->getEmail(), 378 $user->getRealName(), 379 // Message body 380 $mail1_subject, 381 $mail1_body 382 ); 383 $mail1_method = $webmaster->getPreference('contact_method'); 384 if ($mail1_method != 'messaging3' && $mail1_method != 'mailto' && $mail1_method != 'none') { 385 Database::prepare("INSERT INTO `##message` (sender, ip_address, user_id, subject, body) VALUES (? ,? ,? ,? ,?)") 386 ->execute(array($user->getEmail(), WT_CLIENT_IP, $webmaster->getUserId(), $mail1_subject, Filter::unescapeHtml($mail1_body))); 387 } 388 389 echo '<div class="confirm"><p>', I18N::translate('Hello %s…<br>Thank you for your registration.', $user->getRealNameHtml()), '</p>'; 390 echo '<p>', I18N::translate('We will now send a confirmation email to the address <b>%s</b>. You must verify your account request by following instructions in the confirmation email. If you do not confirm your account request within seven days, your application will be rejected automatically. You will have to apply again.<br><br>After you have followed the instructions in the confirmation email, the administrator still has to approve your request before your account can be used.<br><br>To sign in to this website, you will need to know your username and password.', $user->getEmail()), '</p>'; 391 echo '</div>'; 392 echo '</div>'; 393 394 return; 395 } 396 } 397 398 Session::put('good_to_send', true); 399 $controller 400 ->pageHeader() 401 ->addInlineJavascript('function regex_quote(str) {return str.replace(/[\\\\.?+*()[\](){}|]/g, "\\\\$&");}'); 402 403 ?> 404 <div id="login-register-page"> 405 <h2><?php echo $controller->getPageTitle(); ?></h2> 406 407 <?php if (Site::getPreference('SHOW_REGISTER_CAUTION')): ?> 408 <div id="register-text"> 409 <?php echo I18N::translate('<div class="largeError">Notice:</div><div class="error">By completing and submitting this form, you agree:<ul><li>to protect the privacy of living individuals listed on our site;</li><li>and in the text box below, to explain to whom you are related, or to provide us with information on someone who should be listed on our website.</li></ul></div>'); ?> 410 </div> 411 <?php endif; ?> 412 <div id="register-box"> 413 <form id="register-form" name="register-form" method="post" onsubmit="return checkform(this);" autocomplete="off"> 414 <input type="hidden" name="action" value="register"> 415 <h4><?php echo I18N::translate('All fields must be completed.'); ?></h4> 416 <hr> 417 418 <div> 419 <label for="user_realname"> 420 <?php echo I18N::translate('Real name'); ?> 421 <input type="text" id="user_realname" name="user_realname" required maxlength="64" value="<?php echo Filter::escapeHtml($user_realname); ?>" autofocus> 422 </label> 423 <p class="small text-muted"> 424 <?php echo I18N::translate('This is your real name, as you would like it displayed on screen.'); ?> 425 </p> 426 </div> 427 428 <div> 429 <label for="user_email"> 430 <?php echo I18N::translate('Email address'); ?> 431 <input type="email" id="user_email" name="user_email" required maxlength="64" value="<?php echo Filter::escapeHtml($user_email); ?>" pattern=".*@[^.]+\..*"> 432 </label> 433 <p class="small text-muted"> 434 <?php echo I18N::translate('This email address will be used to send password reminders, website notifications, and messages from other family members who are registered on the website.'); ?> 435 </p> 436 </div> 437 438 <div> 439 <label for="username"> 440 <?php echo I18N::translate('Username'); ?> 441 <input type="text" id="username" name="user_name" required maxlength="32" value="<?php Filter::escapeHtml($user_name); ?>"> 442 </label> 443 <p class="small text-muted"> 444 <?php echo I18N::translate('Usernames are case-insensitive and ignore accented letters, so that “chloe”, “chloë”, and “Chloe” are considered to be the same.'); ?> 445 </p> 446 </div> 447 448 <div> 449 <label for="user_password01"> 450 <?php echo I18N::translate('Password'); ?> 451 <input required 452 type="password" 453 id="user_password01" name="user_password01" 454 value="<?php echo Filter::escapeHtml($user_password01); ?>" 455 placeholder="<?php echo /* I18N: placeholder text for new-password field */ I18N::plural('Use at least %s character.', 'Use at least %s characters.', WT_MINIMUM_PASSWORD_LENGTH, I18N::number(WT_MINIMUM_PASSWORD_LENGTH)); ?>" 456 pattern="<?php echo WT_REGEX_PASSWORD; ?>" 457 onchange="form.user_password02.pattern = regex_quote(this.value);" 458 > 459 </label> 460 <p class="small text-muted"> 461 <?php echo I18N::translate('Passwords must be at least 6 characters long and are case-sensitive, so that “secret” is different from “SECRET”.'); ?> 462 </p> 463 </div> 464 465 <div> 466 <label for="user_password02"> 467 <?php echo I18N::translate('Confirm password'); ?> 468 <input required 469 type="password" 470 id="user_password02" name="user_password02" 471 value="<?php echo Filter::escapeHtml($user_password02); ?>" 472 placeholder="<?php echo /* I18N: placeholder text for repeat-password field */ I18N::translate('Type the password again.'); ?>" 473 pattern="<?php echo WT_REGEX_PASSWORD; ?>" 474 > 475 </label> 476 <p class="small text-muted"> 477 <?php echo I18N::translate('Type your password again, to make sure you have typed it correctly.'); ?> 478 </p> 479 </div> 480 481 <div> 482 <label for="user_comments"> 483 <?php echo I18N::translate('Comments'); ?> 484 <textarea required 485 cols="50" rows="5" 486 id="user_comments" name="user_comments" 487 placeholder="<?php /* I18N: placeholder text for registration-comments field */ I18N::translate('Explain why you are requesting an account.'); ?>" 488 ><?php echo Filter::escapeHtml($user_comments); ?></textarea> 489 </label> 490 <p class="small text-muted"> 491 <?php echo I18N::translate('Use this field to tell the site administrator why you are requesting an account and how you are related to the genealogy displayed on this site. You can also use this to enter any other comments you may have for the site administrator.'); ?> 492 </p> 493 </div> 494 495 <hr> 496 497 <div id="registration-submit"> 498 <input type="submit" value="<?php echo I18N::translate('continue'); ?>"> 499 </div> 500 </form> 501 </div> 502 </div> 503 <?php 504 break; 505 506 case 'userverify': 507 if (!Site::getPreference('USE_REGISTRATION_MODULE')) { 508 header('Location: ' . WT_BASE_URL); 509 510 return; 511 } 512 513 // Change to the new user’s language 514 $user = User::findByUserName($user_name); 515 516 I18N::init($user->getPreference('language')); 517 518 $controller->setPageTitle(I18N::translate('User verification')); 519 $controller->pageHeader(); 520 521 echo '<div id="login-register-page"> 522 <form id="verify-form" name="verify-form" method="post" action="', WT_LOGIN_URL, '"> 523 <input type="hidden" name="action" value="verify_hash"> 524 <h4>', I18N::translate('User verification'), '</h4> 525 <div> 526 <label for="username">', I18N::translate('Username'), '</label> 527 <input type="text" id="username" name="user_name" value="', $user_name, '"> 528 </div> 529 <div> 530 <label for="user_password">', I18N::translate('Password'), '</label> 531 <input type="password" id="user_password" name="user_password" value="" autofocus> 532 </div> 533 <div> 534 <label for="user_hashcode">', I18N::translate('Verification code'), '</label> 535 <input type="text" id="user_hashcode" name="user_hashcode" value="', $user_hashcode, '"> 536 </div> 537 <div> 538 <input type="submit" value="', I18N::translate('Send'), '"> 539 </div> 540 </form> 541 </div>'; 542 break; 543 544 case 'verify_hash': 545 if (!Site::getPreference('USE_REGISTRATION_MODULE')) { 546 header('Location: ' . WT_BASE_URL); 547 548 return; 549 } 550 551 // switch language to webmaster settings 552 $webmaster = User::find($WT_TREE->getPreference('WEBMASTER_USER_ID')); 553 I18N::init($webmaster->getPreference('language')); 554 555 $user = User::findByUserName($user_name); 556 $edit_user_url = WT_BASE_URL . "admin_users.php?action=edit&user_id=" . $user->getUserId(); 557 $mail1_body = 558 I18N::translate('Hello administrator…') . 559 Mail::EOL . Mail::EOL . 560 /* I18N: %1$s is a real-name, %2$s is a username, %3$s is an email address */ I18N::translate( 561 'A new user (%1$s) has requested an account (%2$s) and verified an email address (%3$s).', 562 $user->getRealNameHtml(), 563 Filter::escapeHtml($user->getUserName()), 564 Filter::escapeHtml($user->getEmail()) 565 ) . 566 Mail::EOL . Mail::EOL . 567 I18N::translate('You need to review the account details.') . 568 Mail::EOL . Mail::EOL . 569 '<a href="' . $edit_user_url . '">' . $edit_user_url . '</a>' . 570 Mail::EOL . Mail::EOL . 571 /* I18N: You need to: */ I18N::translate('Set the status to “approved”.') . 572 Mail::EOL . 573 /* I18N: You need to: */ I18N::translate('Set the access level for each tree.') . 574 Mail::EOL . 575 /* I18N: You need to: */ I18N::translate('Link the user account to an individual.'); 576 577 $mail1_subject = /* I18N: %s is a server name/URL */ I18N::translate('New user at %s', WT_BASE_URL . ' ' . $WT_TREE->getTitle()); 578 579 // Change to the new user’s language 580 I18N::init($user->getPreference('language')); 581 582 $controller->setPageTitle(I18N::translate('User verification')); 583 $controller->pageHeader(); 584 585 echo '<div id="login-register-page">'; 586 echo '<h2>' . I18N::translate('User verification') . '</h2>'; 587 echo '<div id="user-verify">'; 588 if ($user && $user->checkPassword($user_password) && $user->getPreference('reg_hashcode') === $user_hashcode) { 589 Mail::send( 590 // “From:” header 591 $WT_TREE, 592 // “To:” header 593 $webmaster->getEmail(), 594 $webmaster->getRealName(), 595 // “Reply-To:” header 596 $WT_TREE->getPreference('WEBTREES_EMAIL'), 597 $WT_TREE->getPreference('WEBTREES_EMAIL'), 598 // Message body 599 $mail1_subject, 600 $mail1_body 601 ); 602 $mail1_method = $webmaster->getPreference('CONTACT_METHOD'); 603 if ($mail1_method != 'messaging3' && $mail1_method != 'mailto' && $mail1_method != 'none') { 604 Database::prepare("INSERT INTO `##message` (sender, ip_address, user_id, subject, body) VALUES (? ,? ,? ,? ,?)") 605 ->execute(array($user_name, WT_CLIENT_IP, $webmaster->getUserId(), $mail1_subject, Filter::unescapeHtml($mail1_body))); 606 } 607 608 $user 609 ->setPreference('verified', '1') 610 ->setPreference('reg_timestamp', date('U')) 611 ->deletePreference('reg_hashcode'); 612 613 Log::addAuthenticationLog('User ' . $user_name . ' verified their email address'); 614 615 echo '<p>', I18N::translate('You have confirmed your request to become a registered user.'), '</p>'; 616 echo '<p>', I18N::translate('The administrator has been informed. As soon as they give you permission to sign in, you can sign in with your username and password.'), '</p>'; 617 } else { 618 echo '<p class="warning">'; 619 echo I18N::translate('Could not verify the information you entered. Please try again or contact the site administrator for more information.'); 620 echo '</p>'; 621 } 622 echo '</div>'; 623 echo '</div>'; 624 break; 625} 626