[ 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 ( $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                      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                      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&#8217;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" reduces the number of times you&#8217;ll be asked to log in using 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.


Generated : Fri Jul 17 08:20:15 2026 Cross-referenced by PHPXref