| [ 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 ( $interim_login ) { ?> 406 <input type="hidden" name="interim-login" value="1" /> 407 <?php } ?> 408 409 <?php if ( isset( $_GET['redirect_to'] ) && '' !== $_GET['redirect_to'] ) { ?> 410 <input type="hidden" name="redirect_to" value="<?php echo sanitize_url( $_GET['redirect_to'] ); ?>" /> 411 <?php } ?> 412 413 <?php if ( isset( $_GET['action'] ) && '' !== $_GET['action'] ) { ?> 414 <input type="hidden" name="action" value="<?php echo esc_attr( $_GET['action'] ); ?>" /> 415 <?php } ?> 416 417 <input type="submit" class="button" value="<?php esc_attr_e( 'Change' ); ?>"> 418 419 </form> 420 </div> 421 <?php } ?> 422 <?php } ?> 423 424 <?php 425 426 if ( ! empty( $input_id ) ) { 427 ob_start(); 428 ?> 429 <script> 430 try{document.getElementById('<?php echo $input_id; ?>').focus();}catch(e){} 431 if(typeof wpOnload==='function')wpOnload(); 432 </script> 433 <?php 434 wp_print_inline_script_tag( wp_remove_surrounding_empty_script_tags( ob_get_clean() ) ); 435 } 436 437 /** 438 * Fires in the login page footer. 439 * 440 * @since 3.1.0 441 */ 442 do_action( 'login_footer' ); 443 444 ?> 445 </body> 446 </html> 447 <?php 448 } 449 450 /** 451 * Outputs the JavaScript to handle the form shaking on the login page. 452 * 453 * @since 3.0.0 454 */ 455 function wp_shake_js() { 456 wp_print_inline_script_tag( "document.querySelector('form').classList.add('shake');" ); 457 } 458 459 /** 460 * Outputs the viewport meta tag for the login page. 461 * 462 * @since 3.7.0 463 */ 464 function wp_login_viewport_meta() { 465 ?> 466 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 467 <?php 468 } 469 470 /* 471 * Main part. 472 * 473 * Check the request and redirect or display a form based on the current action. 474 */ 475 476 $action = isset( $_REQUEST['action'] ) && is_string( $_REQUEST['action'] ) ? $_REQUEST['action'] : 'login'; 477 $errors = new WP_Error(); 478 479 if ( isset( $_GET['key'] ) ) { 480 $action = 'resetpass'; 481 } 482 483 if ( isset( $_GET['checkemail'] ) ) { 484 $action = 'checkemail'; 485 } 486 487 $default_actions = array( 488 'confirm_admin_email', 489 'postpass', 490 'logout', 491 'lostpassword', 492 'retrievepassword', 493 'resetpass', 494 'rp', 495 'register', 496 'checkemail', 497 'confirmaction', 498 'login', 499 WP_Recovery_Mode_Link_Service::LOGIN_ACTION_ENTERED, 500 ); 501 502 // Validate action so as to default to the login screen. 503 if ( ! in_array( $action, $default_actions, true ) && false === has_filter( 'login_form_' . $action ) ) { 504 $action = 'login'; 505 } 506 507 nocache_headers(); 508 509 header( 'Content-Type: ' . get_bloginfo( 'html_type' ) . '; charset=' . get_bloginfo( 'charset' ) ); 510 511 if ( defined( 'RELOCATE' ) && RELOCATE ) { // Move flag is set. 512 if ( isset( $_SERVER['PATH_INFO'] ) && ( $_SERVER['PATH_INFO'] !== $_SERVER['PHP_SELF'] ) ) { 513 $_SERVER['PHP_SELF'] = str_replace( $_SERVER['PATH_INFO'], '', $_SERVER['PHP_SELF'] ); 514 } 515 516 $url = dirname( set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] ) ); 517 518 if ( get_option( 'siteurl' ) !== $url ) { 519 update_option( 'siteurl', $url ); 520 } 521 } 522 523 // Set a cookie now to see if they are supported by the browser. 524 $secure = ( 'https' === parse_url( wp_login_url(), PHP_URL_SCHEME ) ); 525 setcookie( TEST_COOKIE, 'WP Cookie check', 0, COOKIEPATH, COOKIE_DOMAIN, $secure, true ); 526 527 if ( SITECOOKIEPATH !== COOKIEPATH ) { 528 setcookie( TEST_COOKIE, 'WP Cookie check', 0, SITECOOKIEPATH, COOKIE_DOMAIN, $secure, true ); 529 } 530 531 if ( isset( $_GET['wp_lang'] ) ) { 532 setcookie( 'wp_lang', sanitize_text_field( $_GET['wp_lang'] ), 0, COOKIEPATH, COOKIE_DOMAIN, $secure, true ); 533 } 534 535 /** 536 * Fires when the login form is initialized. 537 * 538 * @since 3.2.0 539 */ 540 do_action( 'login_init' ); 541 542 /** 543 * Fires before a specified login form action. 544 * 545 * The dynamic portion of the hook name, `$action`, refers to the action 546 * that brought the visitor to the login form. 547 * 548 * Possible hook names include: 549 * 550 * - `login_form_checkemail` 551 * - `login_form_confirm_admin_email` 552 * - `login_form_confirmaction` 553 * - `login_form_entered_recovery_mode` 554 * - `login_form_login` 555 * - `login_form_logout` 556 * - `login_form_lostpassword` 557 * - `login_form_postpass` 558 * - `login_form_register` 559 * - `login_form_resetpass` 560 * - `login_form_retrievepassword` 561 * - `login_form_rp` 562 * 563 * @since 2.8.0 564 */ 565 do_action( "login_form_{$action}" ); 566 567 $http_post = ( 'POST' === $_SERVER['REQUEST_METHOD'] ); 568 $interim_login = isset( $_REQUEST['interim-login'] ); 569 570 /** 571 * Filters the separator used between login form navigation links. 572 * 573 * @since 4.9.0 574 * 575 * @param string $login_link_separator The separator used between login form navigation links. 576 */ 577 $login_link_separator = apply_filters( 'login_link_separator', ' | ' ); 578 579 switch ( $action ) { 580 581 case 'confirm_admin_email': 582 /* 583 * Note that `is_user_logged_in()` will return false immediately after logging in 584 * as the current user is not set, see wp-includes/pluggable.php. 585 * However this action runs on a redirect after logging in. 586 */ 587 if ( ! is_user_logged_in() ) { 588 wp_safe_redirect( wp_login_url() ); 589 exit; 590 } 591 592 if ( ! empty( $_REQUEST['redirect_to'] ) ) { 593 $redirect_to = $_REQUEST['redirect_to']; 594 } else { 595 $redirect_to = admin_url(); 596 } 597 598 if ( current_user_can( 'manage_options' ) ) { 599 $admin_email = get_option( 'admin_email' ); 600 } else { 601 wp_safe_redirect( $redirect_to ); 602 exit; 603 } 604 605 /** 606 * Filters the interval for dismissing the admin email confirmation screen. 607 * 608 * If `0` (zero) is returned, the "Remind me later" link will not be displayed. 609 * 610 * @since 5.3.1 611 * 612 * @param int $interval Interval time (in seconds). Default is 3 days. 613 */ 614 $remind_interval = (int) apply_filters( 'admin_email_remind_interval', 3 * DAY_IN_SECONDS ); 615 616 if ( ! empty( $_GET['remind_me_later'] ) ) { 617 if ( ! wp_verify_nonce( $_GET['remind_me_later'], 'remind_me_later_nonce' ) ) { 618 wp_safe_redirect( wp_login_url() ); 619 exit; 620 } 621 622 if ( $remind_interval > 0 ) { 623 update_option( 'admin_email_lifespan', time() + $remind_interval ); 624 } 625 626 $redirect_to = add_query_arg( 'admin_email_remind_later', 1, $redirect_to ); 627 wp_safe_redirect( $redirect_to ); 628 exit; 629 } 630 631 if ( ! empty( $_POST['correct-admin-email'] ) ) { 632 if ( ! check_admin_referer( 'confirm_admin_email', 'confirm_admin_email_nonce' ) ) { 633 wp_safe_redirect( wp_login_url() ); 634 exit; 635 } 636 637 /** 638 * Filters the interval for redirecting the user to the admin email confirmation screen. 639 * 640 * If `0` (zero) is returned, the user will not be redirected. 641 * 642 * @since 5.3.0 643 * 644 * @param int $interval Interval time (in seconds). Default is 6 months. 645 */ 646 $admin_email_check_interval = (int) apply_filters( 'admin_email_check_interval', 6 * MONTH_IN_SECONDS ); 647 648 if ( $admin_email_check_interval > 0 ) { 649 update_option( 'admin_email_lifespan', time() + $admin_email_check_interval ); 650 } 651 652 wp_safe_redirect( $redirect_to ); 653 exit; 654 } 655 656 login_header( __( 'Confirm your administration email' ), '', $errors ); 657 658 /** 659 * Fires before the admin email confirm form. 660 * 661 * @since 5.3.0 662 * 663 * @param WP_Error $errors A `WP_Error` object containing any errors generated by using invalid 664 * credentials. Note that the error object may not contain any errors. 665 */ 666 do_action( 'admin_email_confirm', $errors ); 667 668 ?> 669 670 <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"> 671 <?php 672 /** 673 * Fires inside the admin-email-confirm-form form tags, before the hidden fields. 674 * 675 * @since 5.3.0 676 */ 677 do_action( 'admin_email_confirm_form' ); 678 679 wp_nonce_field( 'confirm_admin_email', 'confirm_admin_email_nonce' ); 680 681 ?> 682 <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" /> 683 684 <h1 class="admin-email__heading"> 685 <?php _e( 'Administration email verification' ); ?> 686 </h1> 687 <p class="admin-email__details"> 688 <?php _e( 'Please verify that the <strong>administration email</strong> for this website is still correct.' ); ?> 689 <?php 690 691 /* translators: URL to the WordPress help section about admin email. */ 692 $admin_email_help_url = __( 'https://wordpress.org/documentation/article/settings-general-screen/#email-address' ); 693 694 $accessibility_text = sprintf( 695 '<span class="screen-reader-text"> %s</span>', 696 /* translators: Hidden accessibility text. */ 697 __( '(opens in a new tab)' ) 698 ); 699 700 printf( 701 '<a href="%s" target="_blank">%s%s</a>', 702 esc_url( $admin_email_help_url ), 703 __( 'Why is this important?' ), 704 $accessibility_text 705 ); 706 707 ?> 708 </p> 709 <p class="admin-email__details"> 710 <?php 711 712 printf( 713 /* translators: %s: Admin email address. */ 714 __( 'Current administration email: %s' ), 715 '<strong>' . esc_html( $admin_email ) . '</strong>' 716 ); 717 718 ?> 719 </p> 720 <p class="admin-email__details"> 721 <?php _e( 'This email may be different from your personal email address.' ); ?> 722 </p> 723 724 <div class="admin-email__actions"> 725 <div class="admin-email__actions-primary"> 726 <?php 727 728 $change_link = admin_url( 'options-general.php' ); 729 $change_link = add_query_arg( 'highlight', 'confirm_admin_email', $change_link ); 730 731 ?> 732 <a class="button button-large" href="<?php echo esc_url( $change_link ); ?>"><?php _e( 'Update' ); ?></a> 733 <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' ); ?>" /> 734 </div> 735 <?php if ( $remind_interval > 0 ) : ?> 736 <div class="admin-email__actions-secondary"> 737 <?php 738 739 $remind_me_link = wp_login_url( $redirect_to ); 740 $remind_me_link = add_query_arg( 741 array( 742 'action' => 'confirm_admin_email', 743 'remind_me_later' => wp_create_nonce( 'remind_me_later_nonce' ), 744 ), 745 $remind_me_link 746 ); 747 748 ?> 749 <a href="<?php echo esc_url( $remind_me_link ); ?>"><?php _e( 'Remind me later' ); ?></a> 750 </div> 751 <?php endif; ?> 752 </div> 753 </form> 754 755 <?php 756 757 login_footer(); 758 break; 759 760 case 'postpass': 761 $redirect_to = $_POST['redirect_to'] ?? wp_get_referer(); 762 763 if ( ! isset( $_POST['post_password'] ) || ! is_string( $_POST['post_password'] ) ) { 764 wp_safe_redirect( $redirect_to ); 765 exit; 766 } 767 768 require_once ABSPATH . WPINC . '/class-phpass.php'; 769 $hasher = new PasswordHash( 8, true ); 770 771 /** 772 * Filters the life span of the post password cookie. 773 * 774 * By default, the cookie expires 10 days from creation. To turn this 775 * into a session cookie, return 0. 776 * 777 * @since 3.7.0 778 * 779 * @param int $expires The expiry time, as passed to setcookie(). 780 */ 781 $expire = apply_filters( 'post_password_expires', time() + 10 * DAY_IN_SECONDS ); 782 783 if ( $redirect_to ) { 784 $secure = ( 'https' === parse_url( $redirect_to, PHP_URL_SCHEME ) ); 785 } else { 786 $secure = false; 787 } 788 789 setcookie( 'wp-postpass_' . COOKIEHASH, $hasher->HashPassword( wp_unslash( $_POST['post_password'] ) ), $expire, COOKIEPATH, COOKIE_DOMAIN, $secure ); 790 791 wp_safe_redirect( $redirect_to ); 792 exit; 793 794 case 'logout': 795 check_admin_referer( 'log-out' ); 796 797 $user = wp_get_current_user(); 798 799 wp_logout(); 800 801 if ( ! empty( $_REQUEST['redirect_to'] ) && is_string( $_REQUEST['redirect_to'] ) ) { 802 $redirect_to = $_REQUEST['redirect_to']; 803 $requested_redirect_to = $redirect_to; 804 } else { 805 $redirect_to = add_query_arg( 806 array( 807 'loggedout' => 'true', 808 'wp_lang' => get_user_locale( $user ), 809 ), 810 wp_login_url() 811 ); 812 813 $requested_redirect_to = ''; 814 } 815 816 /** 817 * Filters the log out redirect URL. 818 * 819 * @since 4.2.0 820 * 821 * @param string $redirect_to The redirect destination URL. 822 * @param string $requested_redirect_to The requested redirect destination URL passed as a parameter. 823 * @param WP_User $user The WP_User object for the user that's logging out. 824 */ 825 $redirect_to = apply_filters( 'logout_redirect', $redirect_to, $requested_redirect_to, $user ); 826 827 wp_safe_redirect( $redirect_to ); 828 exit; 829 830 case 'lostpassword': 831 case 'retrievepassword': 832 if ( $http_post ) { 833 $errors = retrieve_password(); 834 835 if ( ! is_wp_error( $errors ) ) { 836 $redirect_to = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : 'wp-login.php?checkemail=confirm'; 837 wp_safe_redirect( $redirect_to ); 838 exit; 839 } 840 } 841 842 if ( isset( $_GET['error'] ) ) { 843 if ( 'invalidkey' === $_GET['error'] ) { 844 $errors->add( 'invalidkey', __( '<strong>Error:</strong> Your password reset link appears to be invalid. Please request a new link below.' ) ); 845 } elseif ( 'expiredkey' === $_GET['error'] ) { 846 $errors->add( 'expiredkey', __( '<strong>Error:</strong> Your password reset link has expired. Please request a new link below.' ) ); 847 } 848 } 849 850 $lostpassword_redirect = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : ''; 851 /** 852 * Filters the URL redirected to after submitting the lostpassword/retrievepassword form. 853 * 854 * @since 3.0.0 855 * 856 * @param string $lostpassword_redirect The redirect destination URL. 857 */ 858 $redirect_to = apply_filters( 'lostpassword_redirect', $lostpassword_redirect ); 859 860 /** 861 * Fires before the lost password form. 862 * 863 * @since 1.5.1 864 * @since 5.1.0 Added the `$errors` parameter. 865 * 866 * @param WP_Error $errors A `WP_Error` object containing any errors generated by using invalid 867 * credentials. Note that the error object may not contain any errors. 868 */ 869 do_action( 'lost_password', $errors ); 870 871 login_header( 872 __( 'Lost Password' ), 873 wp_get_admin_notice( 874 __( 'Please enter your username or email address. You will receive an email message with instructions on how to reset your password.' ), 875 array( 876 'type' => 'info', 877 'additional_classes' => array( 'message' ), 878 ) 879 ), 880 $errors 881 ); 882 883 $user_login = ''; 884 885 if ( isset( $_POST['user_login'] ) && is_string( $_POST['user_login'] ) ) { 886 $user_login = wp_unslash( $_POST['user_login'] ); 887 } 888 889 ?> 890 891 <form name="lostpasswordform" id="lostpasswordform" action="<?php echo esc_url( network_site_url( 'wp-login.php?action=lostpassword', 'login_post' ) ); ?>" method="post"> 892 <p> 893 <label for="user_login"><?php _e( 'Username or Email Address' ); ?></label> 894 <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" /> 895 </p> 896 <?php 897 898 /** 899 * Fires inside the lostpassword form tags, before the hidden fields. 900 * 901 * @since 2.1.0 902 */ 903 do_action( 'lostpassword_form' ); 904 905 ?> 906 <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" /> 907 <p class="submit"> 908 <input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Get New Password' ); ?>" /> 909 </p> 910 </form> 911 912 <p id="nav"> 913 <a class="wp-login-log-in" href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a> 914 <?php 915 916 if ( get_option( 'users_can_register' ) ) { 917 $registration_url = sprintf( '<a class="wp-login-register" href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) ); 918 919 echo esc_html( $login_link_separator ); 920 921 /** This filter is documented in wp-includes/general-template.php */ 922 echo apply_filters( 'register', $registration_url ); 923 } 924 925 ?> 926 </p> 927 <?php 928 929 login_footer( 'user_login' ); 930 break; 931 932 case 'resetpass': 933 case 'rp': 934 list( $rp_path ) = explode( '?', wp_unslash( $_SERVER['REQUEST_URI'] ) ); 935 $rp_cookie = 'wp-resetpass-' . COOKIEHASH; 936 937 if ( isset( $_GET['key'] ) && isset( $_GET['login'] ) ) { 938 $value = sprintf( '%s:%s', wp_unslash( $_GET['login'] ), wp_unslash( $_GET['key'] ) ); 939 setcookie( $rp_cookie, $value, 0, $rp_path, COOKIE_DOMAIN, is_ssl(), true ); 940 941 wp_safe_redirect( remove_query_arg( array( 'key', 'login' ) ) ); 942 exit; 943 } 944 945 if ( isset( $_COOKIE[ $rp_cookie ] ) && 0 < strpos( $_COOKIE[ $rp_cookie ], ':' ) ) { 946 list( $rp_login, $rp_key ) = explode( ':', wp_unslash( $_COOKIE[ $rp_cookie ] ), 2 ); 947 948 $user = check_password_reset_key( $rp_key, $rp_login ); 949 950 if ( isset( $_POST['pass1'] ) && ! hash_equals( $rp_key, $_POST['rp_key'] ) ) { 951 $user = false; 952 } 953 } else { 954 $user = false; 955 } 956 957 if ( ! $user || is_wp_error( $user ) ) { 958 setcookie( $rp_cookie, ' ', time() - YEAR_IN_SECONDS, $rp_path, COOKIE_DOMAIN, is_ssl(), true ); 959 960 if ( $user && $user->get_error_code() === 'expired_key' ) { 961 wp_redirect( site_url( 'wp-login.php?action=lostpassword&error=expiredkey' ) ); 962 } else { 963 wp_redirect( site_url( 'wp-login.php?action=lostpassword&error=invalidkey' ) ); 964 } 965 966 exit; 967 } 968 969 $errors = new WP_Error(); 970 971 // Check if password is one or all empty spaces. 972 if ( ! empty( $_POST['pass1'] ) ) { 973 $_POST['pass1'] = trim( $_POST['pass1'] ); 974 975 if ( empty( $_POST['pass1'] ) ) { 976 $errors->add( 'password_reset_empty_space', __( 'The password cannot be a space or all spaces.' ) ); 977 } 978 } 979 980 // Check if password fields do not match. 981 if ( ! empty( $_POST['pass1'] ) && trim( $_POST['pass2'] ) !== $_POST['pass1'] ) { 982 $errors->add( 'password_reset_mismatch', __( '<strong>Error:</strong> The passwords do not match.' ) ); 983 } 984 985 /** 986 * Fires before the password reset procedure is validated. 987 * 988 * @since 3.5.0 989 * 990 * @param WP_Error $errors WP Error object. 991 * @param WP_User|WP_Error $user WP_User object if the login and reset key match. WP_Error object otherwise. 992 */ 993 do_action( 'validate_password_reset', $errors, $user ); 994 995 if ( ( ! $errors->has_errors() ) && isset( $_POST['pass1'] ) && ! empty( $_POST['pass1'] ) ) { 996 reset_password( $user, $_POST['pass1'] ); 997 login_header( 998 __( 'Password Reset' ), 999 wp_get_admin_notice( 1000 __( 'Your password has been reset.' ) . ' <a href="' . esc_url( wp_login_url() ) . '">' . __( 'Log in' ) . '</a>', 1001 array( 1002 'type' => 'info', 1003 'additional_classes' => array( 'message', 'reset-pass' ), 1004 ) 1005 ) 1006 ); 1007 login_footer(); 1008 exit; 1009 } 1010 1011 wp_enqueue_script( 'utils' ); 1012 wp_enqueue_script( 'user-profile' ); 1013 1014 login_header( 1015 __( 'Reset Password' ), 1016 wp_get_admin_notice( 1017 __( 'Enter your new password below or generate one.' ), 1018 array( 1019 'type' => 'info', 1020 'additional_classes' => array( 'message', 'reset-pass' ), 1021 ) 1022 ), 1023 $errors 1024 ); 1025 1026 ?> 1027 <form name="resetpassform" id="resetpassform" action="<?php echo esc_url( network_site_url( 'wp-login.php?action=resetpass', 'login_post' ) ); ?>" method="post" autocomplete="off"> 1028 <input type="hidden" id="user_login" value="<?php echo esc_attr( $rp_login ); ?>" autocomplete="off" /> 1029 1030 <div class="user-pass1-wrap"> 1031 <p> 1032 <label for="pass1"><?php _e( 'New password' ); ?></label> 1033 </p> 1034 1035 <div class="wp-pwd"> 1036 <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" /> 1037 1038 <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' ); ?>"> 1039 <span class="dashicons dashicons-hidden" aria-hidden="true"></span> 1040 </button> 1041 <div id="pass-strength-result" class="hide-if-no-js" aria-live="polite"><?php _e( 'Strength indicator' ); ?></div> 1042 </div> 1043 <div class="pw-weak"> 1044 <input type="checkbox" name="pw_weak" id="pw-weak" class="pw-checkbox" /> 1045 <label for="pw-weak"><?php _e( 'Confirm use of weak password' ); ?></label> 1046 </div> 1047 </div> 1048 1049 <p class="user-pass2-wrap"> 1050 <label for="pass2"><?php _e( 'Confirm new password' ); ?></label> 1051 <input type="password" name="pass2" id="pass2" class="input" size="20" value="" autocomplete="new-password" spellcheck="false" /> 1052 </p> 1053 1054 <p class="description indicator-hint"><?php echo wp_get_password_hint(); ?></p> 1055 1056 <?php 1057 1058 /** 1059 * Fires following the 'Strength indicator' meter in the user password reset form. 1060 * 1061 * @since 3.9.0 1062 * 1063 * @param WP_User $user User object of the user whose password is being reset. 1064 */ 1065 do_action( 'resetpass_form', $user ); 1066 1067 ?> 1068 <input type="hidden" name="rp_key" value="<?php echo esc_attr( $rp_key ); ?>" /> 1069 <p class="submit reset-pass-submit"> 1070 <button type="button" class="button wp-generate-pw hide-if-no-js skip-aria-expanded"><?php _e( 'Generate Password' ); ?></button> 1071 <input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Save Password' ); ?>" /> 1072 </p> 1073 </form> 1074 1075 <p id="nav"> 1076 <a class="wp-login-log-in" href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a> 1077 <?php 1078 1079 if ( get_option( 'users_can_register' ) ) { 1080 $registration_url = sprintf( '<a class="wp-login-register" href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) ); 1081 1082 echo esc_html( $login_link_separator ); 1083 1084 /** This filter is documented in wp-includes/general-template.php */ 1085 echo apply_filters( 'register', $registration_url ); 1086 } 1087 1088 ?> 1089 </p> 1090 <?php 1091 1092 login_footer( 'pass1' ); 1093 break; 1094 1095 case 'register': 1096 if ( is_multisite() ) { 1097 /** 1098 * Filters the Multisite sign up URL. 1099 * 1100 * @since 3.0.0 1101 * 1102 * @param string $sign_up_url The sign up URL. 1103 */ 1104 wp_redirect( apply_filters( 'wp_signup_location', network_site_url( 'wp-signup.php' ) ) ); 1105 exit; 1106 } 1107 1108 if ( ! get_option( 'users_can_register' ) ) { 1109 wp_redirect( site_url( 'wp-login.php?registration=disabled' ) ); 1110 exit; 1111 } 1112 1113 $user_login = ''; 1114 $user_email = ''; 1115 1116 if ( $http_post ) { 1117 if ( isset( $_POST['user_login'] ) && is_string( $_POST['user_login'] ) ) { 1118 $user_login = wp_unslash( $_POST['user_login'] ); 1119 } 1120 1121 if ( isset( $_POST['user_email'] ) && is_string( $_POST['user_email'] ) ) { 1122 $user_email = wp_unslash( $_POST['user_email'] ); 1123 } 1124 1125 $errors = register_new_user( $user_login, $user_email ); 1126 1127 if ( ! is_wp_error( $errors ) ) { 1128 $redirect_to = ! empty( $_POST['redirect_to'] ) ? $_POST['redirect_to'] : 'wp-login.php?checkemail=registered'; 1129 wp_safe_redirect( $redirect_to ); 1130 exit; 1131 } 1132 } 1133 1134 $registration_redirect = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : ''; 1135 1136 /** 1137 * Filters the registration redirect URL. 1138 * 1139 * @since 3.0.0 1140 * @since 5.9.0 Added the `$errors` parameter. 1141 * 1142 * @param string $registration_redirect The redirect destination URL. 1143 * @param int|WP_Error $errors User id if registration was successful, 1144 * WP_Error object otherwise. 1145 */ 1146 $redirect_to = apply_filters( 'registration_redirect', $registration_redirect, $errors ); 1147 1148 login_header( 1149 __( 'Registration Form' ), 1150 wp_get_admin_notice( 1151 __( 'Register For This Site' ), 1152 array( 1153 'type' => 'info', 1154 'additional_classes' => array( 'message', 'register' ), 1155 ) 1156 ), 1157 $errors 1158 ); 1159 1160 ?> 1161 <form name="registerform" id="registerform" action="<?php echo esc_url( site_url( 'wp-login.php?action=register', 'login_post' ) ); ?>" method="post" novalidate="novalidate"> 1162 <p> 1163 <label for="user_login"><?php _e( 'Username' ); ?></label> 1164 <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" /> 1165 </p> 1166 <p> 1167 <label for="user_email"><?php _e( 'Email' ); ?></label> 1168 <input type="email" name="user_email" id="user_email" class="input" value="<?php echo esc_attr( $user_email ); ?>" size="25" autocomplete="email" required="required" /> 1169 </p> 1170 <?php 1171 1172 /** 1173 * Fires following the 'Email' field in the user registration form. 1174 * 1175 * @since 2.1.0 1176 */ 1177 do_action( 'register_form' ); 1178 1179 ?> 1180 <p id="reg_passmail"> 1181 <?php _e( 'Registration confirmation will be emailed to you.' ); ?> 1182 </p> 1183 <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" /> 1184 <p class="submit"> 1185 <input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Register' ); ?>" /> 1186 </p> 1187 </form> 1188 1189 <p id="nav"> 1190 <a class="wp-login-log-in" href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a> 1191 <?php 1192 1193 echo esc_html( $login_link_separator ); 1194 1195 $html_link = sprintf( '<a class="wp-login-lost-password" href="%s">%s</a>', esc_url( wp_lostpassword_url() ), __( 'Lost your password?' ) ); 1196 1197 /** This filter is documented in wp-login.php */ 1198 echo apply_filters( 'lost_password_html_link', $html_link ); 1199 1200 ?> 1201 </p> 1202 <?php 1203 1204 login_footer( 'user_login' ); 1205 break; 1206 1207 case 'checkemail': 1208 $redirect_to = admin_url(); 1209 $errors = new WP_Error(); 1210 1211 if ( 'confirm' === $_GET['checkemail'] ) { 1212 $errors->add( 1213 'confirm', 1214 sprintf( 1215 /* translators: %s: Link to the login page. */ 1216 __( 'Check your email for the confirmation link, then visit the <a href="%s">login page</a>.' ), 1217 esc_url( wp_login_url() ) 1218 ), 1219 'message' 1220 ); 1221 } elseif ( 'registered' === $_GET['checkemail'] ) { 1222 $errors->add( 1223 'registered', 1224 sprintf( 1225 /* translators: %s: Link to the login page. */ 1226 __( 'Registration complete. Please check your email, then visit the <a href="%s">login page</a>.' ), 1227 esc_url( wp_login_url() ) 1228 ), 1229 'message' 1230 ); 1231 } 1232 1233 /** This action is documented in wp-login.php */ 1234 $errors = apply_filters( 'wp_login_errors', $errors, $redirect_to ); 1235 1236 login_header( __( 'Check your email' ), '', $errors ); 1237 login_footer(); 1238 break; 1239 1240 case 'confirmaction': 1241 if ( ! isset( $_GET['request_id'] ) ) { 1242 wp_die( __( 'Missing request ID.' ) ); 1243 } 1244 1245 if ( ! isset( $_GET['confirm_key'] ) ) { 1246 wp_die( __( 'Missing confirm key.' ) ); 1247 } 1248 1249 $request_id = (int) $_GET['request_id']; 1250 $key = sanitize_text_field( wp_unslash( $_GET['confirm_key'] ) ); 1251 $result = wp_validate_user_request_key( $request_id, $key ); 1252 1253 if ( is_wp_error( $result ) ) { 1254 wp_die( $result ); 1255 } 1256 1257 /** 1258 * Fires an action hook when the account action has been confirmed by the user. 1259 * 1260 * Using this you can assume the user has agreed to perform the action by 1261 * clicking on the link in the confirmation email. 1262 * 1263 * After firing this action hook the page will redirect to wp-login a callback 1264 * redirects or exits first. 1265 * 1266 * @since 4.9.6 1267 * 1268 * @param int $request_id Request ID. 1269 */ 1270 do_action( 'user_request_action_confirmed', $request_id ); 1271 1272 $message = _wp_privacy_account_request_confirmed_message( $request_id ); 1273 1274 login_header( __( 'User action confirmed.' ), $message ); 1275 login_footer(); 1276 exit; 1277 1278 case 'login': 1279 default: 1280 $secure_cookie = ''; 1281 $customize_login = isset( $_REQUEST['customize-login'] ); 1282 1283 if ( $customize_login ) { 1284 wp_enqueue_script( 'customize-base' ); 1285 } 1286 1287 // If the user wants SSL but the session is not SSL, force a secure cookie. 1288 if ( ! empty( $_POST['log'] ) && ! force_ssl_admin() ) { 1289 $user_name = sanitize_user( wp_unslash( $_POST['log'] ) ); 1290 $user = get_user_by( 'login', $user_name ); 1291 1292 if ( ! $user && strpos( $user_name, '@' ) ) { 1293 $user = get_user_by( 'email', $user_name ); 1294 } 1295 1296 if ( $user ) { 1297 if ( get_user_option( 'use_ssl', $user->ID ) ) { 1298 $secure_cookie = true; 1299 force_ssl_admin( true ); 1300 } 1301 } 1302 } 1303 1304 if ( isset( $_REQUEST['redirect_to'] ) && is_string( $_REQUEST['redirect_to'] ) ) { 1305 $redirect_to = $_REQUEST['redirect_to']; 1306 // Redirect to HTTPS if user wants SSL. 1307 if ( $secure_cookie && str_contains( $redirect_to, 'wp-admin' ) ) { 1308 $redirect_to = preg_replace( '|^http://|', 'https://', $redirect_to ); 1309 } 1310 } else { 1311 $redirect_to = admin_url(); 1312 } 1313 1314 $reauth = ! empty( $_REQUEST['reauth'] ); 1315 1316 $user = wp_signon( array(), $secure_cookie ); 1317 1318 if ( empty( $_COOKIE[ LOGGED_IN_COOKIE ] ) ) { 1319 if ( headers_sent() ) { 1320 $user = new WP_Error( 1321 'test_cookie', 1322 sprintf( 1323 /* translators: 1: Browser cookie documentation URL, 2: Support forums URL. */ 1324 __( '<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>.' ), 1325 __( 'https://developer.wordpress.org/advanced-administration/wordpress/cookies/' ), 1326 __( 'https://wordpress.org/support/forums/' ) 1327 ) 1328 ); 1329 } elseif ( isset( $_POST['testcookie'] ) && empty( $_COOKIE[ TEST_COOKIE ] ) ) { 1330 // If cookies are disabled, the user can't log in even with a valid username and password. 1331 $user = new WP_Error( 1332 'test_cookie', 1333 sprintf( 1334 /* translators: %s: Browser cookie documentation URL. */ 1335 __( '<strong>Error:</strong> Cookies are blocked or not supported by your browser. You must <a href="%s">enable cookies</a> to use WordPress.' ), 1336 __( 'https://developer.wordpress.org/advanced-administration/wordpress/cookies/#enable-cookies-in-your-browser' ) 1337 ) 1338 ); 1339 } 1340 } 1341 1342 $requested_redirect_to = isset( $_REQUEST['redirect_to'] ) && is_string( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : ''; 1343 1344 /** 1345 * Filters the login redirect URL. 1346 * 1347 * @since 3.0.0 1348 * 1349 * @param string $redirect_to The redirect destination URL. 1350 * @param string $requested_redirect_to The requested redirect destination URL passed as a parameter. 1351 * @param WP_User|WP_Error $user WP_User object if login was successful, WP_Error object otherwise. 1352 */ 1353 $redirect_to = apply_filters( 'login_redirect', $redirect_to, $requested_redirect_to, $user ); 1354 1355 if ( ! is_wp_error( $user ) && ! $reauth ) { 1356 if ( $interim_login ) { 1357 $message = '<p class="message">' . __( 'You have logged in successfully.' ) . '</p>'; 1358 $interim_login = 'success'; 1359 login_header( '', $message ); 1360 1361 ?> 1362 </div> 1363 <?php 1364 1365 /** This action is documented in wp-login.php */ 1366 do_action( 'login_footer' ); 1367 1368 if ( $customize_login ) { 1369 ob_start(); 1370 ?> 1371 <script>setTimeout( function(){ new wp.customize.Messenger({ url: '<?php echo wp_customize_url(); ?>', channel: 'login' }).send('login') }, 1000 );</script> 1372 <?php 1373 wp_print_inline_script_tag( wp_remove_surrounding_empty_script_tags( ob_get_clean() ) ); 1374 } 1375 1376 ?> 1377 </body></html> 1378 <?php 1379 1380 exit; 1381 } 1382 1383 // Check if it is time to add a redirect to the admin email confirmation screen. 1384 if ( $user instanceof WP_User && $user->exists() && $user->has_cap( 'manage_options' ) ) { 1385 $admin_email_lifespan = (int) get_option( 'admin_email_lifespan' ); 1386 1387 /* 1388 * If `0` (or anything "falsey" as it is cast to int) is returned, the user will not be redirected 1389 * to the admin email confirmation screen. 1390 */ 1391 /** This filter is documented in wp-login.php */ 1392 $admin_email_check_interval = (int) apply_filters( 'admin_email_check_interval', 6 * MONTH_IN_SECONDS ); 1393 1394 if ( $admin_email_check_interval > 0 && time() > $admin_email_lifespan ) { 1395 $redirect_to = add_query_arg( 1396 array( 1397 'action' => 'confirm_admin_email', 1398 'wp_lang' => get_user_locale( $user ), 1399 ), 1400 wp_login_url( $redirect_to ) 1401 ); 1402 } 1403 } 1404 1405 if ( ( empty( $redirect_to ) || 'wp-admin/' === $redirect_to || admin_url() === $redirect_to ) ) { 1406 // 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. 1407 if ( is_multisite() && ! get_active_blog_for_user( $user->ID ) && ! is_super_admin( $user->ID ) ) { 1408 $redirect_to = user_admin_url(); 1409 } elseif ( is_multisite() && ! $user->has_cap( 'read' ) ) { 1410 $redirect_to = get_dashboard_url( $user->ID ); 1411 } elseif ( ! $user->has_cap( 'edit_posts' ) ) { 1412 $redirect_to = $user->has_cap( 'read' ) ? admin_url( 'profile.php' ) : home_url(); 1413 } 1414 1415 wp_redirect( $redirect_to ); 1416 exit; 1417 } 1418 1419 wp_safe_redirect( $redirect_to ); 1420 exit; 1421 } 1422 1423 $errors = $user; 1424 // Clear errors if loggedout is set. 1425 if ( ! empty( $_GET['loggedout'] ) || $reauth ) { 1426 $errors = new WP_Error(); 1427 } 1428 1429 if ( empty( $_POST ) && $errors->get_error_codes() === array( 'empty_username', 'empty_password' ) ) { 1430 $errors = new WP_Error( '', '' ); 1431 } 1432 1433 if ( $interim_login ) { 1434 if ( ! $errors->has_errors() ) { 1435 $errors->add( 'expired', __( 'Your session has expired. Please log in to continue where you left off.' ), 'message' ); 1436 } 1437 } else { 1438 // Some parts of this script use the main login form to display a message. 1439 if ( isset( $_GET['loggedout'] ) && $_GET['loggedout'] ) { 1440 $errors->add( 'loggedout', __( 'You are now logged out.' ), 'message' ); 1441 } elseif ( isset( $_GET['registration'] ) && 'disabled' === $_GET['registration'] ) { 1442 $errors->add( 'registerdisabled', __( '<strong>Error:</strong> User registration is currently not allowed.' ) ); 1443 } elseif ( str_contains( $redirect_to, 'about.php?updated' ) ) { 1444 $errors->add( 'updated', __( '<strong>You have successfully updated WordPress!</strong> Please log back in to see what’s new.' ), 'message' ); 1445 } elseif ( WP_Recovery_Mode_Link_Service::LOGIN_ACTION_ENTERED === $action ) { 1446 $errors->add( 'enter_recovery_mode', __( 'Recovery Mode Initialized. Please log in to continue.' ), 'message' ); 1447 } elseif ( isset( $_GET['redirect_to'] ) && is_string( $_GET['redirect_to'] ) 1448 && str_contains( $_GET['redirect_to'], 'wp-admin/authorize-application.php' ) 1449 ) { 1450 $query_component = wp_parse_url( $_GET['redirect_to'], PHP_URL_QUERY ); 1451 $query = array(); 1452 if ( $query_component ) { 1453 parse_str( $query_component, $query ); 1454 } 1455 1456 if ( ! empty( $query['app_name'] ) ) { 1457 /* translators: 1: Website name, 2: Application name. */ 1458 $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>' ); 1459 } else { 1460 /* translators: %s: Website name. */ 1461 $message = sprintf( __( 'Please log in to %s to proceed with authorization.' ), get_bloginfo( 'name', 'display' ) ); 1462 } 1463 1464 $errors->add( 'authorize_application', $message, 'message' ); 1465 } 1466 } 1467 1468 /** 1469 * Filters the login page errors. 1470 * 1471 * @since 3.6.0 1472 * 1473 * @param WP_Error $errors WP Error object. 1474 * @param string $redirect_to Redirect destination URL. 1475 */ 1476 $errors = apply_filters( 'wp_login_errors', $errors, $redirect_to ); 1477 1478 // Clear any stale cookies. 1479 if ( $reauth ) { 1480 wp_clear_auth_cookie(); 1481 } 1482 1483 // Obtain user from password reset cookie flow before clearing the cookie. 1484 $rp_cookie = 'wp-resetpass-' . COOKIEHASH; 1485 if ( isset( $_COOKIE[ $rp_cookie ] ) && is_string( $_COOKIE[ $rp_cookie ] ) ) { 1486 $user_login = sanitize_user( strtok( wp_unslash( $_COOKIE[ $rp_cookie ] ), ':' ) ); 1487 list( $rp_path ) = explode( '?', wp_unslash( $_SERVER['REQUEST_URI'] ) ); 1488 setcookie( $rp_cookie, ' ', time() - YEAR_IN_SECONDS, $rp_path, COOKIE_DOMAIN, is_ssl(), true ); 1489 } 1490 1491 login_header( __( 'Log In' ), '', $errors ); 1492 1493 if ( isset( $_POST['log'] ) ) { 1494 $user_login = ( 'incorrect_password' === $errors->get_error_code() || 'empty_password' === $errors->get_error_code() ) ? wp_unslash( $_POST['log'] ) : ''; 1495 } 1496 1497 $rememberme = ! empty( $_POST['rememberme'] ); 1498 1499 $aria_describedby = ''; 1500 $has_errors = $errors->has_errors(); 1501 1502 if ( $has_errors ) { 1503 $aria_describedby = ' aria-describedby="login_error"'; 1504 } 1505 1506 if ( $has_errors && 'message' === $errors->get_error_data() ) { 1507 $aria_describedby = ' aria-describedby="login-message"'; 1508 } 1509 1510 wp_enqueue_script( 'user-profile' ); 1511 wp_enqueue_script( 'wp-tooltip' ); 1512 ?> 1513 1514 <form name="loginform" id="loginform" action="<?php echo esc_url( site_url( 'wp-login.php', 'login_post' ) ); ?>" method="post"> 1515 <p> 1516 <label for="user_login"><?php _e( 'Username or Email Address' ); ?></label> 1517 <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" /> 1518 </p> 1519 1520 <div class="user-pass-wrap"> 1521 <label for="user_pass"><?php _e( 'Password' ); ?></label> 1522 <div class="wp-pwd"> 1523 <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" /> 1524 <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' ); ?>"> 1525 <span class="dashicons dashicons-visibility" aria-hidden="true"></span> 1526 </button> 1527 </div> 1528 </div> 1529 <?php 1530 1531 /** 1532 * Fires following the 'Password' field in the login form. 1533 * 1534 * @since 2.1.0 1535 */ 1536 do_action( 'login_form' ); 1537 1538 ?> 1539 <?php 1540 /** 1541 * Filters the help text shown in the "Remember Me" tooltip on the login form. 1542 * 1543 * Returning an empty string removes the tooltip toggle from the form. 1544 * 1545 * @since 7.1.0 1546 * 1547 * @param string $rememberme_help_text The tooltip help text. 1548 */ 1549 $rememberme_help_text = apply_filters( 1550 'login_remember_me_help_text', 1551 __( '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.' ) 1552 ); 1553 ?> 1554 <p class="forgetmenot"> 1555 <input name="rememberme" type="checkbox" id="rememberme" value="forever" <?php checked( $rememberme ); ?> /> 1556 <label for="rememberme"><?php esc_html_e( 'Remember Me' ); ?></label> 1557 <?php 1558 echo wp_get_toggletip( 1559 $rememberme_help_text, 1560 array( 1561 'id' => 'rememberme-help-toggletip', 1562 'label' => __( 'Help' ), 1563 ) 1564 ); 1565 ?> 1566 </p> 1567 <p class="submit"> 1568 <input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Log In' ); ?>" /> 1569 <?php 1570 1571 if ( $interim_login ) { 1572 ?> 1573 <input type="hidden" name="interim-login" value="1" /> 1574 <?php 1575 } else { 1576 ?> 1577 <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" /> 1578 <?php 1579 } 1580 1581 if ( $customize_login ) { 1582 ?> 1583 <input type="hidden" name="customize-login" value="1" /> 1584 <?php 1585 } 1586 1587 ?> 1588 <input type="hidden" name="testcookie" value="1" /> 1589 </p> 1590 </form> 1591 1592 <?php 1593 1594 if ( ! $interim_login ) { 1595 ?> 1596 <p id="nav"> 1597 <?php 1598 1599 if ( get_option( 'users_can_register' ) ) { 1600 $registration_url = sprintf( '<a class="wp-login-register" href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) ); 1601 1602 /** This filter is documented in wp-includes/general-template.php */ 1603 echo apply_filters( 'register', $registration_url ); 1604 1605 echo esc_html( $login_link_separator ); 1606 } 1607 1608 $html_link = sprintf( '<a class="wp-login-lost-password" href="%s">%s</a>', esc_url( wp_lostpassword_url() ), __( 'Lost your password?' ) ); 1609 1610 /** 1611 * Filters the link that allows the user to reset the lost password. 1612 * 1613 * @since 6.1.0 1614 * 1615 * @param string $html_link HTML link to the lost password form. 1616 */ 1617 echo apply_filters( 'lost_password_html_link', $html_link ); 1618 1619 ?> 1620 </p> 1621 <?php 1622 } 1623 1624 $login_script = 'function wp_attempt_focus() {'; 1625 $login_script .= 'setTimeout( function() {'; 1626 $login_script .= 'try {'; 1627 1628 if ( $user_login ) { 1629 $login_script .= 'd = document.getElementById( "user_pass" ); d.value = "";'; 1630 } else { 1631 $login_script .= 'd = document.getElementById( "user_login" );'; 1632 1633 if ( $errors->get_error_code() === 'invalid_username' ) { 1634 $login_script .= 'd.value = "";'; 1635 } 1636 } 1637 1638 $login_script .= 'd.focus(); d.select();'; 1639 $login_script .= '} catch( er ) {}'; 1640 $login_script .= '}, 200);'; 1641 $login_script .= "}\n"; // End of wp_attempt_focus(). 1642 1643 /** 1644 * Filters whether to print the call to `wp_attempt_focus()` on the login screen. 1645 * 1646 * @since 4.8.0 1647 * 1648 * @param bool $print Whether to print the function call. Default true. 1649 */ 1650 if ( apply_filters( 'enable_login_autofocus', true ) && ! $error ) { 1651 $login_script .= "wp_attempt_focus();\n"; 1652 } 1653 1654 // Run `wpOnload()` if defined. 1655 $login_script .= "if ( typeof wpOnload === 'function' ) { wpOnload() }"; 1656 1657 wp_print_inline_script_tag( $login_script ); 1658 1659 if ( $interim_login ) { 1660 ob_start(); 1661 ?> 1662 <script> 1663 ( function() { 1664 try { 1665 var i, links = document.getElementsByTagName( 'a' ); 1666 for ( i in links ) { 1667 if ( links[i].href ) { 1668 links[i].target = '_blank'; 1669 } 1670 } 1671 } catch( er ) {} 1672 }()); 1673 </script> 1674 <?php 1675 wp_print_inline_script_tag( wp_remove_surrounding_empty_script_tags( ob_get_clean() ) ); 1676 } 1677 1678 login_footer(); 1679 break; 1680 } // End action switch.
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Sun Aug 16 08:20:24 2026 | Cross-referenced by PHPXref |