| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * WordPress User Page 4 * 5 * Handles authentication, registering, resetting passwords, forgot password, 6 * and other user handling. 7 * 8 * @package WordPress 9 */ 10 11 /** Make sure that the WordPress bootstrap has run before continuing. */ 12 require __DIR__ . '/wp-load.php'; 13 14 // Redirect to HTTPS login if forced to use SSL. 15 if ( force_ssl_admin() && ! is_ssl() ) { 16 if ( str_starts_with( $_SERVER['REQUEST_URI'], 'http' ) ) { 17 wp_safe_redirect( set_url_scheme( $_SERVER['REQUEST_URI'], 'https' ) ); 18 exit; 19 } else { 20 wp_safe_redirect( 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ); 21 exit; 22 } 23 } 24 25 /** 26 * Outputs the login page header. 27 * 28 * @since 2.1.0 29 * 30 * @global string $error Login error message set by deprecated pluggable wp_login() function 31 * or plugins replacing it. 32 * @global bool|string $interim_login Whether interim login modal is being displayed. String 'success' 33 * upon successful login. 34 * @global string $action The action that brought the visitor to the login page. 35 * 36 * @param string|null $title Optional. WordPress login page title to display in the `<title>` element. 37 * Defaults to 'Log In'. 38 * @param string $message Optional. Message to display in header. Default empty. 39 * @param WP_Error|null $wp_error Optional. The error to pass. Defaults to a WP_Error instance. 40 */ 41 function login_header( $title = null, $message = '', $wp_error = null ) { 42 global $error, $interim_login, $action; 43 44 if ( null === $title ) { 45 $title = __( 'Log In' ); 46 } 47 48 // Don't index any of these forms. 49 add_filter( 'wp_robots', 'wp_robots_sensitive_page' ); 50 add_action( 'login_head', 'wp_strict_cross_origin_referrer' ); 51 52 add_action( 'login_head', 'wp_login_viewport_meta' ); 53 54 if ( ! is_wp_error( $wp_error ) ) { 55 $wp_error = new WP_Error(); 56 } 57 58 // Shake it! 59 $shake_error_codes = array( 'empty_password', 'empty_email', 'invalid_email', 'invalidcombo', 'empty_username', 'invalid_username', 'incorrect_password', 'retrieve_password_email_failure' ); 60 /** 61 * Filters the error codes array for shaking the login form. 62 * 63 * @since 3.0.0 64 * 65 * @param string[] $shake_error_codes Error codes that shake the login form. 66 */ 67 $shake_error_codes = apply_filters( 'shake_error_codes', $shake_error_codes ); 68 69 if ( $shake_error_codes && $wp_error->has_errors() && in_array( $wp_error->get_error_code(), $shake_error_codes, true ) ) { 70 add_action( 'login_footer', 'wp_shake_js', 12 ); 71 } 72 73 $login_title = get_bloginfo( 'name', 'display' ); 74 75 /* translators: Login screen title. 1: Login screen name, 2: Network or site name. */ 76 $login_title = sprintf( __( '%1$s ‹ %2$s — WordPress' ), $title, $login_title ); 77 78 if ( wp_is_recovery_mode() ) { 79 /* translators: %s: Login screen title. */ 80 $login_title = sprintf( __( 'Recovery Mode — %s' ), $login_title ); 81 } 82 83 /** 84 * Filters the title tag content for login page. 85 * 86 * @since 4.9.0 87 * 88 * @param string $login_title The page title, with extra context added. 89 * @param string $title The original page title. 90 */ 91 $login_title = apply_filters( 'login_title', $login_title, $title ); 92 93 ?><!DOCTYPE html> 94 <html <?php language_attributes(); ?>> 95 <head> 96 <meta http-equiv="Content-Type" content="<?php bloginfo( 'html_type' ); ?>; charset=<?php bloginfo( 'charset' ); ?>" /> 97 <title><?php echo $login_title; ?></title> 98 <?php 99 100 wp_enqueue_style( 'login' ); 101 102 /* 103 * Remove all stored post data on logging out. 104 * This could be added by add_action('login_head'...) like wp_shake_js(), 105 * but maybe better if it's not removable by plugins. 106 */ 107 if ( 'loggedout' === $wp_error->get_error_code() ) { 108 ob_start(); 109 ?> 110 <script>if("sessionStorage" in window){try{for(var key in sessionStorage){if(key.indexOf("wp-autosave-")!=-1){sessionStorage.removeItem(key)}}}catch(e){}};</script> 111 <?php 112 wp_print_inline_script_tag( wp_remove_surrounding_empty_script_tags( ob_get_clean() ) ); 113 } 114 115 /** 116 * Enqueues scripts and styles for the login page. 117 * 118 * @since 3.1.0 119 */ 120 do_action( 'login_enqueue_scripts' ); 121 122 /** 123 * Fires in the login page header after scripts are enqueued. 124 * 125 * @since 2.1.0 126 */ 127 do_action( 'login_head' ); 128 129 $login_header_url = __( 'https://wordpress.org/' ); 130 131 /** 132 * Filters link URL of the header logo above login form. 133 * 134 * @since 2.1.0 135 * 136 * @param string $login_header_url Login header logo URL. 137 */ 138 $login_header_url = apply_filters( 'login_headerurl', $login_header_url ); 139 140 $login_header_title = ''; 141 142 /** 143 * Filters the title attribute of the header logo above login form. 144 * 145 * @since 2.1.0 146 * @deprecated 5.2.0 Use {@see 'login_headertext'} instead. 147 * 148 * @param string $login_header_title Login header logo title attribute. 149 */ 150 $login_header_title = apply_filters_deprecated( 151 'login_headertitle', 152 array( $login_header_title ), 153 '5.2.0', 154 'login_headertext', 155 __( 'Usage of the title attribute on the login logo is not recommended for accessibility reasons. Use the link text instead.' ) 156 ); 157 158 $login_header_text = empty( $login_header_title ) ? __( 'Powered by WordPress' ) : $login_header_title; 159 160 /** 161 * Filters the link text of the header logo above the login form. 162 * 163 * @since 5.2.0 164 * 165 * @param string $login_header_text The login header logo link text. 166 */ 167 $login_header_text = apply_filters( 'login_headertext', $login_header_text ); 168 169 $classes = array( 'login-action-' . $action, 'wp-core-ui', 'admin-color-modern' ); 170 171 if ( is_rtl() ) { 172 $classes[] = 'rtl'; 173 } 174 175 if ( $interim_login ) { 176 $classes[] = 'interim-login'; 177 178 ?> 179 <style>html{background-color: transparent;}</style> 180 <?php 181 182 if ( 'success' === $interim_login ) { 183 $classes[] = 'interim-login-success'; 184 } 185 } 186 187 $classes[] = 'locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_locale() ) ) ); 188 189 /** 190 * Filters the login page body classes. 191 * 192 * @since 3.5.0 193 * 194 * @param string[] $classes An array of body classes. 195 * @param string $action The action that brought the visitor to the login page. 196 */ 197 $classes = apply_filters( 'login_body_class', $classes, $action ); 198 199 ?> 200 </head> 201 <body class="login no-js <?php echo esc_attr( implode( ' ', $classes ) ); ?>"> 202 <?php 203 wp_print_inline_script_tag( "document.body.className = document.body.className.replace('no-js','js');" ); 204 ?> 205 206 <?php 207 /** 208 * Fires in the login page header after the body tag is opened. 209 * 210 * @since 4.6.0 211 */ 212 do_action( 'login_header' ); 213 ?> 214 <?php 215 if ( 'confirm_admin_email' !== $action && ! empty( $title ) ) : 216 ?> 217 <h1 class="screen-reader-text"><?php echo $title; ?></h1> 218 <?php 219 endif; 220 ?> 221 <div id="login"> 222 <h1 role="presentation" class="wp-login-logo"><a href="<?php echo esc_url( $login_header_url ); ?>"><?php echo $login_header_text; ?></a></h1> 223 <?php 224 /** 225 * Filters the message to display above the login form. 226 * 227 * @since 2.1.0 228 * 229 * @param string $message Login message text. 230 */ 231 $message = apply_filters( 'login_message', $message ); 232 233 if ( ! empty( $message ) ) { 234 echo $message . "\n"; 235 } 236 237 // In case a plugin uses $error rather than the $wp_errors object. 238 if ( ! empty( $error ) ) { 239 $wp_error->add( 'error', $error ); 240 unset( $error ); 241 } 242 243 if ( $wp_error->has_errors() ) { 244 $error_list = array(); 245 $messages = ''; 246 247 foreach ( $wp_error->get_error_codes() as $code ) { 248 $severity = $wp_error->get_error_data( $code ); 249 foreach ( $wp_error->get_error_messages( $code ) as $error_message ) { 250 if ( 'message' === $severity ) { 251 $messages .= '<p>' . $error_message . '</p>'; 252 } else { 253 $error_list[] = $error_message; 254 } 255 } 256 } 257 258 if ( ! empty( $error_list ) ) { 259 $errors = ''; 260 261 if ( count( $error_list ) > 1 ) { 262 $errors .= '<ul class="login-error-list">'; 263 264 foreach ( $error_list as $item ) { 265 $errors .= '<li>' . $item . '</li>'; 266 } 267 268 $errors .= '</ul>'; 269 } else { 270 $errors .= '<p>' . $error_list[0] . '</p>'; 271 } 272 273 /** 274 * Filters the error messages displayed above the login form. 275 * 276 * @since 2.1.0 277 * 278 * @param string $errors Login error messages. 279 */ 280 $errors = apply_filters( 'login_errors', $errors ); 281 282 wp_admin_notice( 283 $errors, 284 array( 285 'type' => 'error', 286 'id' => 'login_error', 287 'paragraph_wrap' => false, 288 ) 289 ); 290 } 291 292 if ( ! empty( $messages ) ) { 293 /** 294 * Filters instructional messages displayed above the login form. 295 * 296 * @since 2.5.0 297 * 298 * @param string $messages Login messages. 299 */ 300 $messages = apply_filters( 'login_messages', $messages ); 301 302 wp_admin_notice( 303 $messages, 304 array( 305 'type' => 'info', 306 'id' => 'login-message', 307 'additional_classes' => array( 'message' ), 308 'paragraph_wrap' => false, 309 ) 310 ); 311 } 312 } 313 } // End of login_header(). 314 315 /** 316 * Outputs the footer for the login page. 317 * 318 * @since 3.1.0 319 * 320 * @global bool|string $interim_login Whether interim login modal is being displayed. String 'success' 321 * upon successful login. 322 * 323 * @param string $input_id Which input to auto-focus. 324 */ 325 function login_footer( $input_id = '' ) { 326 global $interim_login; 327 328 // Don't allow interim logins to navigate away from the page. 329 if ( ! $interim_login ) { 330 ?> 331 <p id="backtoblog"> 332 <?php 333 $html_link = sprintf( 334 '<a href="%s">%s</a>', 335 esc_url( home_url( '/' ) ), 336 sprintf( 337 /* translators: %s: Site title. */ 338 _x( '← Go to %s', 'site' ), 339 get_bloginfo( 'title', 'display' ) 340 ) 341 ); 342 /** 343 * Filters the "Go to site" link displayed in the login page footer. 344 * 345 * @since 5.7.0 346 * 347 * @param string $link HTML link to the home URL of the current site. 348 */ 349 echo apply_filters( 'login_site_html_link', $html_link ); 350 ?> 351 </p> 352 <?php 353 354 the_privacy_policy_link( '<div class="privacy-policy-page-link">', '</div>' ); 355 } 356 357 ?> 358 </div><?php // End of <div id="login">. ?> 359 360 <?php 361 if ( 362 ! $interim_login && 363 /** 364 * Filters whether to display the Language selector on the login screen. 365 * 366 * @since 5.9.0 367 * 368 * @param bool $display Whether to display the Language selector on the login screen. 369 */ 370 apply_filters( 'login_display_language_dropdown', true ) 371 ) { 372 $languages = get_available_languages(); 373 374 if ( ! empty( $languages ) ) { 375 ?> 376 <div class="language-switcher"> 377 <form id="language-switcher" method="get"> 378 379 <label for="language-switcher-locales"> 380 <?php _e( 'Language' ); ?><span class="dashicons dashicons-translation" aria-hidden="true"></span> 381 </label> 382 383 <?php 384 $args = array( 385 'id' => 'language-switcher-locales', 386 'name' => 'wp_lang', 387 'selected' => determine_locale(), 388 'show_available_translations' => false, 389 'explicit_option_en_us' => true, 390 'languages' => $languages, 391 ); 392 393 /** 394 * Filters default arguments for the Language select input on the login screen. 395 * 396 * The arguments get passed to the wp_dropdown_languages() function. 397 * 398 * @since 5.9.0 399 * 400 * @param array $args Arguments for the Language select input on the login screen. 401 */ 402 wp_dropdown_languages( apply_filters( 'login_language_dropdown_args', $args ) ); 403 ?> 404 405 <?php if ( isset( $_GET['redirect_to'] ) && '' !== $_GET['redirect_to'] ) { ?> 406 <input type="hidden" name="redirect_to" value="<?php echo sanitize_url( $_GET['redirect_to'] ); ?>" /> 407 <?php } ?> 408 409 <?php if ( isset( $_GET['action'] ) && '' !== $_GET['action'] ) { ?> 410 <input type="hidden" name="action" value="<?php echo esc_attr( $_GET['action'] ); ?>" /> 411 <?php } ?> 412 413 <input type="submit" class="button" value="<?php esc_attr_e( 'Change' ); ?>"> 414 415 </form> 416 </div> 417 <?php } ?> 418 <?php } ?> 419 420 <?php 421 422 if ( ! empty( $input_id ) ) { 423 ob_start(); 424 ?> 425 <script> 426 try{document.getElementById('<?php echo $input_id; ?>').focus();}catch(e){} 427 if(typeof wpOnload==='function')wpOnload(); 428 </script> 429 <?php 430 wp_print_inline_script_tag( wp_remove_surrounding_empty_script_tags( ob_get_clean() ) ); 431 } 432 433 /** 434 * Fires in the login page footer. 435 * 436 * @since 3.1.0 437 */ 438 do_action( 'login_footer' ); 439 440 ?> 441 </body> 442 </html> 443 <?php 444 } 445 446 /** 447 * Outputs the JavaScript to handle the form shaking on the login page. 448 * 449 * @since 3.0.0 450 */ 451 function wp_shake_js() { 452 wp_print_inline_script_tag( "document.querySelector('form').classList.add('shake');" ); 453 } 454 455 /** 456 * Outputs the viewport meta tag for the login page. 457 * 458 * @since 3.7.0 459 */ 460 function wp_login_viewport_meta() { 461 ?> 462 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 463 <?php 464 } 465 466 /* 467 * Main part. 468 * 469 * Check the request and redirect or display a form based on the current action. 470 */ 471 472 $action = isset( $_REQUEST['action'] ) && is_string( $_REQUEST['action'] ) ? $_REQUEST['action'] : 'login'; 473 $errors = new WP_Error(); 474 475 if ( isset( $_GET['key'] ) ) { 476 $action = 'resetpass'; 477 } 478 479 if ( isset( $_GET['checkemail'] ) ) { 480 $action = 'checkemail'; 481 } 482 483 $default_actions = array( 484 'confirm_admin_email', 485 'postpass', 486 'logout', 487 'lostpassword', 488 'retrievepassword', 489 'resetpass', 490 'rp', 491 'register', 492 'checkemail', 493 'confirmaction', 494 'login', 495 WP_Recovery_Mode_Link_Service::LOGIN_ACTION_ENTERED, 496 ); 497 498 // Validate action so as to default to the login screen. 499 if ( ! in_array( $action, $default_actions, true ) && false === has_filter( 'login_form_' . $action ) ) { 500 $action = 'login'; 501 } 502 503 nocache_headers(); 504 505 header( 'Content-Type: ' . get_bloginfo( 'html_type' ) . '; charset=' . get_bloginfo( 'charset' ) ); 506 507 if ( defined( 'RELOCATE' ) && RELOCATE ) { // Move flag is set. 508 if ( isset( $_SERVER['PATH_INFO'] ) && ( $_SERVER['PATH_INFO'] !== $_SERVER['PHP_SELF'] ) ) { 509 $_SERVER['PHP_SELF'] = str_replace( $_SERVER['PATH_INFO'], '', $_SERVER['PHP_SELF'] ); 510 } 511 512 $url = dirname( set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] ) ); 513 514 if ( get_option( 'siteurl' ) !== $url ) { 515 update_option( 'siteurl', $url ); 516 } 517 } 518 519 // Set a cookie now to see if they are supported by the browser. 520 $secure = ( 'https' === parse_url( wp_login_url(), PHP_URL_SCHEME ) ); 521 setcookie( TEST_COOKIE, 'WP Cookie check', 0, COOKIEPATH, COOKIE_DOMAIN, $secure, true ); 522 523 if ( SITECOOKIEPATH !== COOKIEPATH ) { 524 setcookie( TEST_COOKIE, 'WP Cookie check', 0, SITECOOKIEPATH, COOKIE_DOMAIN, $secure, true ); 525 } 526 527 if ( isset( $_GET['wp_lang'] ) ) { 528 setcookie( 'wp_lang', sanitize_text_field( $_GET['wp_lang'] ), 0, COOKIEPATH, COOKIE_DOMAIN, $secure, true ); 529 } 530 531 /** 532 * Fires when the login form is initialized. 533 * 534 * @since 3.2.0 535 */ 536 do_action( 'login_init' ); 537 538 /** 539 * Fires before a specified login form action. 540 * 541 * The dynamic portion of the hook name, `$action`, refers to the action 542 * that brought the visitor to the login form. 543 * 544 * Possible hook names include: 545 * 546 * - `login_form_checkemail` 547 * - `login_form_confirm_admin_email` 548 * - `login_form_confirmaction` 549 * - `login_form_entered_recovery_mode` 550 * - `login_form_login` 551 * - `login_form_logout` 552 * - `login_form_lostpassword` 553 * - `login_form_postpass` 554 * - `login_form_register` 555 * - `login_form_resetpass` 556 * - `login_form_retrievepassword` 557 * - `login_form_rp` 558 * 559 * @since 2.8.0 560 */ 561 do_action( "login_form_{$action}" ); 562 563 $http_post = ( 'POST' === $_SERVER['REQUEST_METHOD'] ); 564 $interim_login = isset( $_REQUEST['interim-login'] ); 565 566 /** 567 * Filters the separator used between login form navigation links. 568 * 569 * @since 4.9.0 570 * 571 * @param string $login_link_separator The separator used between login form navigation links. 572 */ 573 $login_link_separator = apply_filters( 'login_link_separator', ' | ' ); 574 575 switch ( $action ) { 576 577 case 'confirm_admin_email': 578 /* 579 * Note that `is_user_logged_in()` will return false immediately after logging in 580 * as the current user is not set, see wp-includes/pluggable.php. 581 * However this action runs on a redirect after logging in. 582 */ 583 if ( ! is_user_logged_in() ) { 584 wp_safe_redirect( wp_login_url() ); 585 exit; 586 } 587 588 if ( ! empty( $_REQUEST['redirect_to'] ) ) { 589 $redirect_to = $_REQUEST['redirect_to']; 590 } else { 591 $redirect_to = admin_url(); 592 } 593 594 if ( current_user_can( 'manage_options' ) ) { 595 $admin_email = get_option( 'admin_email' ); 596 } else { 597 wp_safe_redirect( $redirect_to ); 598 exit; 599 } 600 601 /** 602 * Filters the interval for dismissing the admin email confirmation screen. 603 * 604 * If `0` (zero) is returned, the "Remind me later" link will not be displayed. 605 * 606 * @since 5.3.1 607 * 608 * @param int $interval Interval time (in seconds). Default is 3 days. 609 */ 610 $remind_interval = (int) apply_filters( 'admin_email_remind_interval', 3 * DAY_IN_SECONDS ); 611 612 if ( ! empty( $_GET['remind_me_later'] ) ) { 613 if ( ! wp_verify_nonce( $_GET['remind_me_later'], 'remind_me_later_nonce' ) ) { 614 wp_safe_redirect( wp_login_url() ); 615 exit; 616 } 617 618 if ( $remind_interval > 0 ) { 619 update_option( 'admin_email_lifespan', time() + $remind_interval ); 620 } 621 622 $redirect_to = add_query_arg( 'admin_email_remind_later', 1, $redirect_to ); 623 wp_safe_redirect( $redirect_to ); 624 exit; 625 } 626 627 if ( ! empty( $_POST['correct-admin-email'] ) ) { 628 if ( ! check_admin_referer( 'confirm_admin_email', 'confirm_admin_email_nonce' ) ) { 629 wp_safe_redirect( wp_login_url() ); 630 exit; 631 } 632 633 /** 634 * Filters the interval for redirecting the user to the admin email confirmation screen. 635 * 636 * If `0` (zero) is returned, the user will not be redirected. 637 * 638 * @since 5.3.0 639 * 640 * @param int $interval Interval time (in seconds). Default is 6 months. 641 */ 642 $admin_email_check_interval = (int) apply_filters( 'admin_email_check_interval', 6 * MONTH_IN_SECONDS ); 643 644 if ( $admin_email_check_interval > 0 ) { 645 update_option( 'admin_email_lifespan', time() + $admin_email_check_interval ); 646 } 647 648 wp_safe_redirect( $redirect_to ); 649 exit; 650 } 651 652 login_header( __( 'Confirm your administration email' ), '', $errors ); 653 654 /** 655 * Fires before the admin email confirm form. 656 * 657 * @since 5.3.0 658 * 659 * @param WP_Error $errors A `WP_Error` object containing any errors generated by using invalid 660 * credentials. Note that the error object may not contain any errors. 661 */ 662 do_action( 'admin_email_confirm', $errors ); 663 664 ?> 665 666 <form class="admin-email-confirm-form" name="admin-email-confirm-form" action="<?php echo esc_url( site_url( 'wp-login.php?action=confirm_admin_email', 'login_post' ) ); ?>" method="post"> 667 <?php 668 /** 669 * Fires inside the admin-email-confirm-form form tags, before the hidden fields. 670 * 671 * @since 5.3.0 672 */ 673 do_action( 'admin_email_confirm_form' ); 674 675 wp_nonce_field( 'confirm_admin_email', 'confirm_admin_email_nonce' ); 676 677 ?> 678 <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" /> 679 680 <h1 class="admin-email__heading"> 681 <?php _e( 'Administration email verification' ); ?> 682 </h1> 683 <p class="admin-email__details"> 684 <?php _e( 'Please verify that the <strong>administration email</strong> for this website is still correct.' ); ?> 685 <?php 686 687 /* translators: URL to the WordPress help section about admin email. */ 688 $admin_email_help_url = __( 'https://wordpress.org/documentation/article/settings-general-screen/#email-address' ); 689 690 $accessibility_text = sprintf( 691 '<span class="screen-reader-text"> %s</span>', 692 /* translators: Hidden accessibility text. */ 693 __( '(opens in a new tab)' ) 694 ); 695 696 printf( 697 '<a href="%s" target="_blank">%s%s</a>', 698 esc_url( $admin_email_help_url ), 699 __( 'Why is this important?' ), 700 $accessibility_text 701 ); 702 703 ?> 704 </p> 705 <p class="admin-email__details"> 706 <?php 707 708 printf( 709 /* translators: %s: Admin email address. */ 710 __( 'Current administration email: %s' ), 711 '<strong>' . esc_html( $admin_email ) . '</strong>' 712 ); 713 714 ?> 715 </p> 716 <p class="admin-email__details"> 717 <?php _e( 'This email may be different from your personal email address.' ); ?> 718 </p> 719 720 <div class="admin-email__actions"> 721 <div class="admin-email__actions-primary"> 722 <?php 723 724 $change_link = admin_url( 'options-general.php' ); 725 $change_link = add_query_arg( 'highlight', 'confirm_admin_email', $change_link ); 726 727 ?> 728 <a class="button button-large" href="<?php echo esc_url( $change_link ); ?>"><?php _e( 'Update' ); ?></a> 729 <input type="submit" name="correct-admin-email" id="correct-admin-email" class="button button-primary button-large" value="<?php esc_attr_e( 'The email is correct' ); ?>" /> 730 </div> 731 <?php if ( $remind_interval > 0 ) : ?> 732 <div class="admin-email__actions-secondary"> 733 <?php 734 735 $remind_me_link = wp_login_url( $redirect_to ); 736 $remind_me_link = add_query_arg( 737 array( 738 'action' => 'confirm_admin_email', 739 'remind_me_later' => wp_create_nonce( 'remind_me_later_nonce' ), 740 ), 741 $remind_me_link 742 ); 743 744 ?> 745 <a href="<?php echo esc_url( $remind_me_link ); ?>"><?php _e( 'Remind me later' ); ?></a> 746 </div> 747 <?php endif; ?> 748 </div> 749 </form> 750 751 <?php 752 753 login_footer(); 754 break; 755 756 case 'postpass': 757 $redirect_to = $_POST['redirect_to'] ?? wp_get_referer(); 758 759 if ( ! isset( $_POST['post_password'] ) || ! is_string( $_POST['post_password'] ) ) { 760 wp_safe_redirect( $redirect_to ); 761 exit; 762 } 763 764 require_once ABSPATH . WPINC . '/class-phpass.php'; 765 $hasher = new PasswordHash( 8, true ); 766 767 /** 768 * Filters the life span of the post password cookie. 769 * 770 * By default, the cookie expires 10 days from creation. To turn this 771 * into a session cookie, return 0. 772 * 773 * @since 3.7.0 774 * 775 * @param int $expires The expiry time, as passed to setcookie(). 776 */ 777 $expire = apply_filters( 'post_password_expires', time() + 10 * DAY_IN_SECONDS ); 778 779 if ( $redirect_to ) { 780 $secure = ( 'https' === parse_url( $redirect_to, PHP_URL_SCHEME ) ); 781 } else { 782 $secure = false; 783 } 784 785 setcookie( 'wp-postpass_' . COOKIEHASH, $hasher->HashPassword( wp_unslash( $_POST['post_password'] ) ), $expire, COOKIEPATH, COOKIE_DOMAIN, $secure ); 786 787 wp_safe_redirect( $redirect_to ); 788 exit; 789 790 case 'logout': 791 check_admin_referer( 'log-out' ); 792 793 $user = wp_get_current_user(); 794 795 wp_logout(); 796 797 if ( ! empty( $_REQUEST['redirect_to'] ) && is_string( $_REQUEST['redirect_to'] ) ) { 798 $redirect_to = $_REQUEST['redirect_to']; 799 $requested_redirect_to = $redirect_to; 800 } else { 801 $redirect_to = add_query_arg( 802 array( 803 'loggedout' => 'true', 804 'wp_lang' => get_user_locale( $user ), 805 ), 806 wp_login_url() 807 ); 808 809 $requested_redirect_to = ''; 810 } 811 812 /** 813 * Filters the log out redirect URL. 814 * 815 * @since 4.2.0 816 * 817 * @param string $redirect_to The redirect destination URL. 818 * @param string $requested_redirect_to The requested redirect destination URL passed as a parameter. 819 * @param WP_User $user The WP_User object for the user that's logging out. 820 */ 821 $redirect_to = apply_filters( 'logout_redirect', $redirect_to, $requested_redirect_to, $user ); 822 823 wp_safe_redirect( $redirect_to ); 824 exit; 825 826 case 'lostpassword': 827 case 'retrievepassword': 828 if ( $http_post ) { 829 $errors = retrieve_password(); 830 831 if ( ! is_wp_error( $errors ) ) { 832 $redirect_to = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : 'wp-login.php?checkemail=confirm'; 833 wp_safe_redirect( $redirect_to ); 834 exit; 835 } 836 } 837 838 if ( isset( $_GET['error'] ) ) { 839 if ( 'invalidkey' === $_GET['error'] ) { 840 $errors->add( 'invalidkey', __( '<strong>Error:</strong> Your password reset link appears to be invalid. Please request a new link below.' ) ); 841 } elseif ( 'expiredkey' === $_GET['error'] ) { 842 $errors->add( 'expiredkey', __( '<strong>Error:</strong> Your password reset link has expired. Please request a new link below.' ) ); 843 } 844 } 845 846 $lostpassword_redirect = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : ''; 847 /** 848 * Filters the URL redirected to after submitting the lostpassword/retrievepassword form. 849 * 850 * @since 3.0.0 851 * 852 * @param string $lostpassword_redirect The redirect destination URL. 853 */ 854 $redirect_to = apply_filters( 'lostpassword_redirect', $lostpassword_redirect ); 855 856 /** 857 * Fires before the lost password form. 858 * 859 * @since 1.5.1 860 * @since 5.1.0 Added the `$errors` parameter. 861 * 862 * @param WP_Error $errors A `WP_Error` object containing any errors generated by using invalid 863 * credentials. Note that the error object may not contain any errors. 864 */ 865 do_action( 'lost_password', $errors ); 866 867 login_header( 868 __( 'Lost Password' ), 869 wp_get_admin_notice( 870 __( 'Please enter your username or email address. You will receive an email message with instructions on how to reset your password.' ), 871 array( 872 'type' => 'info', 873 'additional_classes' => array( 'message' ), 874 ) 875 ), 876 $errors 877 ); 878 879 $user_login = ''; 880 881 if ( isset( $_POST['user_login'] ) && is_string( $_POST['user_login'] ) ) { 882 $user_login = wp_unslash( $_POST['user_login'] ); 883 } 884 885 ?> 886 887 <form name="lostpasswordform" id="lostpasswordform" action="<?php echo esc_url( network_site_url( 'wp-login.php?action=lostpassword', 'login_post' ) ); ?>" method="post"> 888 <p> 889 <label for="user_login"><?php _e( 'Username or Email Address' ); ?></label> 890 <input type="text" name="user_login" id="user_login" class="input ltr" value="<?php echo esc_attr( $user_login ); ?>" size="20" autocapitalize="off" autocomplete="username" required="required" /> 891 </p> 892 <?php 893 894 /** 895 * Fires inside the lostpassword form tags, before the hidden fields. 896 * 897 * @since 2.1.0 898 */ 899 do_action( 'lostpassword_form' ); 900 901 ?> 902 <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" /> 903 <p class="submit"> 904 <input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Get New Password' ); ?>" /> 905 </p> 906 </form> 907 908 <p id="nav"> 909 <a class="wp-login-log-in" href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a> 910 <?php 911 912 if ( get_option( 'users_can_register' ) ) { 913 $registration_url = sprintf( '<a class="wp-login-register" href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) ); 914 915 echo esc_html( $login_link_separator ); 916 917 /** This filter is documented in wp-includes/general-template.php */ 918 echo apply_filters( 'register', $registration_url ); 919 } 920 921 ?> 922 </p> 923 <?php 924 925 login_footer( 'user_login' ); 926 break; 927 928 case 'resetpass': 929 case 'rp': 930 list( $rp_path ) = explode( '?', wp_unslash( $_SERVER['REQUEST_URI'] ) ); 931 $rp_cookie = 'wp-resetpass-' . COOKIEHASH; 932 933 if ( isset( $_GET['key'] ) && isset( $_GET['login'] ) ) { 934 $value = sprintf( '%s:%s', wp_unslash( $_GET['login'] ), wp_unslash( $_GET['key'] ) ); 935 setcookie( $rp_cookie, $value, 0, $rp_path, COOKIE_DOMAIN, is_ssl(), true ); 936 937 wp_safe_redirect( remove_query_arg( array( 'key', 'login' ) ) ); 938 exit; 939 } 940 941 if ( isset( $_COOKIE[ $rp_cookie ] ) && 0 < strpos( $_COOKIE[ $rp_cookie ], ':' ) ) { 942 list( $rp_login, $rp_key ) = explode( ':', wp_unslash( $_COOKIE[ $rp_cookie ] ), 2 ); 943 944 $user = check_password_reset_key( $rp_key, $rp_login ); 945 946 if ( isset( $_POST['pass1'] ) && ! hash_equals( $rp_key, $_POST['rp_key'] ) ) { 947 $user = false; 948 } 949 } else { 950 $user = false; 951 } 952 953 if ( ! $user || is_wp_error( $user ) ) { 954 setcookie( $rp_cookie, ' ', time() - YEAR_IN_SECONDS, $rp_path, COOKIE_DOMAIN, is_ssl(), true ); 955 956 if ( $user && $user->get_error_code() === 'expired_key' ) { 957 wp_redirect( site_url( 'wp-login.php?action=lostpassword&error=expiredkey' ) ); 958 } else { 959 wp_redirect( site_url( 'wp-login.php?action=lostpassword&error=invalidkey' ) ); 960 } 961 962 exit; 963 } 964 965 $errors = new WP_Error(); 966 967 // Check if password is one or all empty spaces. 968 if ( ! empty( $_POST['pass1'] ) ) { 969 $_POST['pass1'] = trim( $_POST['pass1'] ); 970 971 if ( empty( $_POST['pass1'] ) ) { 972 $errors->add( 'password_reset_empty_space', __( 'The password cannot be a space or all spaces.' ) ); 973 } 974 } 975 976 // Check if password fields do not match. 977 if ( ! empty( $_POST['pass1'] ) && trim( $_POST['pass2'] ) !== $_POST['pass1'] ) { 978 $errors->add( 'password_reset_mismatch', __( '<strong>Error:</strong> The passwords do not match.' ) ); 979 } 980 981 /** 982 * Fires before the password reset procedure is validated. 983 * 984 * @since 3.5.0 985 * 986 * @param WP_Error $errors WP Error object. 987 * @param WP_User|WP_Error $user WP_User object if the login and reset key match. WP_Error object otherwise. 988 */ 989 do_action( 'validate_password_reset', $errors, $user ); 990 991 if ( ( ! $errors->has_errors() ) && isset( $_POST['pass1'] ) && ! empty( $_POST['pass1'] ) ) { 992 reset_password( $user, $_POST['pass1'] ); 993 login_header( 994 __( 'Password Reset' ), 995 wp_get_admin_notice( 996 __( 'Your password has been reset.' ) . ' <a href="' . esc_url( wp_login_url() ) . '">' . __( 'Log in' ) . '</a>', 997 array( 998 'type' => 'info', 999 'additional_classes' => array( 'message', 'reset-pass' ), 1000 ) 1001 ) 1002 ); 1003 login_footer(); 1004 exit; 1005 } 1006 1007 wp_enqueue_script( 'utils' ); 1008 wp_enqueue_script( 'user-profile' ); 1009 1010 login_header( 1011 __( 'Reset Password' ), 1012 wp_get_admin_notice( 1013 __( 'Enter your new password below or generate one.' ), 1014 array( 1015 'type' => 'info', 1016 'additional_classes' => array( 'message', 'reset-pass' ), 1017 ) 1018 ), 1019 $errors 1020 ); 1021 1022 ?> 1023 <form name="resetpassform" id="resetpassform" action="<?php echo esc_url( network_site_url( 'wp-login.php?action=resetpass', 'login_post' ) ); ?>" method="post" autocomplete="off"> 1024 <input type="hidden" id="user_login" value="<?php echo esc_attr( $rp_login ); ?>" autocomplete="off" /> 1025 1026 <div class="user-pass1-wrap"> 1027 <p> 1028 <label for="pass1"><?php _e( 'New password' ); ?></label> 1029 </p> 1030 1031 <div class="wp-pwd"> 1032 <input type="password" name="pass1" id="pass1" class="input password-input ltr" size="24" value="" autocomplete="new-password" spellcheck="false" data-reveal="1" data-pw="<?php echo esc_attr( wp_generate_password( 16 ) ); ?>" aria-describedby="pass-strength-result" /> 1033 1034 <button type="button" class="button button-secondary wp-hide-pw hide-if-no-js" data-toggle="0" aria-label="<?php esc_attr_e( 'Hide password' ); ?>"> 1035 <span class="dashicons dashicons-hidden" aria-hidden="true"></span> 1036 </button> 1037 <div id="pass-strength-result" class="hide-if-no-js" aria-live="polite"><?php _e( 'Strength indicator' ); ?></div> 1038 </div> 1039 <div class="pw-weak"> 1040 <input type="checkbox" name="pw_weak" id="pw-weak" class="pw-checkbox" /> 1041 <label for="pw-weak"><?php _e( 'Confirm use of weak password' ); ?></label> 1042 </div> 1043 </div> 1044 1045 <p class="user-pass2-wrap"> 1046 <label for="pass2"><?php _e( 'Confirm new password' ); ?></label> 1047 <input type="password" name="pass2" id="pass2" class="input" size="20" value="" autocomplete="new-password" spellcheck="false" /> 1048 </p> 1049 1050 <p class="description indicator-hint"><?php echo wp_get_password_hint(); ?></p> 1051 1052 <?php 1053 1054 /** 1055 * Fires following the 'Strength indicator' meter in the user password reset form. 1056 * 1057 * @since 3.9.0 1058 * 1059 * @param WP_User $user User object of the user whose password is being reset. 1060 */ 1061 do_action( 'resetpass_form', $user ); 1062 1063 ?> 1064 <input type="hidden" name="rp_key" value="<?php echo esc_attr( $rp_key ); ?>" /> 1065 <p class="submit reset-pass-submit"> 1066 <button type="button" class="button wp-generate-pw hide-if-no-js skip-aria-expanded"><?php _e( 'Generate Password' ); ?></button> 1067 <input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Save Password' ); ?>" /> 1068 </p> 1069 </form> 1070 1071 <p id="nav"> 1072 <a class="wp-login-log-in" href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a> 1073 <?php 1074 1075 if ( get_option( 'users_can_register' ) ) { 1076 $registration_url = sprintf( '<a class="wp-login-register" href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) ); 1077 1078 echo esc_html( $login_link_separator ); 1079 1080 /** This filter is documented in wp-includes/general-template.php */ 1081 echo apply_filters( 'register', $registration_url ); 1082 } 1083 1084 ?> 1085 </p> 1086 <?php 1087 1088 login_footer( 'pass1' ); 1089 break; 1090 1091 case 'register': 1092 if ( is_multisite() ) { 1093 /** 1094 * Filters the Multisite sign up URL. 1095 * 1096 * @since 3.0.0 1097 * 1098 * @param string $sign_up_url The sign up URL. 1099 */ 1100 wp_redirect( apply_filters( 'wp_signup_location', network_site_url( 'wp-signup.php' ) ) ); 1101 exit; 1102 } 1103 1104 if ( ! get_option( 'users_can_register' ) ) { 1105 wp_redirect( site_url( 'wp-login.php?registration=disabled' ) ); 1106 exit; 1107 } 1108 1109 $user_login = ''; 1110 $user_email = ''; 1111 1112 if ( $http_post ) { 1113 if ( isset( $_POST['user_login'] ) && is_string( $_POST['user_login'] ) ) { 1114 $user_login = wp_unslash( $_POST['user_login'] ); 1115 } 1116 1117 if ( isset( $_POST['user_email'] ) && is_string( $_POST['user_email'] ) ) { 1118 $user_email = wp_unslash( $_POST['user_email'] ); 1119 } 1120 1121 $errors = register_new_user( $user_login, $user_email ); 1122 1123 if ( ! is_wp_error( $errors ) ) { 1124 $redirect_to = ! empty( $_POST['redirect_to'] ) ? $_POST['redirect_to'] : 'wp-login.php?checkemail=registered'; 1125 wp_safe_redirect( $redirect_to ); 1126 exit; 1127 } 1128 } 1129 1130 $registration_redirect = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : ''; 1131 1132 /** 1133 * Filters the registration redirect URL. 1134 * 1135 * @since 3.0.0 1136 * @since 5.9.0 Added the `$errors` parameter. 1137 * 1138 * @param string $registration_redirect The redirect destination URL. 1139 * @param int|WP_Error $errors User id if registration was successful, 1140 * WP_Error object otherwise. 1141 */ 1142 $redirect_to = apply_filters( 'registration_redirect', $registration_redirect, $errors ); 1143 1144 login_header( 1145 __( 'Registration Form' ), 1146 wp_get_admin_notice( 1147 __( 'Register For This Site' ), 1148 array( 1149 'type' => 'info', 1150 'additional_classes' => array( 'message', 'register' ), 1151 ) 1152 ), 1153 $errors 1154 ); 1155 1156 ?> 1157 <form name="registerform" id="registerform" action="<?php echo esc_url( site_url( 'wp-login.php?action=register', 'login_post' ) ); ?>" method="post" novalidate="novalidate"> 1158 <p> 1159 <label for="user_login"><?php _e( 'Username' ); ?></label> 1160 <input type="text" name="user_login" id="user_login" class="input ltr" value="<?php echo esc_attr( $user_login ); ?>" size="20" autocapitalize="off" autocomplete="username" required="required" /> 1161 </p> 1162 <p> 1163 <label for="user_email"><?php _e( 'Email' ); ?></label> 1164 <input type="email" name="user_email" id="user_email" class="input" value="<?php echo esc_attr( $user_email ); ?>" size="25" autocomplete="email" required="required" /> 1165 </p> 1166 <?php 1167 1168 /** 1169 * Fires following the 'Email' field in the user registration form. 1170 * 1171 * @since 2.1.0 1172 */ 1173 do_action( 'register_form' ); 1174 1175 ?> 1176 <p id="reg_passmail"> 1177 <?php _e( 'Registration confirmation will be emailed to you.' ); ?> 1178 </p> 1179 <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" /> 1180 <p class="submit"> 1181 <input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Register' ); ?>" /> 1182 </p> 1183 </form> 1184 1185 <p id="nav"> 1186 <a class="wp-login-log-in" href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a> 1187 <?php 1188 1189 echo esc_html( $login_link_separator ); 1190 1191 $html_link = sprintf( '<a class="wp-login-lost-password" href="%s">%s</a>', esc_url( wp_lostpassword_url() ), __( 'Lost your password?' ) ); 1192 1193 /** This filter is documented in wp-login.php */ 1194 echo apply_filters( 'lost_password_html_link', $html_link ); 1195 1196 ?> 1197 </p> 1198 <?php 1199 1200 login_footer( 'user_login' ); 1201 break; 1202 1203 case 'checkemail': 1204 $redirect_to = admin_url(); 1205 $errors = new WP_Error(); 1206 1207 if ( 'confirm' === $_GET['checkemail'] ) { 1208 $errors->add( 1209 'confirm', 1210 sprintf( 1211 /* translators: %s: Link to the login page. */ 1212 __( 'Check your email for the confirmation link, then visit the <a href="%s">login page</a>.' ), 1213 esc_url( wp_login_url() ) 1214 ), 1215 'message' 1216 ); 1217 } elseif ( 'registered' === $_GET['checkemail'] ) { 1218 $errors->add( 1219 'registered', 1220 sprintf( 1221 /* translators: %s: Link to the login page. */ 1222 __( 'Registration complete. Please check your email, then visit the <a href="%s">login page</a>.' ), 1223 esc_url( wp_login_url() ) 1224 ), 1225 'message' 1226 ); 1227 } 1228 1229 /** This action is documented in wp-login.php */ 1230 $errors = apply_filters( 'wp_login_errors', $errors, $redirect_to ); 1231 1232 login_header( __( 'Check your email' ), '', $errors ); 1233 login_footer(); 1234 break; 1235 1236 case 'confirmaction': 1237 if ( ! isset( $_GET['request_id'] ) ) { 1238 wp_die( __( 'Missing request ID.' ) ); 1239 } 1240 1241 if ( ! isset( $_GET['confirm_key'] ) ) { 1242 wp_die( __( 'Missing confirm key.' ) ); 1243 } 1244 1245 $request_id = (int) $_GET['request_id']; 1246 $key = sanitize_text_field( wp_unslash( $_GET['confirm_key'] ) ); 1247 $result = wp_validate_user_request_key( $request_id, $key ); 1248 1249 if ( is_wp_error( $result ) ) { 1250 wp_die( $result ); 1251 } 1252 1253 /** 1254 * Fires an action hook when the account action has been confirmed by the user. 1255 * 1256 * Using this you can assume the user has agreed to perform the action by 1257 * clicking on the link in the confirmation email. 1258 * 1259 * After firing this action hook the page will redirect to wp-login a callback 1260 * redirects or exits first. 1261 * 1262 * @since 4.9.6 1263 * 1264 * @param int $request_id Request ID. 1265 */ 1266 do_action( 'user_request_action_confirmed', $request_id ); 1267 1268 $message = _wp_privacy_account_request_confirmed_message( $request_id ); 1269 1270 login_header( __( 'User action confirmed.' ), $message ); 1271 login_footer(); 1272 exit; 1273 1274 case 'login': 1275 default: 1276 $secure_cookie = ''; 1277 $customize_login = isset( $_REQUEST['customize-login'] ); 1278 1279 if ( $customize_login ) { 1280 wp_enqueue_script( 'customize-base' ); 1281 } 1282 1283 // If the user wants SSL but the session is not SSL, force a secure cookie. 1284 if ( ! empty( $_POST['log'] ) && ! force_ssl_admin() ) { 1285 $user_name = sanitize_user( wp_unslash( $_POST['log'] ) ); 1286 $user = get_user_by( 'login', $user_name ); 1287 1288 if ( ! $user && strpos( $user_name, '@' ) ) { 1289 $user = get_user_by( 'email', $user_name ); 1290 } 1291 1292 if ( $user ) { 1293 if ( get_user_option( 'use_ssl', $user->ID ) ) { 1294 $secure_cookie = true; 1295 force_ssl_admin( true ); 1296 } 1297 } 1298 } 1299 1300 if ( isset( $_REQUEST['redirect_to'] ) && is_string( $_REQUEST['redirect_to'] ) ) { 1301 $redirect_to = $_REQUEST['redirect_to']; 1302 // Redirect to HTTPS if user wants SSL. 1303 if ( $secure_cookie && str_contains( $redirect_to, 'wp-admin' ) ) { 1304 $redirect_to = preg_replace( '|^http://|', 'https://', $redirect_to ); 1305 } 1306 } else { 1307 $redirect_to = admin_url(); 1308 } 1309 1310 $reauth = ! empty( $_REQUEST['reauth'] ); 1311 1312 $user = wp_signon( array(), $secure_cookie ); 1313 1314 if ( empty( $_COOKIE[ LOGGED_IN_COOKIE ] ) ) { 1315 if ( headers_sent() ) { 1316 $user = new WP_Error( 1317 'test_cookie', 1318 sprintf( 1319 /* translators: 1: Browser cookie documentation URL, 2: Support forums URL. */ 1320 __( '<strong>Error:</strong> Cookies are blocked due to unexpected output. For help, please see <a href="%1$s">this documentation</a> or try the <a href="%2$s">support forums</a>.' ), 1321 __( 'https://developer.wordpress.org/advanced-administration/wordpress/cookies/' ), 1322 __( 'https://wordpress.org/support/forums/' ) 1323 ) 1324 ); 1325 } elseif ( isset( $_POST['testcookie'] ) && empty( $_COOKIE[ TEST_COOKIE ] ) ) { 1326 // If cookies are disabled, the user can't log in even with a valid username and password. 1327 $user = new WP_Error( 1328 'test_cookie', 1329 sprintf( 1330 /* translators: %s: Browser cookie documentation URL. */ 1331 __( '<strong>Error:</strong> Cookies are blocked or not supported by your browser. You must <a href="%s">enable cookies</a> to use WordPress.' ), 1332 __( 'https://developer.wordpress.org/advanced-administration/wordpress/cookies/#enable-cookies-in-your-browser' ) 1333 ) 1334 ); 1335 } 1336 } 1337 1338 $requested_redirect_to = isset( $_REQUEST['redirect_to'] ) && is_string( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : ''; 1339 1340 /** 1341 * Filters the login redirect URL. 1342 * 1343 * @since 3.0.0 1344 * 1345 * @param string $redirect_to The redirect destination URL. 1346 * @param string $requested_redirect_to The requested redirect destination URL passed as a parameter. 1347 * @param WP_User|WP_Error $user WP_User object if login was successful, WP_Error object otherwise. 1348 */ 1349 $redirect_to = apply_filters( 'login_redirect', $redirect_to, $requested_redirect_to, $user ); 1350 1351 if ( ! is_wp_error( $user ) && ! $reauth ) { 1352 if ( $interim_login ) { 1353 $message = '<p class="message">' . __( 'You have logged in successfully.' ) . '</p>'; 1354 $interim_login = 'success'; 1355 login_header( '', $message ); 1356 1357 ?> 1358 </div> 1359 <?php 1360 1361 /** This action is documented in wp-login.php */ 1362 do_action( 'login_footer' ); 1363 1364 if ( $customize_login ) { 1365 ob_start(); 1366 ?> 1367 <script>setTimeout( function(){ new wp.customize.Messenger({ url: '<?php echo wp_customize_url(); ?>', channel: 'login' }).send('login') }, 1000 );</script> 1368 <?php 1369 wp_print_inline_script_tag( wp_remove_surrounding_empty_script_tags( ob_get_clean() ) ); 1370 } 1371 1372 ?> 1373 </body></html> 1374 <?php 1375 1376 exit; 1377 } 1378 1379 // Check if it is time to add a redirect to the admin email confirmation screen. 1380 if ( $user instanceof WP_User && $user->exists() && $user->has_cap( 'manage_options' ) ) { 1381 $admin_email_lifespan = (int) get_option( 'admin_email_lifespan' ); 1382 1383 /* 1384 * If `0` (or anything "falsey" as it is cast to int) is returned, the user will not be redirected 1385 * to the admin email confirmation screen. 1386 */ 1387 /** This filter is documented in wp-login.php */ 1388 $admin_email_check_interval = (int) apply_filters( 'admin_email_check_interval', 6 * MONTH_IN_SECONDS ); 1389 1390 if ( $admin_email_check_interval > 0 && time() > $admin_email_lifespan ) { 1391 $redirect_to = add_query_arg( 1392 array( 1393 'action' => 'confirm_admin_email', 1394 'wp_lang' => get_user_locale( $user ), 1395 ), 1396 wp_login_url( $redirect_to ) 1397 ); 1398 } 1399 } 1400 1401 if ( ( empty( $redirect_to ) || 'wp-admin/' === $redirect_to || admin_url() === $redirect_to ) ) { 1402 // If the user doesn't belong to a blog, send them to user admin. If the user can't edit posts, send them to their profile. 1403 if ( is_multisite() && ! get_active_blog_for_user( $user->ID ) && ! is_super_admin( $user->ID ) ) { 1404 $redirect_to = user_admin_url(); 1405 } elseif ( is_multisite() && ! $user->has_cap( 'read' ) ) { 1406 $redirect_to = get_dashboard_url( $user->ID ); 1407 } elseif ( ! $user->has_cap( 'edit_posts' ) ) { 1408 $redirect_to = $user->has_cap( 'read' ) ? admin_url( 'profile.php' ) : home_url(); 1409 } 1410 1411 wp_redirect( $redirect_to ); 1412 exit; 1413 } 1414 1415 wp_safe_redirect( $redirect_to ); 1416 exit; 1417 } 1418 1419 $errors = $user; 1420 // Clear errors if loggedout is set. 1421 if ( ! empty( $_GET['loggedout'] ) || $reauth ) { 1422 $errors = new WP_Error(); 1423 } 1424 1425 if ( empty( $_POST ) && $errors->get_error_codes() === array( 'empty_username', 'empty_password' ) ) { 1426 $errors = new WP_Error( '', '' ); 1427 } 1428 1429 if ( $interim_login ) { 1430 if ( ! $errors->has_errors() ) { 1431 $errors->add( 'expired', __( 'Your session has expired. Please log in to continue where you left off.' ), 'message' ); 1432 } 1433 } else { 1434 // Some parts of this script use the main login form to display a message. 1435 if ( isset( $_GET['loggedout'] ) && $_GET['loggedout'] ) { 1436 $errors->add( 'loggedout', __( 'You are now logged out.' ), 'message' ); 1437 } elseif ( isset( $_GET['registration'] ) && 'disabled' === $_GET['registration'] ) { 1438 $errors->add( 'registerdisabled', __( '<strong>Error:</strong> User registration is currently not allowed.' ) ); 1439 } elseif ( str_contains( $redirect_to, 'about.php?updated' ) ) { 1440 $errors->add( 'updated', __( '<strong>You have successfully updated WordPress!</strong> Please log back in to see what’s new.' ), 'message' ); 1441 } elseif ( WP_Recovery_Mode_Link_Service::LOGIN_ACTION_ENTERED === $action ) { 1442 $errors->add( 'enter_recovery_mode', __( 'Recovery Mode Initialized. Please log in to continue.' ), 'message' ); 1443 } elseif ( isset( $_GET['redirect_to'] ) && is_string( $_GET['redirect_to'] ) 1444 && str_contains( $_GET['redirect_to'], 'wp-admin/authorize-application.php' ) 1445 ) { 1446 $query_component = wp_parse_url( $_GET['redirect_to'], PHP_URL_QUERY ); 1447 $query = array(); 1448 if ( $query_component ) { 1449 parse_str( $query_component, $query ); 1450 } 1451 1452 if ( ! empty( $query['app_name'] ) ) { 1453 /* translators: 1: Website name, 2: Application name. */ 1454 $message = sprintf( __( 'Please log in to %1$s to authorize %2$s to connect to your account.' ), get_bloginfo( 'name', 'display' ), '<strong>' . esc_html( $query['app_name'] ) . '</strong>' ); 1455 } else { 1456 /* translators: %s: Website name. */ 1457 $message = sprintf( __( 'Please log in to %s to proceed with authorization.' ), get_bloginfo( 'name', 'display' ) ); 1458 } 1459 1460 $errors->add( 'authorize_application', $message, 'message' ); 1461 } 1462 } 1463 1464 /** 1465 * Filters the login page errors. 1466 * 1467 * @since 3.6.0 1468 * 1469 * @param WP_Error $errors WP Error object. 1470 * @param string $redirect_to Redirect destination URL. 1471 */ 1472 $errors = apply_filters( 'wp_login_errors', $errors, $redirect_to ); 1473 1474 // Clear any stale cookies. 1475 if ( $reauth ) { 1476 wp_clear_auth_cookie(); 1477 } 1478 1479 // Obtain user from password reset cookie flow before clearing the cookie. 1480 $rp_cookie = 'wp-resetpass-' . COOKIEHASH; 1481 if ( isset( $_COOKIE[ $rp_cookie ] ) && is_string( $_COOKIE[ $rp_cookie ] ) ) { 1482 $user_login = sanitize_user( strtok( wp_unslash( $_COOKIE[ $rp_cookie ] ), ':' ) ); 1483 list( $rp_path ) = explode( '?', wp_unslash( $_SERVER['REQUEST_URI'] ) ); 1484 setcookie( $rp_cookie, ' ', time() - YEAR_IN_SECONDS, $rp_path, COOKIE_DOMAIN, is_ssl(), true ); 1485 } 1486 1487 login_header( __( 'Log In' ), '', $errors ); 1488 1489 if ( isset( $_POST['log'] ) ) { 1490 $user_login = ( 'incorrect_password' === $errors->get_error_code() || 'empty_password' === $errors->get_error_code() ) ? wp_unslash( $_POST['log'] ) : ''; 1491 } 1492 1493 $rememberme = ! empty( $_POST['rememberme'] ); 1494 1495 $aria_describedby = ''; 1496 $has_errors = $errors->has_errors(); 1497 1498 if ( $has_errors ) { 1499 $aria_describedby = ' aria-describedby="login_error"'; 1500 } 1501 1502 if ( $has_errors && 'message' === $errors->get_error_data() ) { 1503 $aria_describedby = ' aria-describedby="login-message"'; 1504 } 1505 1506 wp_enqueue_script( 'user-profile' ); 1507 wp_enqueue_script( 'wp-tooltip' ); 1508 ?> 1509 1510 <form name="loginform" id="loginform" action="<?php echo esc_url( site_url( 'wp-login.php', 'login_post' ) ); ?>" method="post"> 1511 <p> 1512 <label for="user_login"><?php _e( 'Username or Email Address' ); ?></label> 1513 <input type="text" name="log" id="user_login"<?php echo $aria_describedby; ?> class="input ltr" value="<?php echo esc_attr( $user_login ); ?>" size="20" autocapitalize="off" autocomplete="username" required="required" /> 1514 </p> 1515 1516 <div class="user-pass-wrap"> 1517 <label for="user_pass"><?php _e( 'Password' ); ?></label> 1518 <div class="wp-pwd"> 1519 <input type="password" name="pwd" id="user_pass"<?php echo $aria_describedby; ?> class="input password-input ltr" value="" size="20" autocomplete="current-password" spellcheck="false" required="required" /> 1520 <button type="button" class="button button-secondary wp-hide-pw hide-if-no-js" data-toggle="0" aria-label="<?php esc_attr_e( 'Show password' ); ?>"> 1521 <span class="dashicons dashicons-visibility" aria-hidden="true"></span> 1522 </button> 1523 </div> 1524 </div> 1525 <?php 1526 1527 /** 1528 * Fires following the 'Password' field in the login form. 1529 * 1530 * @since 2.1.0 1531 */ 1532 do_action( 'login_form' ); 1533 1534 ?> 1535 <?php 1536 /** 1537 * Filters the help text shown in the "Remember Me" tooltip on the login form. 1538 * 1539 * Returning an empty string removes the tooltip toggle from the form. 1540 * 1541 * @since 7.1.0 1542 * 1543 * @param string $rememberme_help_text The tooltip help text. 1544 */ 1545 $rememberme_help_text = apply_filters( 1546 'login_remember_me_help_text', 1547 __( 'Selecting "Remember Me" increases the length of time until you’re asked to log in again on this device. To keep your account secure, use this option only on your personal devices.' ) 1548 ); 1549 ?> 1550 <p class="forgetmenot"> 1551 <input name="rememberme" type="checkbox" id="rememberme" value="forever" <?php checked( $rememberme ); ?> /> 1552 <label for="rememberme"><?php esc_html_e( 'Remember Me' ); ?></label> 1553 <?php 1554 echo wp_get_toggletip( 1555 $rememberme_help_text, 1556 array( 1557 'id' => 'rememberme-help-toggletip', 1558 'label' => __( 'Help' ), 1559 ) 1560 ); 1561 ?> 1562 </p> 1563 <p class="submit"> 1564 <input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Log In' ); ?>" /> 1565 <?php 1566 1567 if ( $interim_login ) { 1568 ?> 1569 <input type="hidden" name="interim-login" value="1" /> 1570 <?php 1571 } else { 1572 ?> 1573 <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" /> 1574 <?php 1575 } 1576 1577 if ( $customize_login ) { 1578 ?> 1579 <input type="hidden" name="customize-login" value="1" /> 1580 <?php 1581 } 1582 1583 ?> 1584 <input type="hidden" name="testcookie" value="1" /> 1585 </p> 1586 </form> 1587 1588 <?php 1589 1590 if ( ! $interim_login ) { 1591 ?> 1592 <p id="nav"> 1593 <?php 1594 1595 if ( get_option( 'users_can_register' ) ) { 1596 $registration_url = sprintf( '<a class="wp-login-register" href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) ); 1597 1598 /** This filter is documented in wp-includes/general-template.php */ 1599 echo apply_filters( 'register', $registration_url ); 1600 1601 echo esc_html( $login_link_separator ); 1602 } 1603 1604 $html_link = sprintf( '<a class="wp-login-lost-password" href="%s">%s</a>', esc_url( wp_lostpassword_url() ), __( 'Lost your password?' ) ); 1605 1606 /** 1607 * Filters the link that allows the user to reset the lost password. 1608 * 1609 * @since 6.1.0 1610 * 1611 * @param string $html_link HTML link to the lost password form. 1612 */ 1613 echo apply_filters( 'lost_password_html_link', $html_link ); 1614 1615 ?> 1616 </p> 1617 <?php 1618 } 1619 1620 $login_script = 'function wp_attempt_focus() {'; 1621 $login_script .= 'setTimeout( function() {'; 1622 $login_script .= 'try {'; 1623 1624 if ( $user_login ) { 1625 $login_script .= 'd = document.getElementById( "user_pass" ); d.value = "";'; 1626 } else { 1627 $login_script .= 'd = document.getElementById( "user_login" );'; 1628 1629 if ( $errors->get_error_code() === 'invalid_username' ) { 1630 $login_script .= 'd.value = "";'; 1631 } 1632 } 1633 1634 $login_script .= 'd.focus(); d.select();'; 1635 $login_script .= '} catch( er ) {}'; 1636 $login_script .= '}, 200);'; 1637 $login_script .= "}\n"; // End of wp_attempt_focus(). 1638 1639 /** 1640 * Filters whether to print the call to `wp_attempt_focus()` on the login screen. 1641 * 1642 * @since 4.8.0 1643 * 1644 * @param bool $print Whether to print the function call. Default true. 1645 */ 1646 if ( apply_filters( 'enable_login_autofocus', true ) && ! $error ) { 1647 $login_script .= "wp_attempt_focus();\n"; 1648 } 1649 1650 // Run `wpOnload()` if defined. 1651 $login_script .= "if ( typeof wpOnload === 'function' ) { wpOnload() }"; 1652 1653 wp_print_inline_script_tag( $login_script ); 1654 1655 if ( $interim_login ) { 1656 ob_start(); 1657 ?> 1658 <script> 1659 ( function() { 1660 try { 1661 var i, links = document.getElementsByTagName( 'a' ); 1662 for ( i in links ) { 1663 if ( links[i].href ) { 1664 links[i].target = '_blank'; 1665 } 1666 } 1667 } catch( er ) {} 1668 }()); 1669 </script> 1670 <?php 1671 wp_print_inline_script_tag( wp_remove_surrounding_empty_script_tags( ob_get_clean() ) ); 1672 } 1673 1674 login_footer(); 1675 break; 1676 } // End action switch.
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Thu Oct 15 08:20:32 2026 | Cross-referenced by PHPXref |