[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/ -> wp-login.php (source)

   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 &lsaquo; %2$s &#8212; WordPress' ), $title, $login_title );
  77  
  78      if ( wp_is_recovery_mode() ) {
  79          /* translators: %s: Login screen title. */
  80          $login_title = sprintf( __( 'Recovery Mode &#8212; %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( '&larr; 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&#8217;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&#8217;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.


Generated : Thu Oct 15 08:20:32 2026 Cross-referenced by PHPXref